Update.
[platform/upstream/glibc.git] / rt / aio_cancel.c
1 /* Cancel requests associated with given file descriptor.
2    Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
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
22 /* We use an UGLY hack to prevent gcc from finding us cheating.  The
23    implementation of aio_cancel and aio_cancel64 are identical and so
24    we want to avoid code duplication by using aliases.  But gcc sees
25    the different parameter lists and prints a warning.  We define here
26    a function so that aio_cancel64 has no prototype.  */
27 #define aio_cancel64 XXX
28 #include <aio.h>
29 /* And undo the hack.  */
30 #undef aio_cancel64
31
32 #include <assert.h>
33 #include <errno.h>
34
35 #include "aio_misc.h"
36
37
38 int
39 aio_cancel (fildes, aiocbp)
40      int fildes;
41      struct aiocb *aiocbp;
42 {
43   struct requestlist *req = NULL;
44   int result = AIO_ALLDONE;
45
46   /* Request the mutex.  */
47   pthread_mutex_lock (&__aio_requests_mutex);
48
49   /* We are asked to cancel a specific AIO request.  */
50   if (aiocbp != NULL)
51     {
52       /* If the AIO request is not for this descriptor it has no value
53          to look for the request block.  */
54       if (aiocbp->aio_fildes == fildes)
55         {
56           struct requestlist *last = NULL;
57
58           req = __aio_find_req_fd (fildes);
59
60           if (req == NULL)
61             {
62             not_found:
63               pthread_mutex_unlock (&__aio_requests_mutex);
64               __set_errno (EINVAL);
65               return -1;
66             }
67
68           while (req->aiocbp != (aiocb_union *) aiocbp)
69             {
70               last = req;
71               req = req->next_prio;
72               if (req == NULL)
73                 goto not_found;
74             }
75
76           /* Don't remove the entry if a thread is already working on it.  */
77           if (req->running == allocated)
78             {
79               result = AIO_NOTCANCELED;
80               req = NULL;
81             }
82           else
83             {
84               /* We can remove the entry.  */
85               __aio_remove_request (last, req, 0);
86
87               result = AIO_CANCELED;
88
89               req->next_prio = NULL;
90             }
91         }
92     }
93   else
94     {
95       /* Find the beginning of the list of all requests for this
96          desriptor.  */
97       req = __aio_find_req_fd (fildes);
98
99       /* If any request is worked on by a thread it must be the first.
100          So either we can delete all requests or all but the first.  */
101       if (req != NULL)
102         {
103           if (req->running == allocated)
104             {
105               struct requestlist *old = req;
106               req = req->next_prio;
107               old->next_prio = NULL;
108
109               result = AIO_NOTCANCELED;
110
111               if (req != NULL)
112                 __aio_remove_request (old, req, 1);
113             }
114           else
115             {
116               result = AIO_CANCELED;
117
118               /* We can remove the entry.  */
119               __aio_remove_request (NULL, req, 1);
120             }
121         }
122     }
123
124   /* Mark requests as canceled and send signal.  */
125   while (req != NULL)
126     {
127       struct requestlist *old = req;
128       assert (req->running == yes || req->running == queued);
129       req->aiocbp->aiocb.__error_code = ECANCELED;
130       req->aiocbp->aiocb.__return_value = -1;
131       __aio_notify (req);
132       req = req->next_prio;
133       __aio_free_request (old);
134     }
135
136   /* Release the mutex.  */
137   pthread_mutex_unlock (&__aio_requests_mutex);
138
139   return result;
140 }
141
142 weak_alias (aio_cancel, aio_cancel64)