Rewrite to support lio_listio and aio_suspend.
[kopensolaris-gnu/glibc.git] / rt / aio_cancel.c
1 /* Cancel requests associated with given file descriptor.
2    Copyright (C) 1997 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 <errno.h>
33
34 #include "aio_misc.h"
35
36
37 /* Argh, so far there is no ECANCELED.  */
38 #define ECANCELED 125
39
40 int
41 aio_cancel (fildes, aiocbp)
42      int fildes;
43      struct aiocb *aiocbp;
44 {
45   struct requestlist *req = NULL;
46   int result = AIO_ALLDONE;
47
48   /* Request the mutex.  */
49   pthread_mutex_lock (&__aio_requests_mutex);
50
51   /* We are asked to cancel a specific AIO request.  */
52   if (aiocbp != NULL)
53     {
54       /* If the AIO request is not for this descriptor it has no value
55          to look for the request block.  */
56       if (aiocbp->aio_fildes == fildes)
57         {
58           struct requestlist *last = NULL;
59
60           req = __aio_find_req_fd (fildes);
61
62           while (req->aiocbp != (aiocb_union *) aiocbp)
63             {
64               last = req;
65               req = req->next_prio;
66             }
67
68           /* Don't remove the entry if a thread is already working on it.  */
69           if (req->running == allocated)
70             result = AIO_NOTCANCELED;
71           else
72             {
73               /* We can remove the entry.  */
74               if (last != NULL)
75                 last->next_prio = req->next_prio;
76               else
77                 if (req->next_prio == NULL)
78                   {
79                     if (req->last_fd != NULL)
80                       req->last_fd->next_fd = req->next_fd;
81                     if (req->next_fd != NULL)
82                       req->next_fd->last_fd = req->last_fd;
83                   }
84                 else
85                   {
86                     if (req->last_fd != NULL)
87                       req->last_fd->next_fd = req->next_prio;
88                     if (req->next_fd != NULL)
89                       req->next_fd->last_fd = req->next_prio;
90                     req->next_prio->last_fd = req->last_fd;
91                     req->next_prio->next_fd = req->next_fd;
92
93                     /* Mark this entry as runnable.  */
94                     req->next_prio->running = yes;
95                   }
96
97               result = AIO_CANCELED;
98             }
99
100           req->next_prio = NULL;
101         }
102     }
103   else
104     {
105       /* Find the beginning of the list of all requests for this
106          desriptor.  */
107       req = __aio_find_req_fd (fildes);
108
109       /* If any request is worked on by a thread it must be the first.
110          So either we can delete all requests or all but the first.  */
111       if (req != NULL)
112         if (req->running == allocated)
113           {
114             struct requestlist *old = req;
115             req = req->next_prio;
116             old->next_prio = NULL;
117
118             result = AIO_NOTCANCELED;
119           }
120         else
121           {
122             /* Remove entry from the file descriptor list.  */
123             if (req->last_fd != NULL)
124               req->last_fd->next_fd = req->next_fd;
125             if (req->next_fd != NULL)
126               req->next_fd->last_fd = req->last_fd;
127
128             result = AIO_CANCELED;
129           }
130     }
131
132   /* Mark requests as canceled and send signal.  */
133   while (req != NULL)
134     {
135       struct requestlist *old = req;
136       req->aiocbp->aiocb.__error_code = ECANCELED;
137       req->aiocbp->aiocb.__return_value = -1;
138       __aio_notify (req);
139       req = req->next_prio;
140       __aio_free_request (old);
141     }
142
143   /* Release the mutex.  */
144   pthread_mutex_unlock (&__aio_requests_mutex);
145
146   return result;
147 }
148
149 weak_alias (aio_cancel, aio_cancel64)