blob: c8115f9a596bb73dd3c08304e709f44c81e4b36b [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/* 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
29static __always_inline
30_syscall5(int, waitid5, idtype_t, idtype, id_t, id, siginfo_t*, infop,
31 int, options, struct rusage*, ru)
32# endif
33
34int 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