Back to index

glibc  2.9
sigtimedwait.c
Go to the documentation of this file.
00001 /* Copyright (C) 1997,1998,2000,2002,2003,2004, 2005 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 <signal.h>
00021 #include <string.h>
00022 
00023 #include <sysdep-cancel.h>
00024 #include <sys/syscall.h>
00025 #include <bp-checks.h>
00026 
00027 #ifdef __NR_rt_sigtimedwait
00028 
00029 static int
00030 do_sigtimedwait (const sigset_t *set, siginfo_t *info,
00031                const struct timespec *timeout)
00032 {
00033 #ifdef SIGCANCEL
00034   sigset_t tmpset;
00035   if (set != NULL
00036       && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
00037 # ifdef SIGSETXID
00038          || __builtin_expect (__sigismember (set, SIGSETXID), 0)
00039 # endif
00040          ))
00041     {
00042       /* Create a temporary mask without the bit for SIGCANCEL set.  */
00043       // We are not copying more than we have to.
00044       memcpy (&tmpset, set, _NSIG / 8);
00045       __sigdelset (&tmpset, SIGCANCEL);
00046 # ifdef SIGSETXID
00047       __sigdelset (&tmpset, SIGSETXID);
00048 # endif
00049       set = &tmpset;
00050     }
00051 #endif
00052 
00053     /* XXX The size argument hopefully will have to be changed to the
00054        real size of the user-level sigset_t.  */
00055   int result = INLINE_SYSCALL (rt_sigtimedwait, 4, CHECK_SIGSET (set),
00056                             CHECK_1 (info), timeout, _NSIG / 8);
00057 
00058   /* The kernel generates a SI_TKILL code in si_code in case tkill is
00059      used.  tkill is transparently used in raise().  Since having
00060      SI_TKILL as a code is useful in general we fold the results
00061      here.  */
00062   if (result != -1 && info != NULL && info->si_code == SI_TKILL)
00063     info->si_code = SI_USER;
00064 
00065   return result;
00066 }
00067 
00068 
00069 /* Return any pending signal or wait for one for the given time.  */
00070 int
00071 __sigtimedwait (set, info, timeout)
00072      const sigset_t *set;
00073      siginfo_t *info;
00074      const struct timespec *timeout;
00075 {
00076   if (SINGLE_THREAD_P)
00077     return do_sigtimedwait (set, info, timeout);
00078 
00079   int oldtype = LIBC_CANCEL_ASYNC ();
00080 
00081   /* XXX The size argument hopefully will have to be changed to the
00082      real size of the user-level sigset_t.  */
00083   int result = do_sigtimedwait (set, info, timeout);
00084 
00085   LIBC_CANCEL_RESET (oldtype);
00086 
00087   return result;
00088 }
00089 libc_hidden_def (__sigtimedwait)
00090 weak_alias (__sigtimedwait, sigtimedwait)
00091 #else
00092 # include <signal/sigtimedwait.c>
00093 #endif