diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-06-17 22:11:22 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-06-17 22:11:22 +0000 |
commit | 60d73a7ac4e0116ef2e458d705aeee14aff7aed9 (patch) | |
tree | 6a54617cdad5490be019cc1ad288f9d7e7e3091a /sysdeps/pthread/aio_suspend.c | |
parent | aa3cee213a291e2fd7298579059706622dd16793 (diff) | |
download | glibc-60d73a7ac4e0116ef2e458d705aeee14aff7aed9.tar.gz glibc-60d73a7ac4e0116ef2e458d705aeee14aff7aed9.tar.xz glibc-60d73a7ac4e0116ef2e458d705aeee14aff7aed9.zip |
Update.
* sysdeps/unix/clock_nanosleep.c (clock_nanosleep): nanosleep takes care of enabling cancellation. * sysdeps/pthread/aio_suspend.c (aio_suspend): Make aio_suspend cancelable. It's not correct to disable cancellation. Instead of a cleanup handler.
Diffstat (limited to 'sysdeps/pthread/aio_suspend.c')
-rw-r--r-- | sysdeps/pthread/aio_suspend.c | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/sysdeps/pthread/aio_suspend.c b/sysdeps/pthread/aio_suspend.c index ffc1c64703..1b09aef028 100644 --- a/sysdeps/pthread/aio_suspend.c +++ b/sysdeps/pthread/aio_suspend.c @@ -35,9 +35,54 @@ #include <stdlib.h> #include <sys/time.h> +#include <bits/libc-lock.h> #include "aio_misc.h" +struct clparam +{ + const struct aiocb *const *list; + struct waitlist *waitlist; + struct requestlist **requestlist; + pthread_cond_t *cond; + int nent; +}; + + +static void +cleanup (void *arg) +{ + const struct clparam *param = (const struct clparam *) arg; + + /* Now remove the entry in the waiting list for all requests + which didn't terminate. */ + int cnt = param->nent; + while (cnt-- > 0) + if (param->list[cnt] != NULL + && param->list[cnt]->__error_code == EINPROGRESS) + { + struct waitlist **listp; + + assert (param->requestlist[cnt] != NULL); + + /* There is the chance that we cannot find our entry anymore. This + could happen if the request terminated and restarted again. */ + listp = ¶m->requestlist[cnt]->waiting; + while (*listp != NULL && *listp != ¶m->waitlist[cnt]) + listp = &(*listp)->next; + + if (*listp != NULL) + *listp = (*listp)->next; + } + + /* Release the conditional variable. */ + (void) pthread_cond_destroy (param->cond); + + /* Release the mutex. */ + pthread_mutex_unlock (&__aio_requests_mutex); +} + + int aio_suspend (list, nent, timeout) const struct aiocb *const list[]; @@ -87,12 +132,16 @@ aio_suspend (list, nent, timeout) /* Only if none of the entries is NULL or finished to be wait. */ if (cnt == nent && any) { - int oldstate; + struct clparam clparam = + { + .list = list, + .waitlist = waitlist, + .requestlist = requestlist, + .cond = &cond, + .nent = nent + }; - /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation - points we must be careful. We added entries to the waiting lists - which we must remove. So defer cancelation for now. */ - pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); + __libc_cleanup_region_start (1, cleanup, &clparam); if (timeout == NULL) result = pthread_cond_wait (&cond, &__aio_requests_mutex); @@ -116,8 +165,7 @@ aio_suspend (list, nent, timeout) &abstime); } - /* Now it's time to restore the cancellation state. */ - pthread_setcancelstate (oldstate, NULL); + __libc_cleanup_region_end (0); } /* Now remove the entry in the waiting list for all requests |