]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitid.c
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / sysdeps / linux / common / waitid.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Copyright (C) 2007 Erik Andersen <andersen@uclibc.org>
4  *
5  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
6  */
7
8 #include <features.h>
9
10 #if defined __USE_SVID || defined __USE_XOPEN
11 # include <string.h>
12 # include <sys/types.h>
13 # include <sys/wait.h>
14 # include <sys/syscall.h>
15
16 # ifdef __NR_waitid
17
18 #  ifdef __UCLIBC_HAS_THREADS_NATIVE__
19 #  include <sysdep-cancel.h>
20 #  else
21 #  define SINGLE_THREAD_P 1
22 #  endif
23
24 /* The waitid() POSIX interface takes 4 arguments, but the kernel function
25  * actually takes 5.  The fifth is a pointer to struct rusage.  Make sure
26  * we pass NULL rather than letting whatever was in the register bleed up.
27  */
28 #define __NR_waitid5 __NR_waitid
29 static __always_inline
30 _syscall5(int, waitid5, idtype_t, idtype, id_t, id, siginfo_t*, infop,
31                  int, options, struct rusage*, ru)
32 # endif
33
34 int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
35 {
36 # ifdef __NR_waitid
37  if (SINGLE_THREAD_P)
38                 return waitid5(idtype, id, infop, options, NULL);
39
40 #  ifdef __UCLIBC_HAS_THREADS_NATIVE__
41         int oldtype = LIBC_CANCEL_ASYNC ();
42         int result = waitid5(idtype, id, infop, options, NULL);
43         LIBC_CANCEL_RESET (oldtype);
44         return result;
45 #  endif
46
47 # elif defined __NR_waitpid
48         switch (idtype) {
49                 case P_PID:
50                         if (id <= 0)
51                                 goto invalid;
52                         break;
53                 case P_PGID:
54                         if (id < 0 || id == 1)
55                                 goto invalid;
56                         id = -id;
57                         break;
58                 case P_ALL:
59                         id = -1;
60                         break;
61                 default:
62                 invalid:
63                         __set_errno(EINVAL);
64                         return -1;
65         }
66
67         memset(infop, 0, sizeof *infop);
68         infop->si_pid = waitpid(id, &infop->si_status, options
69 #  ifdef WEXITED
70                                            &~ WEXITED
71 #  endif
72                                           );
73         if (infop->si_pid < 0)
74                 return infop->si_pid;
75         return 0;
76 # else
77  __set_errno(ENOSYS);
78  return -1;
79 # endif
80 }
81 #endif