about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nptl/ChangeLog16
-rw-r--r--nptl/pthread_attr_setschedparam.c18
-rw-r--r--nptl/pthread_attr_setschedpolicy.c5
-rw-r--r--nptl/pthread_create.c57
-rw-r--r--nptl/pthread_getschedparam.c35
-rw-r--r--nptl/pthread_setschedparam.c3
-rw-r--r--nptl/sysdeps/pthread/createthread.c20
-rw-r--r--nptl/sysdeps/unix/sysv/linux/internaltypes.h4
8 files changed, 120 insertions, 38 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 8fb8dd4920..10250ae3e9 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,5 +1,21 @@
 2004-02-26  Ulrich Drepper  <drepper@redhat.com>
 
+	* 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 aa365326c4..976ad13873 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 <drepper@redhat.com>, 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 73a7c4425a..b9710d57a5 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 <drepper@redhat.com>, 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 f8ab269bdd..014c41b7a4 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 <drepper@redhat.com>, 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 d9d6cb43b0..434d867779 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 <drepper@redhat.com>, 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 3084836ad8..5889cc98a9 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 <drepper@redhat.com>, 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 c4695fced3..58a7b637a1 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 39afb32aac..10d0d95518 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 <drepper@redhat.com>, 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.  */