summaryrefslogtreecommitdiff
path: root/pflocal/sock.c
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1995-07-19 20:39:57 +0000
committerMiles Bader <miles@gnu.org>1995-07-19 20:39:57 +0000
commit194094fcfdadfaf5e7f40876e9b3fcc484144aa4 (patch)
treef8a09d68e25b73ef1f9dcba7b3d9f755d1601709 /pflocal/sock.c
parentf9578f921d081f56e2d1eb92b67678bef5243481 (diff)
Formerly sock.c.~10~
Diffstat (limited to 'pflocal/sock.c')
-rw-r--r--pflocal/sock.c126
1 files changed, 86 insertions, 40 deletions
diff --git a/pflocal/sock.c b/pflocal/sock.c
index 1ffac4c9..925f8187 100644
--- a/pflocal/sock.c
+++ b/pflocal/sock.c
@@ -20,14 +20,68 @@
#include <string.h> /* For bzero() */
-#include "pflocal.h"
+#include <cthreads.h>
+
#include "sock.h"
#include "pipe.h"
+
+/* ---------------------------------------------------------------- */
-/* We hold this lock before we lock two sockets at once, to prevent someone
- else trying to lock the same two sockets in the reverse order, resulting
- in a deadlock. */
-static struct mutex socket_pair_lock;
+/* A port bucket to handle SOCK_USERs and ADDRs. */
+static 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);
+ return socket_server (inp, outp) || io_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. */
+static 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));
+ }
+}
/* ---------------------------------------------------------------- */
@@ -109,6 +163,7 @@ sock_create (struct pipe_class *pipe_class, struct sock **sock)
if (! (pipe_class->flags & PIPE_CLASS_CONNECTIONLESS))
/* No data source yet. */
new->read_pipe->flags |= PIPE_BROKEN;
+ new->read_pipe->refs++;
new->refs = 0;
new->flags = 0;
@@ -155,7 +210,7 @@ sock_clone (struct sock *template, struct sock **sock)
/* ---------------------------------------------------------------- */
-struct port_class *sock_user_port_class = NULL;
+struct port_class *sock_user_port_class;
/* Get rid of a user reference to a socket. */
static void
@@ -169,18 +224,15 @@ clean_sock_user (void *vuser)
error_t
sock_create_port (struct sock *sock, mach_port_t *port)
{
- struct sock_user *user;
-
- if (sock_user_port_class == NULL)
- sock_user_port_class = ports_create_class (NULL, clean_sock_user);
-
- user =
- ports_allocate_port (pflocal_port_bucket,
+ struct sock_user *user =
+ ports_allocate_port (sock_port_bucket,
sizeof (struct sock_user), sock_user_port_class);
if (!user)
return ENOMEM;
+ ensure_sock_server ();
+
mutex_lock (&sock->lock);
sock->refs++;
mutex_unlock (&sock->lock);
@@ -202,7 +254,7 @@ struct addr
struct mutex lock;
};
-struct port_class *addr_port_class = NULL;
+struct port_class *addr_port_class;
/* Get rid of ADDR's socket's reference to it, in preparation for ADDR going
away. */
@@ -242,15 +294,14 @@ clean_addr (void *vaddr)
inline error_t
addr_create (struct addr **addr)
{
- if (addr_port_class == NULL)
- addr_port_class = ports_create_class (unbind_addr, clean_addr);
-
*addr =
- ports_allocate_port (pflocal_port_bucket,
+ ports_allocate_port (sock_port_bucket,
sizeof (struct addr), addr_port_class);
if (! *addr)
return ENOMEM;
+ ensure_sock_server ();
+
(*addr)->sock = NULL;
return 0;
}
@@ -347,26 +398,14 @@ sock_get_addr (struct sock *sock, struct addr **addr)
return err; /* XXX */
}
-
-/* If SOCK is a connected socket, returns a send right to SOCK's peer's
- address in ADDR_PORT. */
-error_t
-sock_get_write_addr_port (struct sock *sock, mach_port_t *addr_port)
-{
- error_t err = 0;
-
- mutex_lock (&sock->lock);
- if (sock->write_addr)
- *addr_port = ports_get_right (sock->write_addr);
- else
- err = ENOTCONN;
- mutex_unlock (&sock->lock);
-
- return err;
-}
/* ---------------------------------------------------------------- */
+/* We hold this lock before we lock two sockets at once, to prevent someone
+ else trying to lock the same two sockets in the reverse order, resulting
+ in a deadlock. */
+static struct mutex socket_pair_lock;
+
/* Connect SOCK1 and SOCK2. */
error_t
sock_connect (struct sock *sock1, struct sock *sock2)
@@ -382,15 +421,13 @@ sock_connect (struct sock *sock1, struct sock *sock2)
void connect (struct sock *wr, struct sock *rd)
{
- if ((wr->flags & SOCK_SHUTDOWN_WRITE)
- || (rd->flags & SOCK_SHUTDOWN_READ))
+ if (!( (wr->flags & SOCK_SHUTDOWN_WRITE)
+ || (rd->flags & SOCK_SHUTDOWN_READ)))
{
struct pipe *pipe = rd->read_pipe;
pipe_aquire (pipe);
pipe->flags &= ~PIPE_BROKEN; /* Not yet... */
wr->write_pipe = pipe;
- ensure_addr (rd, &wr->write_addr); /* XXXXXXXXXXX */
- ports_port_ref (wr->write_addr);
mutex_unlock (&pipe->lock);
}
}
@@ -479,9 +516,18 @@ sock_shutdown (struct sock *sock, unsigned flags)
/* ---------------------------------------------------------------- */
+error_t
+sock_global_init ()
+{
+ sock_port_bucket = ports_create_bucket ();
+ sock_user_port_class = ports_create_class (NULL, clean_sock_user);
+ addr_port_class = ports_create_class (unbind_addr, clean_addr);
+ return 0;
+}
+
/* Try to shutdown any active sockets, returning EBUSY if we can't. */
error_t
-sock_goaway (int flags)
+sock_global_shutdown (int flags)
{
/* XXX */
return 0;