]>
Commit | Line | Data |
---|---|---|
daa3fc9b FW |
1 | /* Cancel requests associated with given file descriptor. |
2 | Copyright (C) 1997-2021 Free Software Foundation, Inc. | |
478b92f0 UD |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
478b92f0 UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
478b92f0 | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 | 16 | License along with the GNU C Library; if not, see |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
28f540f4 | 18 | |
28f540f4 | 19 | |
b6ab06ce UD |
20 | /* We use an UGLY hack to prevent gcc from finding us cheating. The |
21 | implementation of aio_cancel and aio_cancel64 are identical and so | |
22 | we want to avoid code duplication by using aliases. But gcc sees | |
23 | the different parameter lists and prints a warning. We define here | |
24 | a function so that aio_cancel64 has no prototype. */ | |
daa3fc9b | 25 | #ifndef aio_cancel |
b6ab06ce UD |
26 | #define aio_cancel64 XXX |
27 | #include <aio.h> | |
28 | /* And undo the hack. */ | |
29 | #undef aio_cancel64 | |
daa3fc9b | 30 | #endif |
28f540f4 | 31 | |
daa3fc9b | 32 | #include <assert.h> |
b6ab06ce | 33 | #include <errno.h> |
daa3fc9b FW |
34 | #include <fcntl.h> |
35 | ||
36 | #include <aio_misc.h> | |
3df6dcc5 | 37 | #include <pthreadP.h> |
daa3fc9b | 38 | |
28f540f4 | 39 | |
b6ab06ce | 40 | int |
3df6dcc5 | 41 | __aio_cancel (int fildes, struct aiocb *aiocbp) |
b6ab06ce | 42 | { |
daa3fc9b FW |
43 | struct requestlist *req = NULL; |
44 | int result = AIO_ALLDONE; | |
45 | ||
46 | /* If fildes is invalid, error. */ | |
3df6dcc5 | 47 | if (__fcntl (fildes, F_GETFL) < 0) |
daa3fc9b FW |
48 | { |
49 | __set_errno (EBADF); | |
50 | return -1; | |
51 | } | |
52 | ||
53 | /* Request the mutex. */ | |
3df6dcc5 | 54 | __pthread_mutex_lock (&__aio_requests_mutex); |
daa3fc9b FW |
55 | |
56 | /* We are asked to cancel a specific AIO request. */ | |
57 | if (aiocbp != NULL) | |
58 | { | |
59 | /* If the AIO request is not for this descriptor it has no value | |
60 | to look for the request block. */ | |
61 | if (aiocbp->aio_fildes != fildes) | |
62 | { | |
3df6dcc5 | 63 | __pthread_mutex_unlock (&__aio_requests_mutex); |
daa3fc9b FW |
64 | __set_errno (EINVAL); |
65 | return -1; | |
66 | } | |
67 | else if (aiocbp->__error_code == EINPROGRESS) | |
68 | { | |
69 | struct requestlist *last = NULL; | |
70 | ||
71 | req = __aio_find_req_fd (fildes); | |
72 | ||
73 | if (req == NULL) | |
74 | { | |
75 | not_found: | |
3df6dcc5 | 76 | __pthread_mutex_unlock (&__aio_requests_mutex); |
daa3fc9b FW |
77 | __set_errno (EINVAL); |
78 | return -1; | |
79 | } | |
80 | ||
81 | while (req->aiocbp != (aiocb_union *) aiocbp) | |
82 | { | |
83 | last = req; | |
84 | req = req->next_prio; | |
85 | if (req == NULL) | |
86 | goto not_found; | |
87 | } | |
88 | ||
89 | /* Don't remove the entry if a thread is already working on it. */ | |
90 | if (req->running == allocated) | |
91 | { | |
92 | result = AIO_NOTCANCELED; | |
93 | req = NULL; | |
94 | } | |
95 | else | |
96 | { | |
97 | /* We can remove the entry. */ | |
98 | __aio_remove_request (last, req, 0); | |
99 | ||
100 | result = AIO_CANCELED; | |
101 | ||
102 | req->next_prio = NULL; | |
103 | } | |
104 | } | |
105 | } | |
106 | else | |
107 | { | |
108 | /* Find the beginning of the list of all requests for this | |
109 | desriptor. */ | |
110 | req = __aio_find_req_fd (fildes); | |
111 | ||
112 | /* If any request is worked on by a thread it must be the first. | |
113 | So either we can delete all requests or all but the first. */ | |
114 | if (req != NULL) | |
115 | { | |
116 | if (req->running == allocated) | |
117 | { | |
118 | struct requestlist *old = req; | |
119 | req = req->next_prio; | |
120 | old->next_prio = NULL; | |
121 | ||
122 | result = AIO_NOTCANCELED; | |
123 | ||
124 | if (req != NULL) | |
125 | __aio_remove_request (old, req, 1); | |
126 | } | |
127 | else | |
128 | { | |
129 | result = AIO_CANCELED; | |
130 | ||
131 | /* We can remove the entry. */ | |
132 | __aio_remove_request (NULL, req, 1); | |
133 | } | |
134 | } | |
135 | } | |
136 | ||
137 | /* Mark requests as canceled and send signal. */ | |
138 | while (req != NULL) | |
139 | { | |
140 | struct requestlist *old = req; | |
141 | assert (req->running == yes || req->running == queued); | |
142 | req->aiocbp->aiocb.__error_code = ECANCELED; | |
143 | req->aiocbp->aiocb.__return_value = -1; | |
144 | __aio_notify (req); | |
145 | req = req->next_prio; | |
146 | __aio_free_request (old); | |
147 | } | |
148 | ||
149 | /* Release the mutex. */ | |
3df6dcc5 | 150 | __pthread_mutex_unlock (&__aio_requests_mutex); |
daa3fc9b FW |
151 | |
152 | return result; | |
28f540f4 | 153 | } |
3df6dcc5 FW |
154 | #if PTHREAD_IN_LIBC |
155 | # ifndef __aio_cancel | |
156 | versioned_symbol (libc, __aio_cancel, aio_cancel, GLIBC_2_34); | |
157 | versioned_symbol (libc, __aio_cancel, aio_cancel64, GLIBC_2_34); | |
158 | # if OTHER_SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_34) | |
159 | compat_symbol (librt, __aio_cancel, aio_cancel, GLIBC_2_1); | |
160 | compat_symbol (librt, __aio_cancel, aio_cancel64, GLIBC_2_1); | |
161 | # endif | |
162 | # endif /* __aio_cancel */ | |
163 | #else /* !PTHREAD_IN_LIBC */ | |
164 | strong_alias (__aio_cancel, aio_cancel) | |
165 | weak_alias (__aio_cancel, aio_cancel64) | |
daa3fc9b | 166 | #endif |