| /* Cancel requests associated with given file descriptor. |
| Copyright (C) 1997-2014 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. |
| |
| The GNU C Library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| The GNU C Library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with the GNU C Library; if not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| |
| /* We use an UGLY hack to prevent gcc from finding us cheating. The |
| implementation of aio_cancel and aio_cancel64 are identical and so |
| we want to avoid code duplication by using aliases. But gcc sees |
| the different parameter lists and prints a warning. We define here |
| a function so that aio_cancel64 has no prototype. */ |
| #ifndef aio_cancel |
| #define aio_cancel64 XXX |
| #include <aio.h> |
| /* And undo the hack. */ |
| #undef aio_cancel64 |
| #endif |
| |
| #include <assert.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| |
| #include <aio_misc.h> |
| |
| |
| int |
| aio_cancel (fildes, aiocbp) |
| int fildes; |
| struct aiocb *aiocbp; |
| { |
| struct requestlist *req = NULL; |
| int result = AIO_ALLDONE; |
| |
| /* If fildes is invalid, error. */ |
| if (fcntl (fildes, F_GETFL) < 0) |
| { |
| __set_errno (EBADF); |
| return -1; |
| } |
| |
| /* Request the mutex. */ |
| pthread_mutex_lock (&__aio_requests_mutex); |
| |
| /* We are asked to cancel a specific AIO request. */ |
| if (aiocbp != NULL) |
| { |
| /* If the AIO request is not for this descriptor it has no value |
| to look for the request block. */ |
| if (aiocbp->aio_fildes != fildes) |
| { |
| pthread_mutex_unlock (&__aio_requests_mutex); |
| __set_errno (EINVAL); |
| return -1; |
| } |
| else if (aiocbp->__error_code == EINPROGRESS) |
| { |
| struct requestlist *last = NULL; |
| |
| req = __aio_find_req_fd (fildes); |
| |
| if (req == NULL) |
| { |
| not_found: |
| pthread_mutex_unlock (&__aio_requests_mutex); |
| __set_errno (EINVAL); |
| return -1; |
| } |
| |
| while (req->aiocbp != (aiocb_union *) aiocbp) |
| { |
| last = req; |
| req = req->next_prio; |
| if (req == NULL) |
| goto not_found; |
| } |
| |
| /* Don't remove the entry if a thread is already working on it. */ |
| if (req->running == allocated) |
| { |
| result = AIO_NOTCANCELED; |
| req = NULL; |
| } |
| else |
| { |
| /* We can remove the entry. */ |
| __aio_remove_request (last, req, 0); |
| |
| result = AIO_CANCELED; |
| |
| req->next_prio = NULL; |
| } |
| } |
| } |
| else |
| { |
| /* Find the beginning of the list of all requests for this |
| desriptor. */ |
| req = __aio_find_req_fd (fildes); |
| |
| /* If any request is worked on by a thread it must be the first. |
| So either we can delete all requests or all but the first. */ |
| if (req != NULL) |
| { |
| if (req->running == allocated) |
| { |
| struct requestlist *old = req; |
| req = req->next_prio; |
| old->next_prio = NULL; |
| |
| result = AIO_NOTCANCELED; |
| |
| if (req != NULL) |
| __aio_remove_request (old, req, 1); |
| } |
| else |
| { |
| result = AIO_CANCELED; |
| |
| /* We can remove the entry. */ |
| __aio_remove_request (NULL, req, 1); |
| } |
| } |
| } |
| |
| /* Mark requests as canceled and send signal. */ |
| while (req != NULL) |
| { |
| struct requestlist *old = req; |
| assert (req->running == yes || req->running == queued); |
| req->aiocbp->aiocb.__error_code = ECANCELED; |
| req->aiocbp->aiocb.__return_value = -1; |
| __aio_notify (req); |
| req = req->next_prio; |
| __aio_free_request (old); |
| } |
| |
| /* Release the mutex. */ |
| pthread_mutex_unlock (&__aio_requests_mutex); |
| |
| return result; |
| } |
| |
| #ifndef aio_cancel |
| weak_alias (aio_cancel, aio_cancel64) |
| #endif |