]>
Commit | Line | Data |
---|---|---|
cbdee279 | 1 | /* Suspend until termination of a requests. |
8f480b4b RM |
2 | Copyright (C) 1997,1998,1999,2000,2002,2003,2005 |
3 | Free Software Foundation, Inc. | |
cbdee279 UD |
4 | This file is part of the GNU C Library. |
5 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. | |
6 | ||
7 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
8 | modify it under the terms of the GNU Lesser General Public |
9 | License as published by the Free Software Foundation; either | |
10 | version 2.1 of the License, or (at your option) any later version. | |
cbdee279 UD |
11 | |
12 | The GNU C Library is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 15 | Lesser General Public License for more details. |
cbdee279 | 16 | |
41bdb6e2 AJ |
17 | You should have received a copy of the GNU Lesser General Public |
18 | License along with the GNU C Library; if not, write to the Free | |
19 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
20 | 02111-1307 USA. */ | |
cbdee279 UD |
21 | |
22 | ||
23 | /* We use an UGLY hack to prevent gcc from finding us cheating. The | |
f14811c7 | 24 | implementations of aio_suspend and aio_suspend64 are identical and so |
cbdee279 UD |
25 | we want to avoid code duplication by using aliases. But gcc sees |
26 | the different parameter lists and prints a warning. We define here | |
27 | a function so that aio_suspend64 has no prototype. */ | |
28 | #define aio_suspend64 XXX | |
29 | #include <aio.h> | |
30 | /* And undo the hack. */ | |
31 | #undef aio_suspend64 | |
32 | ||
8b8cc76f | 33 | #include <assert.h> |
cbdee279 | 34 | #include <errno.h> |
c547b58a | 35 | #include <stdbool.h> |
3d8e9510 | 36 | #include <stdlib.h> |
f14811c7 | 37 | #include <sys/time.h> |
cbdee279 | 38 | |
60d73a7a | 39 | #include <bits/libc-lock.h> |
8f480b4b | 40 | #include <aio_misc.h> |
cbdee279 UD |
41 | |
42 | ||
60d73a7a UD |
43 | struct clparam |
44 | { | |
45 | const struct aiocb *const *list; | |
46 | struct waitlist *waitlist; | |
47 | struct requestlist **requestlist; | |
48 | pthread_cond_t *cond; | |
49 | int nent; | |
50 | }; | |
51 | ||
52 | ||
53 | static void | |
54 | cleanup (void *arg) | |
55 | { | |
56 | const struct clparam *param = (const struct clparam *) arg; | |
57 | ||
58 | /* Now remove the entry in the waiting list for all requests | |
59 | which didn't terminate. */ | |
60 | int cnt = param->nent; | |
61 | while (cnt-- > 0) | |
62 | if (param->list[cnt] != NULL | |
63 | && param->list[cnt]->__error_code == EINPROGRESS) | |
64 | { | |
65 | struct waitlist **listp; | |
66 | ||
67 | assert (param->requestlist[cnt] != NULL); | |
68 | ||
69 | /* There is the chance that we cannot find our entry anymore. This | |
70 | could happen if the request terminated and restarted again. */ | |
71 | listp = ¶m->requestlist[cnt]->waiting; | |
72 | while (*listp != NULL && *listp != ¶m->waitlist[cnt]) | |
73 | listp = &(*listp)->next; | |
74 | ||
75 | if (*listp != NULL) | |
76 | *listp = (*listp)->next; | |
77 | } | |
78 | ||
79 | /* Release the conditional variable. */ | |
80 | (void) pthread_cond_destroy (param->cond); | |
81 | ||
82 | /* Release the mutex. */ | |
83 | pthread_mutex_unlock (&__aio_requests_mutex); | |
84 | } | |
85 | ||
86 | ||
cbdee279 UD |
87 | int |
88 | aio_suspend (list, nent, timeout) | |
89 | const struct aiocb *const list[]; | |
90 | int nent; | |
91 | const struct timespec *timeout; | |
92 | { | |
d71b808a UD |
93 | struct waitlist waitlist[nent]; |
94 | struct requestlist *requestlist[nent]; | |
18de8c73 | 95 | pthread_cond_t cond = PTHREAD_COND_INITIALIZER; |
cbdee279 | 96 | int cnt; |
c547b58a | 97 | bool any = false; |
d71b808a | 98 | int result = 0; |
a334319f | 99 | int dummy; |
d71b808a UD |
100 | |
101 | /* Request the mutex. */ | |
102 | pthread_mutex_lock (&__aio_requests_mutex); | |
cbdee279 | 103 | |
b9337b6a UD |
104 | /* There is not yet a finished request. Signal the request that |
105 | we are working for it. */ | |
cbdee279 | 106 | for (cnt = 0; cnt < nent; ++cnt) |
8b8cc76f | 107 | if (list[cnt] != NULL) |
b9337b6a | 108 | { |
8b8cc76f | 109 | if (list[cnt]->__error_code == EINPROGRESS) |
b9337b6a | 110 | { |
8b8cc76f UD |
111 | requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]); |
112 | ||
113 | if (requestlist[cnt] != NULL) | |
114 | { | |
115 | waitlist[cnt].cond = &cond; | |
116 | waitlist[cnt].next = requestlist[cnt]->waiting; | |
a334319f | 117 | waitlist[cnt].counterp = &dummy; |
8b8cc76f | 118 | waitlist[cnt].sigevp = NULL; |
b61c8aba | 119 | #ifdef BROKEN_THREAD_SIGNALS |
8b8cc76f | 120 | waitlist[cnt].caller_pid = 0; /* Not needed. */ |
b61c8aba | 121 | #endif |
8b8cc76f | 122 | requestlist[cnt]->waiting = &waitlist[cnt]; |
c547b58a | 123 | any = true; |
8b8cc76f UD |
124 | } |
125 | else | |
126 | /* We will never suspend. */ | |
127 | break; | |
b9337b6a | 128 | } |
8b8cc76f UD |
129 | else |
130 | /* We will never suspend. */ | |
131 | break; | |
b9337b6a | 132 | } |
d71b808a | 133 | |
8ee87680 UD |
134 | |
135 | /* Only if none of the entries is NULL or finished to be wait. */ | |
c547b58a | 136 | if (cnt == nent && any) |
d71b808a | 137 | { |
60d73a7a UD |
138 | struct clparam clparam = |
139 | { | |
140 | .list = list, | |
141 | .waitlist = waitlist, | |
142 | .requestlist = requestlist, | |
143 | .cond = &cond, | |
144 | .nent = nent | |
145 | }; | |
d71b808a | 146 | |
67b78ef9 | 147 | pthread_cleanup_push (cleanup, &clparam); |
d71b808a | 148 | |
8ee87680 UD |
149 | if (timeout == NULL) |
150 | result = pthread_cond_wait (&cond, &__aio_requests_mutex); | |
151 | else | |
f14811c7 | 152 | { |
8ee87680 UD |
153 | /* We have to convert the relative timeout value into an |
154 | absolute time value with pthread_cond_timedwait expects. */ | |
155 | struct timeval now; | |
156 | struct timespec abstime; | |
157 | ||
158 | __gettimeofday (&now, NULL); | |
159 | abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000; | |
160 | abstime.tv_sec = timeout->tv_sec + now.tv_sec; | |
161 | if (abstime.tv_nsec >= 1000000000) | |
f14811c7 | 162 | { |
8ee87680 UD |
163 | abstime.tv_nsec -= 1000000000; |
164 | abstime.tv_sec += 1; | |
f14811c7 | 165 | } |
8ee87680 UD |
166 | |
167 | result = pthread_cond_timedwait (&cond, &__aio_requests_mutex, | |
168 | &abstime); | |
f14811c7 | 169 | } |
d71b808a | 170 | |
67b78ef9 | 171 | pthread_cleanup_pop (0); |
8ee87680 | 172 | } |
8b8cc76f | 173 | |
8ee87680 UD |
174 | /* Now remove the entry in the waiting list for all requests |
175 | which didn't terminate. */ | |
176 | while (cnt-- > 0) | |
177 | if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS) | |
178 | { | |
179 | struct waitlist **listp; | |
d71b808a | 180 | |
8ee87680 | 181 | assert (requestlist[cnt] != NULL); |
d71b808a | 182 | |
8ee87680 UD |
183 | /* There is the chance that we cannot find our entry anymore. This |
184 | could happen if the request terminated and restarted again. */ | |
185 | listp = &requestlist[cnt]->waiting; | |
186 | while (*listp != NULL && *listp != &waitlist[cnt]) | |
187 | listp = &(*listp)->next; | |
d71b808a | 188 | |
8ee87680 UD |
189 | if (*listp != NULL) |
190 | *listp = (*listp)->next; | |
191 | } | |
d71b808a | 192 | |
8ee87680 UD |
193 | /* Release the conditional variable. */ |
194 | if (__builtin_expect (pthread_cond_destroy (&cond) != 0, 0)) | |
195 | /* This must never happen. */ | |
196 | abort (); | |
b9337b6a | 197 | |
8ee87680 UD |
198 | if (result != 0) |
199 | { | |
a334319f | 200 | /* An error occurred. Possibly it's EINTR. We have to translate |
8ee87680 UD |
201 | the timeout error report of `pthread_cond_timedwait' to the |
202 | form expected from `aio_suspend'. */ | |
203 | if (result == ETIMEDOUT) | |
204 | __set_errno (EAGAIN); | |
67b78ef9 UD |
205 | else |
206 | __set_errno (result); | |
d71b808a | 207 | |
8ee87680 | 208 | result = -1; |
d71b808a | 209 | } |
cbdee279 | 210 | |
d71b808a UD |
211 | /* Release the mutex. */ |
212 | pthread_mutex_unlock (&__aio_requests_mutex); | |
cbdee279 | 213 | |
d71b808a | 214 | return result; |
cbdee279 UD |
215 | } |
216 | ||
217 | weak_alias (aio_suspend, aio_suspend64) |