This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: The problem with __pthread_manager_adjust_prio


On Wed, Mar 20, 2002 at 04:50:08PM -0800, H . J . Lu wrote:
> There is a race condition between __pthread_manager_adjust_prio
> called from pthread_setschedparam and pthread_start_thread on
> manager_thread->p_priority. When a thread is calling
> pthread_setschedparam, the new thread may inherit SCHED_FIFO from
> the manager thread. That is
> 
> Thread A calls pthread_setschedparam
>   calls __pthread_manager_adjust_prio
>     calls __sched_setscheduler (SCHED_FIFO) on the manager thread.
> The main thread calls pthread_create
>   The manager threads calls pthread_start_thread. It does
> 
> 	if (manager_thread->p_priority > 0)
> 	  __sched_setscheduler (SCHED_OTHER)
> 
> Since manager_thread->p_priority may not be changed by
> __pthread_manager_adjust_prio yet, the new thread may inherit
> SCHED_FIFO. Here is a patch. the worst case is pthread_start_thread
> may call __sched_setscheduler (SCHED_OTHER) before 
> __sched_setscheduler (SCHED_FIFO) is called on the manager thread.
> 

A new patch with spinlock.


H.J.
----
2002-03-20  H.J. Lu  <hjl@gnu.org>

	* manager.c (pthread_start_thread): Protect accees to
	manager_thread->p_priority with manager_thread->p_lock.
	(__pthread_manager_adjust_prio): Likewise.

--- linuxthreads/manager.c.sched	Wed Mar 20 23:35:52 2002
+++ linuxthreads/manager.c	Thu Mar 21 00:05:34 2002
@@ -295,15 +295,24 @@ pthread_start_thread(void *arg)
     __sched_setscheduler(THREAD_GETMEM(self, p_pid),
 			 THREAD_GETMEM(self, p_start_args.schedpolicy),
                          &self->p_start_args.schedparam);
-  else if (manager_thread->p_priority > 0)
-    /* Default scheduling required, but thread manager runs in realtime
-       scheduling: switch new thread to SCHED_OTHER policy */
+  else
     {
-      struct sched_param default_params;
-      default_params.sched_priority = 0;
-      __sched_setscheduler(THREAD_GETMEM(self, p_pid),
-                           SCHED_OTHER, &default_params);
+      int set_sched;
+      __pthread_lock(manager_thread->p_lock, NULL);
+      set_sched = manager_thread->p_priority > 0;
+      __pthread_unlock(manager_thread->p_lock);
+      if (set_sched)
+	/* Default scheduling required, but thread manager runs in
+	   realtime scheduling: switch new thread to SCHED_OTHER
+	   policy */
+	{
+	  struct sched_param default_params;
+	  default_params.sched_priority = 0;
+	  __sched_setscheduler(THREAD_GETMEM(self, p_pid),
+			       SCHED_OTHER, &default_params);
+	}
     }
+
   /* Make gdb aware of new thread */
   if (__pthread_threads_debug && __pthread_sig_debug > 0) {
     request.req_thread = self;
@@ -1076,12 +1085,20 @@ void __pthread_manager_sighandler(int si
 
 void __pthread_manager_adjust_prio(int thread_prio)
 {
-  struct sched_param param;
+  int set_sched;
 
-  if (thread_prio <= manager_thread->p_priority) return;
-  param.sched_priority =
-    thread_prio < __sched_get_priority_max(SCHED_FIFO)
-    ? thread_prio + 1 : thread_prio;
-  __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, &param);
-  manager_thread->p_priority = thread_prio;
+  __pthread_lock(manager_thread->p_lock, NULL);
+  set_sched = thread_prio > manager_thread->p_priority;
+  if (set_sched)
+    manager_thread->p_priority = thread_prio;
+  __pthread_unlock(manager_thread->p_lock);
+
+  if (set_sched)
+    {
+      struct sched_param param;
+      param.sched_priority =
+	thread_prio < __sched_get_priority_max(SCHED_FIFO)
+	? thread_prio + 1 : thread_prio;
+      __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, &param);
+    }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]