]>
Commit | Line | Data |
---|---|---|
0ecb606c JJ |
1 | /* Copyright (C) 2006 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. | |
3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
15 | License along with the GNU C Library; if not, write to the Free | |
16 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
17 | 02111-1307 USA. */ | |
18 | ||
19 | /* We define a special synchronization primitive for AIO. POSIX | |
20 | conditional variables would be ideal but the pthread_cond_*wait | |
21 | operations do not return on EINTR. This is a requirement for | |
22 | correct aio_suspend and lio_listio implementations. */ | |
23 | ||
24 | #include <assert.h> | |
25 | #include <signal.h> | |
26 | #include <pthreadP.h> | |
27 | #include <lowlevellock.h> | |
28 | ||
29 | #define DONT_NEED_GAI_MISC_COND 1 | |
30 | ||
31 | #define GAI_MISC_NOTIFY(waitlist) \ | |
32 | do { \ | |
33 | if (*waitlist->counterp > 0 && --*waitlist->counterp == 0) \ | |
34 | lll_futex_wake (waitlist->counterp, 1); \ | |
35 | } while (0) | |
36 | ||
37 | #define GAI_MISC_WAIT(result, futex, timeout, cancel) \ | |
38 | do { \ | |
39 | volatile int *futexaddr = &futex; \ | |
40 | int oldval = futex; \ | |
41 | \ | |
42 | if (oldval != 0) \ | |
43 | { \ | |
44 | pthread_mutex_unlock (&__gai_requests_mutex); \ | |
45 | \ | |
46 | int oldtype; \ | |
47 | if (cancel) \ | |
48 | oldtype = LIBC_CANCEL_ASYNC (); \ | |
49 | \ | |
50 | int status; \ | |
51 | do \ | |
52 | { \ | |
53 | status = lll_futex_timed_wait (futexaddr, oldval, timeout); \ | |
54 | if (status != -EWOULDBLOCK) \ | |
55 | break; \ | |
56 | \ | |
57 | oldval = *futexaddr; \ | |
58 | } \ | |
59 | while (oldval != 0); \ | |
60 | \ | |
61 | if (cancel) \ | |
62 | LIBC_CANCEL_RESET (oldtype); \ | |
63 | \ | |
64 | if (status == -EINTR) \ | |
65 | result = EINTR; \ | |
66 | else if (status == -ETIMEDOUT) \ | |
67 | result = EAGAIN; \ | |
68 | else \ | |
69 | assert (status == 0 || status == -EWOULDBLOCK); \ | |
70 | \ | |
71 | pthread_mutex_lock (&__gai_requests_mutex); \ | |
72 | } \ | |
73 | } while (0) | |
74 | ||
75 | ||
76 | #define gai_start_notify_thread __gai_start_notify_thread | |
77 | #define gai_create_helper_thread __gai_create_helper_thread | |
78 | ||
79 | extern inline void | |
80 | __gai_start_notify_thread (void) | |
81 | { | |
82 | sigset_t ss; | |
83 | sigemptyset (&ss); | |
84 | INTERNAL_SYSCALL_DECL (err); | |
85 | INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); | |
86 | } | |
87 | ||
88 | extern inline int | |
89 | __gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), | |
90 | void *arg) | |
91 | { | |
92 | pthread_attr_t attr; | |
93 | ||
94 | /* Make sure the thread is created detached. */ | |
95 | pthread_attr_init (&attr); | |
96 | pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); | |
97 | ||
98 | /* The helper thread needs only very little resources. */ | |
99 | (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); | |
100 | ||
101 | /* Block all signals in the helper thread. To do this thoroughly we | |
102 | temporarily have to block all signals here. */ | |
103 | sigset_t ss; | |
104 | sigset_t oss; | |
105 | sigfillset (&ss); | |
106 | INTERNAL_SYSCALL_DECL (err); | |
107 | INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); | |
108 | ||
109 | int ret = pthread_create (threadp, &attr, tf, arg); | |
110 | ||
111 | /* Restore the signal mask. */ | |
112 | INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, | |
113 | _NSIG / 8); | |
114 | ||
115 | (void) pthread_attr_destroy (&attr); | |
116 | return ret; | |
117 | } | |
118 | ||
119 | #include_next <gai_misc.h> |