Back to index

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