/* Server for socket ops Copyright (C) 1995, 1997, 2013 Free Software Foundation, Inc. Written by Miles Bader 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 #include #include /* 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 pthread_spinlock_t sock_server_active_lock = PTHREAD_SPINLOCK_INITIALIZER; #include "io_S.h" #include "socket_S.h" #include "../libports/interrupt_S.h" #include "../libports/notify_S.h" /* A demuxer for socket operations. */ static int sock_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) { mig_routine_t routine; if ((routine = io_server_routine (inp)) || (routine = socket_server_routine (inp)) || (routine = ports_interrupt_server_routine (inp)) || (routine = ports_notify_server_routine (inp))) { (*routine) (inp, outp); return TRUE; } else return FALSE; } /* Handle socket requests while there are sockets around. */ static void * handle_sock_requests (void *unused) { 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, 0); } /* The last service thread is about to exist; make this known. */ pthread_spin_lock (&sock_server_active_lock); sock_server_active = 0; pthread_spin_unlock (&sock_server_active_lock); /* Let the whole joke start once again. */ ports_enable_bucket (sock_port_bucket); return NULL; } /* 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 () { pthread_t thread; error_t err; pthread_spin_lock (&sock_server_active_lock); if (sock_server_active) pthread_spin_unlock (&sock_server_active_lock); else { sock_server_active = 1; pthread_spin_unlock (&sock_server_active_lock); err = pthread_create (&thread, NULL, handle_sock_requests, NULL); if (!err) pthread_detach (thread); else { errno = err; perror ("pthread_create"); } } }