Back to index

glibc  2.9
sigwait.c
Go to the documentation of this file.
00001 /* Copyright (C) 1996,97,2001,02 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <errno.h>
00020 #include <hurd.h>
00021 #include <hurd/signal.h>
00022 #include <hurd/msg.h>
00023 #include <hurd/sigpreempt.h>
00024 #include <assert.h>
00025 
00026 /* Select any of pending signals from SET or wait for any to arrive.  */
00027 int
00028 __sigwait (const sigset_t *set, int *sig)
00029 {
00030   struct hurd_sigstate *ss;
00031   sigset_t mask, ready;
00032   int signo = 0;
00033   struct hurd_signal_preemptor preemptor;
00034   jmp_buf buf;
00035   mach_port_t wait;
00036   mach_msg_header_t msg;
00037 
00038   sighandler_t
00039     preempt_fun (struct hurd_signal_preemptor *pe,
00040                struct hurd_sigstate *ss,
00041                int *sigp,
00042                struct hurd_signal_detail *detail)
00043     {
00044       if (signo)
00045        /* We've already been run; don't interfere. */
00046        return SIG_ERR;
00047 
00048       signo = *sigp;
00049 
00050       /* Make sure this is all kosher */
00051       assert (__sigismember (&mask, signo));
00052 
00053       /* Make sure this signal is unblocked */
00054       __sigdelset (&ss->blocked, signo);
00055 
00056       return pe->handler;
00057     }
00058 
00059   void
00060     handler (int sig)
00061     {
00062       assert (sig == signo);
00063       longjmp (buf, 1);
00064     }
00065 
00066   wait = __mach_reply_port ();
00067 
00068   if (set != NULL)
00069     /* Crash before locking */
00070     mask = *set;
00071   else
00072     __sigemptyset (&mask);
00073 
00074   ss = _hurd_self_sigstate ();
00075   __spin_lock (&ss->lock);
00076 
00077   /* See if one of these signals is currently pending.  */
00078   __sigandset (&ready, &ss->pending, &mask);
00079   if (! __sigisemptyset (&ready))
00080     {
00081       for (signo = 1; signo < NSIG; signo++)
00082        if (__sigismember (&ready, signo))
00083          {
00084            __sigdelset (&ready, signo);
00085            goto all_done;
00086          }
00087       /* Huh?  Where'd it go? */
00088       abort ();
00089     }
00090 
00091   /* Wait for one of them to show up.  */
00092 
00093   if (!setjmp (buf))
00094     {
00095       /* Make the preemptor */
00096       preemptor.signals = mask;
00097       preemptor.first = 0;
00098       preemptor.last = -1;
00099       preemptor.preemptor = preempt_fun;
00100       preemptor.handler = handler;
00101 
00102       /* Install this preemptor */
00103       preemptor.next = ss->preemptors;
00104       ss->preemptors = &preemptor;
00105 
00106       __spin_unlock (&ss->lock);
00107 
00108       /* Wait. */
00109       __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
00110                 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
00111       abort ();
00112     }
00113   else
00114     {
00115       assert (signo);
00116 
00117       __spin_lock (&ss->lock);
00118 
00119       /* Delete our preemptor. */
00120       assert (ss->preemptors == &preemptor);
00121       ss->preemptors = preemptor.next;
00122     }
00123 
00124 
00125 all_done:
00126   spin_unlock (&ss->lock);
00127 
00128   __mach_port_destroy (__mach_task_self (), wait);
00129   *sig = signo;
00130   return 0;
00131 }
00132 
00133 weak_alias (__sigwait, sigwait)