]>
Commit | Line | Data |
---|---|---|
cbdee279 | 1 | /* Enqueue and list of read or write requests. |
3a9eb648 | 2 | Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. |
cbdee279 UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Library General Public License as | |
8 | published by the Free Software Foundation; either version 2 of the | |
9 | License, or (at your option) any later version. | |
10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Library General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Library General Public | |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include <aio.h> | |
22 | #include <errno.h> | |
d71b808a | 23 | #include <stdlib.h> |
3a9eb648 | 24 | #include <unistd.h> |
cbdee279 UD |
25 | |
26 | #include "aio_misc.h" | |
27 | ||
28 | ||
d71b808a UD |
29 | /* We need this special structure to handle asynchronous I/O. */ |
30 | struct async_waitlist | |
31 | { | |
32 | int counter; | |
33 | struct sigevent sigev; | |
34 | struct waitlist list[0]; | |
35 | }; | |
36 | ||
37 | ||
cbdee279 UD |
38 | int |
39 | lio_listio (mode, list, nent, sig) | |
40 | int mode; | |
41 | struct aiocb *const list[]; | |
42 | int nent; | |
43 | struct sigevent *sig; | |
44 | { | |
d71b808a | 45 | struct requestlist *requests[nent]; |
cbdee279 | 46 | int cnt; |
d71b808a | 47 | volatile int total = 0; |
cbdee279 UD |
48 | int result = 0; |
49 | ||
50 | /* Check arguments. */ | |
51 | if (mode != LIO_WAIT && mode != LIO_NOWAIT) | |
52 | { | |
53 | __set_errno (EINVAL); | |
54 | return -1; | |
55 | } | |
56 | ||
d71b808a UD |
57 | /* Request the mutex. */ |
58 | pthread_mutex_lock (&__aio_requests_mutex); | |
cbdee279 UD |
59 | |
60 | /* Now we can enqueue all requests. Since we already acquired the | |
d71b808a | 61 | mutex the enqueue function need not do this. */ |
cbdee279 UD |
62 | for (cnt = 0; cnt < nent; ++cnt) |
63 | if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP) | |
d71b808a UD |
64 | { |
65 | requests[cnt] = __aio_enqueue_request ((aiocb_union *) list[cnt], | |
66 | list[cnt]->aio_lio_opcode); | |
67 | ||
68 | if (requests[cnt] != NULL) | |
69 | /* Successfully enqueued. */ | |
70 | ++total; | |
71 | else | |
72 | /* Signal that we've seen an error. `errno' and the error code | |
73 | of the aiocb will tell more. */ | |
74 | result = -1; | |
75 | } | |
76 | ||
77 | if (total == 0) | |
78 | { | |
79 | /* We don't have anything to do except signalling if we work | |
80 | asynchronously. */ | |
3a9eb648 UD |
81 | |
82 | /* Release the mutex. We do this before raising a signal since the | |
83 | signal handler might do a `siglongjmp' and then the mutex is | |
84 | locked forever. */ | |
85 | pthread_mutex_unlock (&__aio_requests_mutex); | |
86 | ||
d71b808a | 87 | if (mode == LIO_NOWAIT) |
3a9eb648 UD |
88 | __aio_notify_only (sig, |
89 | sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0); | |
90 | ||
91 | return result; | |
d71b808a UD |
92 | } |
93 | else if (mode == LIO_WAIT) | |
94 | { | |
18de8c73 | 95 | pthread_cond_t cond = PTHREAD_COND_INITIALIZER; |
d71b808a UD |
96 | struct waitlist waitlist[nent]; |
97 | int oldstate; | |
98 | ||
99 | total = 0; | |
100 | for (cnt = 0; cnt < nent; ++cnt) | |
101 | if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP | |
102 | && requests[cnt] != NULL) | |
103 | { | |
104 | waitlist[cnt].cond = &cond; | |
105 | waitlist[cnt].next = requests[cnt]->waiting; | |
6b9c2e67 | 106 | waitlist[cnt].counterp = &total; |
d71b808a | 107 | waitlist[cnt].sigevp = NULL; |
3a9eb648 | 108 | waitlist[cnt].caller_pid = 0; /* Not needed. */ |
d71b808a UD |
109 | requests[cnt]->waiting = &waitlist[cnt]; |
110 | ++total; | |
111 | } | |
112 | ||
113 | /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation | |
114 | points we must be careful. We added entries to the waiting lists | |
115 | which we must remove. So defer cancelation for now. */ | |
116 | pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); | |
117 | ||
118 | while (total > 0) | |
6b9c2e67 | 119 | pthread_cond_wait (&cond, &__aio_requests_mutex); |
d71b808a UD |
120 | |
121 | /* Now it's time to restore the cancelation state. */ | |
122 | pthread_setcancelstate (oldstate, NULL); | |
b9337b6a UD |
123 | |
124 | /* Release the conditional variable. */ | |
125 | if (pthread_cond_destroy (&cond) != 0) | |
126 | /* This must never happen. */ | |
127 | abort (); | |
d71b808a UD |
128 | } |
129 | else | |
130 | { | |
131 | struct async_waitlist *waitlist; | |
132 | ||
133 | waitlist = (struct async_waitlist *) | |
134 | malloc (sizeof (struct async_waitlist) | |
135 | + (nent * sizeof (struct waitlist))); | |
136 | ||
137 | if (waitlist == NULL) | |
138 | { | |
139 | __set_errno (EAGAIN); | |
140 | result = -1; | |
141 | } | |
cbdee279 | 142 | else |
d71b808a | 143 | { |
3a9eb648 | 144 | pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0; |
d71b808a | 145 | total = 0; |
cbdee279 | 146 | |
d71b808a UD |
147 | for (cnt = 0; cnt < nent; ++cnt) |
148 | if (list[cnt] != NULL && list[cnt]->aio_lio_opcode != LIO_NOP | |
149 | && requests[cnt] != NULL) | |
150 | { | |
151 | waitlist->list[cnt].cond = NULL; | |
152 | waitlist->list[cnt].next = requests[cnt]->waiting; | |
153 | waitlist->list[cnt].counterp = &waitlist->counter; | |
154 | waitlist->list[cnt].sigevp = &waitlist->sigev; | |
3a9eb648 | 155 | waitlist->list[cnt].caller_pid = caller_pid; |
d71b808a UD |
156 | requests[cnt]->waiting = &waitlist->list[cnt]; |
157 | ++total; | |
158 | } | |
cbdee279 | 159 | |
d71b808a UD |
160 | waitlist->counter = total; |
161 | waitlist->sigev = *sig; | |
162 | } | |
163 | } | |
cbdee279 | 164 | |
d71b808a UD |
165 | /* Release the mutex. */ |
166 | pthread_mutex_unlock (&__aio_requests_mutex); | |
cbdee279 UD |
167 | |
168 | return result; | |
169 | } |