summaryrefslogtreecommitdiff
path: root/pflocal/sserver.c
blob: 8d835a7cef237c92c33ee591ee0a5713e7284658 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* Server for socket ops

   Copyright (C) 1995 Free Software Foundation, Inc.

   Written by Miles Bader <miles@gnu.ai.mit.edu>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2, or (at
   your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */

#include <cthreads.h>

#include <hurd/ports.h>

#include "notify_S.h"

#include "debug.h"

/* A port bucket to handle SOCK_USERs and ADDRs.  */
struct port_bucket *sock_port_bucket;

/* ---------------------------------------------------------------- */

/* True if there are threads servicing sock requests.  */
static int sock_server_active = 0;
static spin_lock_t sock_server_active_lock = SPIN_LOCK_INITIALIZER;

/* A demuxer for socket operations.  */
static int
sock_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
{
  extern int socket_server (mach_msg_header_t *inp, mach_msg_header_t *outp);
  extern int io_server (mach_msg_header_t *inp, mach_msg_header_t *outp);
  extern int interrupt_server (mach_msg_header_t *, mach_msg_header_t *);
  extern int notify_server (mach_msg_header_t *, mach_msg_header_t *);
  return
    socket_server (inp, outp)
      || io_server (inp, outp)
      || interrupt_server (inp, outp)
      || notify_server (inp, outp);
}

/* Handle socket requests while there are sockets around.  */
static void
handle_sock_requests ()
{
  while (ports_count_bucket (sock_port_bucket) > 0)
    {
      ports_enable_bucket (sock_port_bucket);
      ports_manage_port_operations_multithread (sock_port_bucket, sock_demuxer,
						30*1000, 2*60*1000,
						1, MACH_PORT_NULL);
    }

  /* The last service thread is about to exist; make this known.  */
  spin_lock (&sock_server_active_lock);
  sock_server_active = 0;
  spin_unlock (&sock_server_active_lock);

  /* Let the whole joke start once again.  */
  ports_enable_bucket (sock_port_bucket);
}

/* Makes sure there are some request threads for sock operations, and starts
   a server if necessary.  This routine should be called *after* creating the
   port(s) which need server, as the server routine only operates while there
   are any ports.  */
void
ensure_sock_server ()
{
  spin_lock (&sock_server_active_lock);
  if (sock_server_active)
    spin_unlock (&sock_server_active_lock);
  else
    {
      sock_server_active = 1;
      spin_unlock (&sock_server_active_lock);
      cthread_detach (cthread_fork ((cthread_fn_t)handle_sock_requests,
				    (any_t)0));
    }
}

/* ---------------------------------------------------------------- */
/* Notify stubs.  */

error_t
do_mach_notify_no_senders (mach_port_t port, mach_port_mscount_t count)
{
  void *pi = ports_lookup_port (sock_port_bucket, port, 0);
debug (pi, "count: %lu, refs: %d",
       count, (pi ? ((struct port_info *)pi)->refcnt : 0));
  if (!pi)
    return EOPNOTSUPP;
  ports_no_senders (pi, count);
  ports_port_deref (pi);
  return 0;
}

error_t
do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name)
{
  return 0;
}

error_t
do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name)
{
  return 0;
}

error_t
do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t name)
{
  return 0;
}

error_t
do_mach_notify_send_once (mach_port_t notify)
{
  return 0;
}

error_t
do_mach_notify_dead_name (mach_port_t notify, mach_port_t deadport)
{
  return 0;
}