From 14ffbc8350791ff0f33ccc65af26ebaa1b520132 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 27 Feb 2004 08:09:35 +0000 Subject: [PATCH] Update. * pthread_attr_setschedparam.c: Don't test priority against limits here. Set ATTR_FLAG_SCHED_SET flag. * pthread_attr_setschedpolicy.c: Set ATTR_FLAG_POLICY_SET flag. * pthread_create.c (__pthread_create_2_1): Copy scheduling attributes from parent thread to child. If attribute is used and scheduling parameters are not inherited, copy parameters from attribute or compute them. Check priority value. * pthread_getschedparam.c: If the parameters aren't known yet get them from the kernel. * pthread_setschedparam.c: Set ATTR_FLAG_SCHED_SET and ATTR_FLAG_POLICY_SET flag for thread. * sysdeps/unix/sysv/linux/internaltypes.h: Define ATTR_FLAG_SCHED_SET and ATTR_FLAG_POLICY_SET. * sysdeps/pthread/createthread.c: Use tgkill if possible. --- nptl/ChangeLog | 16 ++++++++ nptl/pthread_attr_setschedparam.c | 18 +++------ nptl/pthread_attr_setschedpolicy.c | 5 ++- nptl/pthread_create.c | 57 ++++++++++++++++++++-------- nptl/pthread_getschedparam.c | 35 ++++++++++++++--- nptl/pthread_setschedparam.c | 3 +- nptl/sysdeps/pthread/createthread.c | 20 +++++++++- nptl/sysdeps/unix/sysv/linux/internaltypes.h | 4 +- 8 files changed, 120 insertions(+), 38 deletions(-) diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 8fb8dd4..10250ae 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,5 +1,21 @@ 2004-02-26 Ulrich Drepper + * pthread_attr_setschedparam.c: Don't test priority against limits + here. Set ATTR_FLAG_SCHED_SET flag. + * pthread_attr_setschedpolicy.c: Set ATTR_FLAG_POLICY_SET flag. + * pthread_create.c (__pthread_create_2_1): Copy scheduling attributes + from parent thread to child. If attribute is used and scheduling + parameters are not inherited, copy parameters from attribute or + compute them. Check priority value. + * pthread_getschedparam.c: If the parameters aren't known yet get + them from the kernel. + * pthread_setschedparam.c: Set ATTR_FLAG_SCHED_SET and + ATTR_FLAG_POLICY_SET flag for thread. + * sysdeps/unix/sysv/linux/internaltypes.h: Define ATTR_FLAG_SCHED_SET + and ATTR_FLAG_POLICY_SET. + + * sysdeps/pthread/createthread.c: Use tgkill if possible. + * pthread_attr_getstackaddr.c (__pthread_attr_getstackaddr): Don't fail if stack address hasn't been set. Just return 0. diff --git a/nptl/pthread_attr_setschedparam.c b/nptl/pthread_attr_setschedparam.c index aa36532..976ad13 100644 --- a/nptl/pthread_attr_setschedparam.c +++ b/nptl/pthread_attr_setschedparam.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -28,23 +28,15 @@ __pthread_attr_setschedparam (attr, param) pthread_attr_t *attr; const struct sched_param *param; { - struct pthread_attr *iattr; - int max_prio; - int min_prio; - assert (sizeof (*attr) >= sizeof (struct pthread_attr)); - iattr = (struct pthread_attr *) attr; - - max_prio = __sched_get_priority_max (iattr->schedpolicy); - min_prio = __sched_get_priority_min (iattr->schedpolicy); - - /* Catch invalid values. */ - if (param->sched_priority < min_prio || param->sched_priority > max_prio) - return EINVAL; + struct pthread_attr *iattr = (struct pthread_attr *) attr; /* Copy the new values. */ memcpy (&iattr->schedparam, param, sizeof (struct sched_param)); + /* Remember we set the value. */ + iattr->flags |= ATTR_FLAG_SCHED_SET; + return 0; } strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam) diff --git a/nptl/pthread_attr_setschedpolicy.c b/nptl/pthread_attr_setschedpolicy.c index 73a7c44..b9710d5 100644 --- a/nptl/pthread_attr_setschedpolicy.c +++ b/nptl/pthread_attr_setschedpolicy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -39,6 +39,9 @@ __pthread_attr_setschedpolicy (attr, policy) /* Store the new values. */ iattr->schedpolicy = policy; + /* Remember we set the value. */ + iattr->flags |= ATTR_FLAG_POLICY_SET; + return 0; } strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy) diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index f8ab269..014c41b 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -386,7 +386,9 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg) pd->arg = arg; /* Copy the thread attribute flags. */ - pd->flags = iattr->flags; + struct pthread *self = THREAD_SELF; + pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) + | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))); /* Initialize the field for the ID of the thread which is waiting for us. This is a self-reference in case the thread is created @@ -394,25 +396,49 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg) pd->joinid = iattr->flags & ATTR_FLAG_DETACHSTATE ? pd : NULL; /* The debug events are inherited from the parent. */ - pd->eventbuf = THREAD_SELF->eventbuf; + pd->eventbuf = self->eventbuf; + + /* Copy the parent's scheduling parameters. The flags will say what + is valid and what is not. */ + pd->schedpolicy = self->schedpolicy; + pd->schedparam = self->schedparam; - /* Determine scheduling parameters for the thread. - XXX How to determine whether scheduling handling is needed? */ - if (0 && attr != NULL) + /* Determine scheduling parameters for the thread. */ + if (attr != NULL + && __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0) + && (iattr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) != 0) { - if (iattr->flags & ATTR_FLAG_NOTINHERITSCHED) + INTERNAL_SYSCALL_DECL (err); + + /* Use the scheduling parameters the user provided. */ + if (iattr->flags & ATTR_FLAG_POLICY_SET) + pd->schedpolicy = iattr->schedpolicy; + else if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) { - /* Use the scheduling parameters the user provided. */ - pd->schedpolicy = iattr->schedpolicy; - memcpy (&pd->schedparam, &iattr->schedparam, - sizeof (struct sched_param)); + pd->schedpolicy = INTERNAL_SYSCALL (sched_getscheduler, err, 1, 0); + pd->flags |= ATTR_FLAG_POLICY_SET; } - else + + if (iattr->flags & ATTR_FLAG_SCHED_SET) + memcpy (&pd->schedparam, &iattr->schedparam, + sizeof (struct sched_param)); + else if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) + { + INTERNAL_SYSCALL (sched_getparam, err, 2, 0, &pd->schedparam); + pd->flags |= ATTR_FLAG_SCHED_SET; + } + + /* Check for valid priorities. */ + int minprio = INTERNAL_SYSCALL (sched_get_priority_min, err, 1, + iattr->schedpolicy); + int maxprio = INTERNAL_SYSCALL (sched_get_priority_max, err, 1, + iattr->schedpolicy); + if (pd->schedparam.sched_priority < minprio + || pd->schedparam.sched_priority > maxprio) { - /* Just store the scheduling attributes of the parent. */ - pd->schedpolicy = __sched_getscheduler (0); - __sched_getparam (0, &pd->schedparam); + err = EINVAL; + goto errout; } } @@ -423,6 +449,7 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg) err = create_thread (pd, iattr, STACK_VARIABLES_ARGS); if (err != 0) { + errout: /* Something went wrong. Free the resources. */ __deallocate_stack (pd); return err; diff --git a/nptl/pthread_getschedparam.c b/nptl/pthread_getschedparam.c index d9d6cb4..434d867 100644 --- a/nptl/pthread_getschedparam.c +++ b/nptl/pthread_getschedparam.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -36,8 +36,10 @@ __pthread_getschedparam (threadid, policy, param) /* Not a valid thread handle. */ return ESRCH; + int result = 0; + /* We have to handle cancellation in the following code since we are - locking another threads desriptor. */ + locking another threads descriptor. */ pthread_cleanup_push ((void (*) (void *)) lll_unlock_wake_cb, &pd->lock); lll_lock (pd->lock); @@ -45,14 +47,35 @@ __pthread_getschedparam (threadid, policy, param) /* The library is responsible for maintaining the values at all times. If the user uses a interface other than pthread_setschedparam to modify the scheduler setting it is not - the library's problem. */ - *policy = pd->schedpolicy; - memcpy (param, &pd->schedparam, sizeof (struct sched_param)); + the library's problem. In case the descriptor's values have + not yet been retrieved do it now. */ + if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) + { + if (__sched_getparam (pd->tid, &pd->schedparam) != 0) + result = 1; + else + pd->flags |= ATTR_FLAG_SCHED_SET; + } + + if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) + { + pd->schedpolicy = __sched_getscheduler (pd->tid); + if (pd->schedpolicy == -1) + result = 1; + else + pd->flags |= ATTR_FLAG_POLICY_SET; + } + + if (result == 0) + { + *policy = pd->schedpolicy; + memcpy (param, &pd->schedparam, sizeof (struct sched_param)); + } lll_unlock (pd->lock); pthread_cleanup_pop (0); - return 0; + return result; } strong_alias (__pthread_getschedparam, pthread_getschedparam) diff --git a/nptl/pthread_setschedparam.c b/nptl/pthread_setschedparam.c index 3084836..5889cc9 100644 --- a/nptl/pthread_setschedparam.c +++ b/nptl/pthread_setschedparam.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -55,6 +55,7 @@ __pthread_setschedparam (threadid, policy, param) change in the thread descriptor. */ pd->schedpolicy = policy; memcpy (&pd->schedparam, param, sizeof (struct sched_param)); + pd->flags |= ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET; } lll_unlock (pd->lock); diff --git a/nptl/sysdeps/pthread/createthread.c b/nptl/sysdeps/pthread/createthread.c index c4695fc..58a7b63 100644 --- a/nptl/sysdeps/pthread/createthread.c +++ b/nptl/sysdeps/pthread/createthread.c @@ -93,11 +93,24 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr, send it the cancellation signal. */ INTERNAL_SYSCALL_DECL (err2); err_out: +#if __ASSUME_TGKILL + (void) INTERNAL_SYSCALL (tgkill, err2, 3, + THREAD_GETMEM (THREAD_SELF, pid), + pd->tid, SIGCANCEL); + +# ifdef __ASSUME_CLONE_STOPPED + /* Then wake it up so that the signal can be processed. */ + (void) INTERNAL_SYSCALL (tgkill, err2, 3, + THREAD_GETMEM (THREAD_SELF, pid), + pd->tid, SIGCONT); +# endif +#else (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL); -#ifdef __ASSUME_CLONE_STOPPED +# ifdef __ASSUME_CLONE_STOPPED /* Then wake it up so that the signal can be processed. */ (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCONT); +# endif #endif return INTERNAL_SYSCALL_ERRNO (res, err); @@ -116,7 +129,12 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr, #ifdef __ASSUME_CLONE_STOPPED /* Now start the thread for real. */ +# if __ASSUME_TGKILL + res = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + pd->tid, SIGCONT); +# else res = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, SIGCONT); +# endif /* If something went wrong, kill the thread. */ if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) diff --git a/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/internaltypes.h index 39afb32..10d0d95 100644 --- a/nptl/sysdeps/unix/sysv/linux/internaltypes.h +++ b/nptl/sysdeps/unix/sysv/linux/internaltypes.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -48,6 +48,8 @@ struct pthread_attr #define ATTR_FLAG_SCOPEPROCESS 0x0004 #define ATTR_FLAG_STACKADDR 0x0008 #define ATTR_FLAG_OLDATTR 0x0010 +#define ATTR_FLAG_SCHED_SET 0x0020 +#define ATTR_FLAG_POLICY_SET 0x0040 /* Mutex attribute data structure. */ -- 2.7.4