f2d938965032841c6940370b9b83b2aea1f4cd10
[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 #include <pthread.h>
34
35 #include "aio_misc.h"
36
37
38 /* Argh, so far there is no ECANCELED.  */
39 #define ECANCELED 125
40
41 int
42 aio_cancel (fildes, aiocbp)
43      int fildes;
44      struct aiocb *aiocbp;
45 {
46   struct aiocb *firstp;
47   int result = AIO_ALLDONE;
48
49   /* Request the semaphore.  */
50   sem_wait (&__aio_requests_sema);
51
52   /* Search for the list of requests associated with the given file
53      descriptor.  */
54   for (firstp = (struct aiocb *) __aio_requests; firstp != NULL;
55        firstp = firstp->__next_fd)
56     if (firstp->aio_fildes == fildes)
57       break;
58
59   /* If the file descriptor is not found all work seems to done
60      already.  Otherwise try to cancel the request(s).  */
61   if (firstp != NULL)
62     {
63       if (aiocbp != NULL)
64         {
65           /* Locate the entry corresponding to the AIOCBP parameter.  */
66           if (aiocbp == firstp)
67             /* The requests is currently handled, therefore don't
68                cancel it and signal this to the user.  */
69             result = AIO_NOTCANCELED;
70           else
71             {
72               while (firstp->__next_prio != NULL
73                      && aiocbp != firstp->__next_prio)
74                 firstp = firstp->__next_prio;
75
76               if (firstp->__next_prio != NULL)
77                 {
78                   /* The request the user wants to cancel is in the
79                      queue.  Simply remove it.  */
80                   firstp->__next_prio = aiocbp->__next_prio;
81
82                   /* Mark as canceled.  */
83                   aiocbp->__error_code = ECANCELED;
84                   aiocbp->__return_value = -1;
85
86                   /* Send the signal to notify about canceled
87                      processing of the request.  */
88                   if (aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD)
89                     {
90                       /* We have to start a thread.  */
91                       pthread_t tid;
92                       pthread_attr_t attr, *pattr;
93
94                       pattr = (pthread_attr_t *)
95                         aiocbp->aio_sigevent.sigev_notify_attributes;
96                       if (pattr == NULL)
97                         {
98                           pthread_attr_init (&attr);
99                           pthread_attr_setdetachstate (&attr,
100                                                        PTHREAD_CREATE_DETACHED);
101                           pattr = &attr;
102                         }
103
104                       pthread_create (&tid, pattr,
105                                       (void *(*) (void *))
106                                       aiocbp->aio_sigevent.sigev_notify_function,
107                                       aiocbp->aio_sigevent.sigev_value.sival_ptr);
108                     }
109                   else if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
110                     /* We have to send a signal.  */
111                     __aio_sigqueue (aiocbp->aio_sigevent.sigev_signo,
112                                     aiocbp->aio_sigevent.sigev_value);
113
114                   result = AIO_CANCELED;
115                 }
116             }
117         }
118       else
119         {
120           /* First dequeue all waiting requests.  */
121           aiocbp = firstp;
122
123           while ((firstp = firstp->__next_prio) != NULL)
124             {
125               firstp->__error_code = ECANCELED;
126               firstp->__return_value = -1;
127
128
129               /* Send the signal to notify about canceled processing
130                  of the request.  */
131               if (firstp->aio_sigevent.sigev_notify == SIGEV_THREAD)
132                 {
133                   /* We have to start a thread.  */
134                   pthread_t tid;
135                   pthread_attr_t attr, *pattr;
136
137                   pattr = (pthread_attr_t *)
138                     aiocbp->aio_sigevent.sigev_notify_attributes;
139                   if (pattr == NULL)
140                     {
141                       pthread_attr_init (&attr);
142                       pthread_attr_setdetachstate (&attr,
143                                                    PTHREAD_CREATE_DETACHED);
144                       pattr = &attr;
145                     }
146
147                   pthread_create (&tid, pattr,
148                                   (void *(*) (void *))
149                                   firstp->aio_sigevent.sigev_notify_function,
150                                   firstp->aio_sigevent.sigev_value.sival_ptr);
151                 }
152               else if (firstp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
153                 /* We have to send a signal.  */
154                 __aio_sigqueue (firstp->aio_sigevent.sigev_signo,
155                                 firstp->aio_sigevent.sigev_value);
156             }
157
158           /* We have to signal that not all requests could be canceled
159              since the first requests is currently processed.  */
160           result = AIO_NOTCANCELED;
161
162           aiocbp->__next_prio = NULL;
163         }
164     }
165
166   /* Release the semaphore.  */
167   sem_post (&__aio_requests_sema);
168
169   return result;
170 }
171
172 weak_alias (aio_cancel, aio_cancel64)