summaryrefslogtreecommitdiff
path: root/rt/aio_cancel.c
diff options
context:
space:
mode:
Diffstat (limited to 'rt/aio_cancel.c')
-rw-r--r--rt/aio_cancel.c195
1 files changed, 86 insertions, 109 deletions
diff --git a/rt/aio_cancel.c b/rt/aio_cancel.c
index f2d9389650..e802a8533f 100644
--- a/rt/aio_cancel.c
+++ b/rt/aio_cancel.c
@@ -30,7 +30,6 @@
#undef aio_cancel64
#include <errno.h>
-#include <pthread.h>
#include "aio_misc.h"
@@ -43,128 +42,106 @@ aio_cancel (fildes, aiocbp)
int fildes;
struct aiocb *aiocbp;
{
- struct aiocb *firstp;
+ struct requestlist *req = NULL;
int result = AIO_ALLDONE;
- /* Request the semaphore. */
- sem_wait (&__aio_requests_sema);
+ /* Request the mutex. */
+ pthread_mutex_lock (&__aio_requests_mutex);
- /* Search for the list of requests associated with the given file
- descriptor. */
- for (firstp = (struct aiocb *) __aio_requests; firstp != NULL;
- firstp = firstp->__next_fd)
- if (firstp->aio_fildes == fildes)
- break;
-
- /* If the file descriptor is not found all work seems to done
- already. Otherwise try to cancel the request(s). */
- if (firstp != NULL)
+ /* We are asked to cancel a specific AIO request. */
+ if (aiocbp != NULL)
{
- 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)
{
- /* Locate the entry corresponding to the AIOCBP parameter. */
- if (aiocbp == firstp)
- /* The requests is currently handled, therefore don't
- cancel it and signal this to the user. */
- result = AIO_NOTCANCELED;
- else
+ struct requestlist *last = NULL;
+
+ req = __aio_find_req_fd (fildes);
+
+ while (req->aiocbp != (aiocb_union *) aiocbp)
{
- while (firstp->__next_prio != NULL
- && aiocbp != firstp->__next_prio)
- firstp = firstp->__next_prio;
-
- if (firstp->__next_prio != NULL)
- {
- /* The request the user wants to cancel is in the
- queue. Simply remove it. */
- firstp->__next_prio = aiocbp->__next_prio;
-
- /* Mark as canceled. */
- aiocbp->__error_code = ECANCELED;
- aiocbp->__return_value = -1;
-
- /* Send the signal to notify about canceled
- processing of the request. */
- if (aiocbp->aio_sigevent.sigev_notify == SIGEV_THREAD)
- {
- /* We have to start a thread. */
- pthread_t tid;
- pthread_attr_t attr, *pattr;
-
- pattr = (pthread_attr_t *)
- aiocbp->aio_sigevent.sigev_notify_attributes;
- if (pattr == NULL)
- {
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate (&attr,
- PTHREAD_CREATE_DETACHED);
- pattr = &attr;
- }
-
- pthread_create (&tid, pattr,
- (void *(*) (void *))
- aiocbp->aio_sigevent.sigev_notify_function,
- aiocbp->aio_sigevent.sigev_value.sival_ptr);
- }
- else if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
- /* We have to send a signal. */
- __aio_sigqueue (aiocbp->aio_sigevent.sigev_signo,
- aiocbp->aio_sigevent.sigev_value);
-
- result = AIO_CANCELED;
- }
+ last = req;
+ req = req->next_prio;
}
- }
- else
- {
- /* First dequeue all waiting requests. */
- aiocbp = firstp;
- while ((firstp = firstp->__next_prio) != NULL)
+ /* Don't remove the entry if a thread is already working on it. */
+ if (req->running == allocated)
+ result = AIO_NOTCANCELED;
+ else
{
- firstp->__error_code = ECANCELED;
- firstp->__return_value = -1;
-
-
- /* Send the signal to notify about canceled processing
- of the request. */
- if (firstp->aio_sigevent.sigev_notify == SIGEV_THREAD)
- {
- /* We have to start a thread. */
- pthread_t tid;
- pthread_attr_t attr, *pattr;
-
- pattr = (pthread_attr_t *)
- aiocbp->aio_sigevent.sigev_notify_attributes;
- if (pattr == NULL)
- {
- pthread_attr_init (&attr);
- pthread_attr_setdetachstate (&attr,
- PTHREAD_CREATE_DETACHED);
- pattr = &attr;
- }
-
- pthread_create (&tid, pattr,
- (void *(*) (void *))
- firstp->aio_sigevent.sigev_notify_function,
- firstp->aio_sigevent.sigev_value.sival_ptr);
- }
- else if (firstp->aio_sigevent.sigev_notify == SIGEV_SIGNAL)
- /* We have to send a signal. */
- __aio_sigqueue (firstp->aio_sigevent.sigev_signo,
- firstp->aio_sigevent.sigev_value);
+ /* We can remove the entry. */
+ if (last != NULL)
+ last->next_prio = req->next_prio;
+ else
+ if (req->next_prio == NULL)
+ {
+ if (req->last_fd != NULL)
+ req->last_fd->next_fd = req->next_fd;
+ if (req->next_fd != NULL)
+ req->next_fd->last_fd = req->last_fd;
+ }
+ else
+ {
+ if (req->last_fd != NULL)
+ req->last_fd->next_fd = req->next_prio;
+ if (req->next_fd != NULL)
+ req->next_fd->last_fd = req->next_prio;
+ req->next_prio->last_fd = req->last_fd;
+ req->next_prio->next_fd = req->next_fd;
+
+ /* Mark this entry as runnable. */
+ req->next_prio->running = yes;
+ }
+
+ result = AIO_CANCELED;
}
- /* We have to signal that not all requests could be canceled
- since the first requests is currently processed. */
- result = AIO_NOTCANCELED;
-
- aiocbp->__next_prio = NULL;
+ 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;
+ }
+ else
+ {
+ /* Remove entry from the file descriptor list. */
+ if (req->last_fd != NULL)
+ req->last_fd->next_fd = req->next_fd;
+ if (req->next_fd != NULL)
+ req->next_fd->last_fd = req->last_fd;
+
+ result = AIO_CANCELED;
+ }
+ }
+
+ /* Mark requests as canceled and send signal. */
+ while (req != NULL)
+ {
+ struct requestlist *old = req;
+ 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 semaphore. */
- sem_post (&__aio_requests_sema);
+ /* Release the mutex. */
+ pthread_mutex_unlock (&__aio_requests_mutex);
return result;
}