Back to index

glibc  2.9
aio_cancel.c
Go to the documentation of this file.
00001 /* Cancel requests associated with given file descriptor.
00002    Copyright (C) 1997, 1998, 2000, 2002, 2005 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 
00022 /* We use an UGLY hack to prevent gcc from finding us cheating.  The
00023    implementation of aio_cancel and aio_cancel64 are identical and so
00024    we want to avoid code duplication by using aliases.  But gcc sees
00025    the different parameter lists and prints a warning.  We define here
00026    a function so that aio_cancel64 has no prototype.  */
00027 #ifndef aio_cancel
00028 #define aio_cancel64 XXX
00029 #include <aio.h>
00030 /* And undo the hack.  */
00031 #undef aio_cancel64
00032 #endif
00033 
00034 #include <assert.h>
00035 #include <errno.h>
00036 
00037 #include <aio_misc.h>
00038 
00039 
00040 int
00041 aio_cancel (fildes, aiocbp)
00042      int fildes;
00043      struct aiocb *aiocbp;
00044 {
00045   struct requestlist *req = NULL;
00046   int result = AIO_ALLDONE;
00047 
00048   /* If fildes is invalid, error. */
00049   if (fcntl (fildes, F_GETFL) < 0)
00050     {
00051       __set_errno (EBADF);
00052       return -1;
00053     }
00054 
00055   /* Request the mutex.  */
00056   pthread_mutex_lock (&__aio_requests_mutex);
00057 
00058   /* We are asked to cancel a specific AIO request.  */
00059   if (aiocbp != NULL)
00060     {
00061       /* If the AIO request is not for this descriptor it has no value
00062         to look for the request block.  */
00063       if (aiocbp->aio_fildes != fildes)
00064        {
00065          pthread_mutex_unlock (&__aio_requests_mutex);
00066          __set_errno (EINVAL);
00067          return -1;
00068        }
00069       else if (aiocbp->__error_code == EINPROGRESS)
00070        {
00071          struct requestlist *last = NULL;
00072 
00073          req = __aio_find_req_fd (fildes);
00074 
00075          if (req == NULL)
00076            {
00077            not_found:
00078              pthread_mutex_unlock (&__aio_requests_mutex);
00079              __set_errno (EINVAL);
00080              return -1;
00081            }
00082 
00083          while (req->aiocbp != (aiocb_union *) aiocbp)
00084            {
00085              last = req;
00086              req = req->next_prio;
00087              if (req == NULL)
00088               goto not_found;
00089            }
00090 
00091          /* Don't remove the entry if a thread is already working on it.  */
00092          if (req->running == allocated)
00093            {
00094              result = AIO_NOTCANCELED;
00095              req = NULL;
00096            }
00097          else
00098            {
00099              /* We can remove the entry.  */
00100              __aio_remove_request (last, req, 0);
00101 
00102              result = AIO_CANCELED;
00103 
00104              req->next_prio = NULL;
00105            }
00106        }
00107     }
00108   else
00109     {
00110       /* Find the beginning of the list of all requests for this
00111         desriptor.  */
00112       req = __aio_find_req_fd (fildes);
00113 
00114       /* If any request is worked on by a thread it must be the first.
00115         So either we can delete all requests or all but the first.  */
00116       if (req != NULL)
00117        {
00118          if (req->running == allocated)
00119            {
00120              struct requestlist *old = req;
00121              req = req->next_prio;
00122              old->next_prio = NULL;
00123 
00124              result = AIO_NOTCANCELED;
00125 
00126              if (req != NULL)
00127               __aio_remove_request (old, req, 1);
00128            }
00129          else
00130            {
00131              result = AIO_CANCELED;
00132 
00133              /* We can remove the entry.  */
00134              __aio_remove_request (NULL, req, 1);
00135            }
00136        }
00137     }
00138 
00139   /* Mark requests as canceled and send signal.  */
00140   while (req != NULL)
00141     {
00142       struct requestlist *old = req;
00143       assert (req->running == yes || req->running == queued);
00144       req->aiocbp->aiocb.__error_code = ECANCELED;
00145       req->aiocbp->aiocb.__return_value = -1;
00146       __aio_notify (req);
00147       req = req->next_prio;
00148       __aio_free_request (old);
00149     }
00150 
00151   /* Release the mutex.  */
00152   pthread_mutex_unlock (&__aio_requests_mutex);
00153 
00154   return result;
00155 }
00156 
00157 #ifndef aio_cancel
00158 weak_alias (aio_cancel, aio_cancel64)
00159 #endif