diff options
author | Ulrich Drepper <drepper@redhat.com> | 2006-08-03 08:17:20 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2006-08-03 08:17:20 +0000 |
commit | f1762c0c4b3ba91073f82da02a16d8ee29ed7444 (patch) | |
tree | dd3ed0e40f1cb6a2560dfba1fd300cfe98be28ba /resolv | |
parent | 6eab4ee54b5ae38e6243a7bb419061d8d0fa216e (diff) |
[BZ #2978]
2006-08-03 Ulrich Drepper <drepper@redhat.com>
* rt/Makefile (tests): Add tst-clock2.
* rt/tst-clock2.c: New file.
[BZ #2978]
* resolv/gai_notify.c (__gai_notify_only): Copy memory for thread
function and its parameters and pass it to new thread.
(__gai_notify): Add support for alternative waiting for completion.
* resolv/gai_suspend.c (gai_suspend): Add support for alternative
waiting for completion.
* resolv/getaddrinfo_a.c: Likewise.
* resolv/gai_misc.h (struct waitlist): Don't add cond if alternative
waiting for completion is used.
* resolv/gai_misc.c: Allow overwriting code to start helper thread.
* resolv/gai_cancel.c: Include <gai_misc.h> not "gai_misc.h".
* resolv/gai_error.c: Likewise.
* resolv/gai_sigqueue.c: Likewise.
* hurd/getdport.c (__detdport): Don't return EBADF; instead set
errno to EBADF and return MACH_PORT_NULL.
* posix/Makefile (CFLAGS-waitid.c): Add -fasynchronous-unwind-tables.
Diffstat (limited to 'resolv')
-rw-r--r-- | resolv/gai_cancel.c | 4 | ||||
-rw-r--r-- | resolv/gai_error.c | 4 | ||||
-rw-r--r-- | resolv/gai_misc.c | 32 | ||||
-rw-r--r-- | resolv/gai_misc.h | 4 | ||||
-rw-r--r-- | resolv/gai_notify.c | 53 | ||||
-rw-r--r-- | resolv/gai_sigqueue.c | 4 | ||||
-rw-r--r-- | resolv/gai_suspend.c | 18 | ||||
-rw-r--r-- | resolv/getaddrinfo_a.c | 21 |
8 files changed, 108 insertions, 32 deletions
diff --git a/resolv/gai_cancel.c b/resolv/gai_cancel.c index 45432065c4..19a0a9bb87 100644 --- a/resolv/gai_cancel.c +++ b/resolv/gai_cancel.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -20,7 +20,7 @@ #include <netdb.h> #include <pthread.h> -#include "gai_misc.h" +#include <gai_misc.h> int diff --git a/resolv/gai_error.c b/resolv/gai_error.c index 0620b04b9d..4c91628a62 100644 --- a/resolv/gai_error.c +++ b/resolv/gai_error.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -19,7 +19,7 @@ #include <netdb.h> -#include "gai_misc.h" +#include <gai_misc.h> int gai_error (struct gaicb *req) diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c index b3334f38ef..2eec0f529d 100644 --- a/resolv/gai_misc.c +++ b/resolv/gai_misc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -23,10 +23,31 @@ #include <stdlib.h> #include <sys/time.h> -#include "gai_misc.h" +#include <gai_misc.h> +#ifndef gai_create_helper_thread +# define gai_create_helper_thread __gai_create_helper_thread + +extern inline int +__gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), + void *arg) +{ + pthread_attr_t attr; + + /* Make sure the thread is created detached. */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + + int ret = pthread_create (threadp, &attr, tf, arg); + + (void) pthread_attr_destroy (&attr); + return ret; +} +#endif + + /* Pool of request list entries. */ static struct requestlist **pool; @@ -229,16 +250,11 @@ __gai_enqueue_request (struct gaicb *gaicbp) if (nthreads < optim.gai_threads && idle_thread_count == 0) { pthread_t thid; - pthread_attr_t attr; newp->running = 1; - /* Make sure the thread is created detached. */ - pthread_attr_init (&attr); - pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); - /* Now try to start a thread. */ - if (pthread_create (&thid, &attr, handle_requests, newp) == 0) + if (gai_create_helper_thread (&thid, handle_requests, newp) == 0) /* We managed to enqueue the request. All errors which can happen now can be recognized by calls to `gai_error'. */ ++nthreads; diff --git a/resolv/gai_misc.h b/resolv/gai_misc.h index 48a93977ae..94005de02c 100644 --- a/resolv/gai_misc.h +++ b/resolv/gai_misc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -29,7 +29,9 @@ struct waitlist { struct waitlist *next; +#ifndef DONT_NEED_GAI_MISC_COND pthread_cond_t *cond; +#endif volatile int *counterp; /* The next field is used in asynchronous `lio_listio' operations. */ struct sigevent *sigevp; diff --git a/resolv/gai_notify.c b/resolv/gai_notify.c index 987a64c0e2..c3ce0afb45 100644 --- a/resolv/gai_notify.c +++ b/resolv/gai_notify.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -20,15 +20,24 @@ #include <netdb.h> #include <pthread.h> #include <stdlib.h> +#include <gai_misc.h> -#include "gai_misc.h" +struct notify_func + { + void (*func) (sigval_t); + sigval_t value; + }; static void * notify_func_wrapper (void *arg) { - struct sigevent *sigev = arg; - sigev->sigev_notify_function (sigev->sigev_value); + gai_start_notify_thread (); + struct notify_func *const n = arg; + void (*func) (sigval_t) = n->func; + sigval_t value = n->value; + free (n); + (*func) (value); return NULL; } @@ -54,8 +63,26 @@ __gai_notify_only (struct sigevent *sigev, pid_t caller_pid) pattr = &attr; } - if (pthread_create (&tid, pattr, notify_func_wrapper, sigev) < 0) + /* SIGEV may be freed as soon as we return, so we cannot let the + notification thread use that pointer. Even though a sigval_t is + only one word and the same size as a void *, we cannot just pass + the value through pthread_create as the argument and have the new + thread run the user's function directly, because on some machines + the calling convention for a union like sigval_t is different from + that for a pointer type like void *. */ + struct notify_func *nf = malloc (sizeof *nf); + if (nf == NULL) result = -1; + else + { + nf->func = sigev->sigev_notify_function; + nf->value = sigev->sigev_value; + if (pthread_create (&tid, pattr, notify_func_wrapper, nf) < 0) + { + free (nf); + result = -1; + } + } } else if (sigev->sigev_notify == SIGEV_SIGNAL) /* We have to send a signal. */ @@ -79,15 +106,21 @@ __gai_notify (struct requestlist *req) { struct waitlist *next = waitlist->next; - /* Decrement the counter. This is used in both cases. */ - --*waitlist->counterp; - if (waitlist->sigevp == NULL) - pthread_cond_signal (waitlist->cond); + { +#ifdef DONT_NEED_GAI_MISC_COND + GAI_MISC_NOTIFY (waitlist); +#else + /* Decrement the counter. */ + --*waitlist->counterp; + + pthread_cond_signal (waitlist->cond); +#endif + } else /* This is part of a asynchronous `getaddrinfo_a' operation. If this request is the last one, send the signal. */ - if (*waitlist->counterp == 0) + if (--*waitlist->counterp == 0) { __gai_notify_only (waitlist->sigevp, waitlist->caller_pid); /* This is tricky. See getaddrinfo_a.c for the reason why diff --git a/resolv/gai_sigqueue.c b/resolv/gai_sigqueue.c index 2c91df6ddc..278a1d8026 100644 --- a/resolv/gai_sigqueue.c +++ b/resolv/gai_sigqueue.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -20,7 +20,7 @@ #include <errno.h> #include <signal.h> -#include "gai_misc.h" +#include <gai_misc.h> int __gai_sigqueue (sig, val, caller_pid) diff --git a/resolv/gai_suspend.c b/resolv/gai_suspend.c index bb3c9c3402..c2095124b7 100644 --- a/resolv/gai_suspend.c +++ b/resolv/gai_suspend.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -23,7 +23,7 @@ #include <stdlib.h> #include <sys/time.h> -#include "gai_misc.h" +#include <gai_misc.h> int @@ -32,9 +32,11 @@ gai_suspend (const struct gaicb *const list[], int ent, { struct waitlist waitlist[ent]; struct requestlist *requestlist[ent]; +#ifndef DONT_NEED_GAI_MISC_COND pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +#endif int cnt; - int dummy; + int cntr = 1; int none = 1; int result; @@ -50,9 +52,11 @@ gai_suspend (const struct gaicb *const list[], int ent, if (requestlist[cnt] != NULL) { +#ifndef DONT_NEED_GAI_MISC_COND waitlist[cnt].cond = &cond; +#endif waitlist[cnt].next = requestlist[cnt]->waiting; - waitlist[cnt].counterp = &dummy; + waitlist[cnt].counterp = &cntr; waitlist[cnt].sigevp = NULL; waitlist[cnt].caller_pid = 0; /* Not needed. */ requestlist[cnt]->waiting = &waitlist[cnt]; @@ -78,6 +82,9 @@ gai_suspend (const struct gaicb *const list[], int ent, which we must remove. So defer cancelation for now. */ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); +#ifdef DONT_NEED_GAI_MISC_COND + GAI_MISC_WAIT (result, cntr, timeout, 1); +#else if (timeout == NULL) result = pthread_cond_wait (&cond, &__gai_requests_mutex); else @@ -99,6 +106,7 @@ gai_suspend (const struct gaicb *const list[], int ent, result = pthread_cond_timedwait (&cond, &__gai_requests_mutex, &abstime); } +#endif /* Now remove the entry in the waiting list for all requests which didn't terminate. */ @@ -121,10 +129,12 @@ gai_suspend (const struct gaicb *const list[], int ent, /* Now it's time to restore the cancelation state. */ pthread_setcancelstate (oldstate, NULL); +#ifndef DONT_NEED_GAI_MISC_COND /* Release the conditional variable. */ if (pthread_cond_destroy (&cond) != 0) /* This must never happen. */ abort (); +#endif if (result != 0) { diff --git a/resolv/getaddrinfo_a.c b/resolv/getaddrinfo_a.c index abac27d361..f6af3aa45a 100644 --- a/resolv/getaddrinfo_a.c +++ b/resolv/getaddrinfo_a.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -23,7 +23,7 @@ #include <stdlib.h> #include <unistd.h> -#include "gai_misc.h" +#include <gai_misc.h> /* We need this special structure to handle asynchronous I/O. */ @@ -96,7 +96,9 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig) } else if (mode == GAI_WAIT) { +#ifndef DONT_NEED_GAI_MISC_COND pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +#endif struct waitlist waitlist[ent]; int oldstate; @@ -104,7 +106,9 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig) for (cnt = 0; cnt < ent; ++cnt) if (requests[cnt] != NULL) { +#ifndef DONT_NEED_GAI_MISC_COND waitlist[cnt].cond = &cond; +#endif waitlist[cnt].next = requests[cnt]->waiting; waitlist[cnt].counterp = &total; waitlist[cnt].sigevp = NULL; @@ -119,15 +123,24 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig) pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); while (total > 0) - pthread_cond_wait (&cond, &__gai_requests_mutex); + { +#ifdef DONT_NEED_GAI_MISC_COND + int result; + GAI_MISC_WAIT (result, total, NULL, 1); +#else + pthread_cond_wait (&cond, &__gai_requests_mutex); +#endif + } /* Now it's time to restore the cancelation state. */ pthread_setcancelstate (oldstate, NULL); +#ifndef DONT_NEED_GAI_MISC_COND /* Release the conditional variable. */ if (pthread_cond_destroy (&cond) != 0) /* This must never happen. */ abort (); +#endif } else { @@ -147,7 +160,9 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig) for (cnt = 0; cnt < ent; ++cnt) if (requests[cnt] != NULL) { +#ifndef DONT_NEED_GAI_MISC_COND waitlist->list[cnt].cond = NULL; +#endif waitlist->list[cnt].next = requests[cnt]->waiting; waitlist->list[cnt].counterp = &waitlist->counter; waitlist->list[cnt].sigevp = &waitlist->sigev; |