Browse Source

sync some style changes and stack fixes with glibc

Mike Frysinger 20 years ago
parent
commit
c196ed5c18
1 changed files with 88 additions and 12 deletions
  1. 88 12
      libpthread/linuxthreads/manager.c

+ 88 - 12
libpthread/linuxthreads/manager.c

@@ -14,9 +14,12 @@
 
 
 /* The "thread manager" thread: manages creation and termination of threads */
 /* The "thread manager" thread: manages creation and termination of threads */
 
 
-/* mods for uClibc: getpwd and getpagesize are the syscalls */
+/* mods for uClibc */
 #define __getpid getpid
 #define __getpid getpid
 #define __getpagesize getpagesize
 #define __getpagesize getpagesize
+#define __sched_get_priority_max sched_get_priority_max
+#define __sched_getscheduler sched_getscheduler
+#define __sched_getparam sched_getparam
 
 
 #include <features.h>
 #include <features.h>
 #define __USE_GNU
 #define __USE_GNU
@@ -81,8 +84,13 @@ volatile pthread_descr __pthread_last_event;
 
 
 static inline pthread_descr thread_segment(int seg)
 static inline pthread_descr thread_segment(int seg)
 {
 {
+# ifdef _STACK_GROWS_UP
+  return (pthread_descr)(THREAD_STACK_START_ADDRESS + (seg - 1) * STACK_SIZE)
+         + 1;
+# else
   return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE)
   return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE)
          - 1;
          - 1;
+# endif
 }
 }
 
 
 /* Flag set in signal handler to record child termination */
 /* Flag set in signal handler to record child termination */
@@ -149,7 +157,7 @@ __pthread_manager(void *arg)
   sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
   sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
   sigdelset(&manager_mask, SIGTRAP);            /* for debugging purposes */
   sigdelset(&manager_mask, SIGTRAP);            /* for debugging purposes */
   if (__pthread_threads_debug && __pthread_sig_debug > 0)
   if (__pthread_threads_debug && __pthread_sig_debug > 0)
-      sigdelset(&manager_mask, __pthread_sig_debug);
+    sigdelset(&manager_mask, __pthread_sig_debug);
   sigprocmask(SIG_SETMASK, &manager_mask, NULL);
   sigprocmask(SIG_SETMASK, &manager_mask, NULL);
   /* Raise our priority to match that of main thread */
   /* Raise our priority to match that of main thread */
   __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
   __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
@@ -245,10 +253,12 @@ __pthread_manager(void *arg)
         PDEBUG("got REQ_DEBUG\n");
         PDEBUG("got REQ_DEBUG\n");
 	/* Make gdb aware of new thread and gdb will restart the
 	/* Make gdb aware of new thread and gdb will restart the
 	   new thread when it is ready to handle the new thread. */
 	   new thread when it is ready to handle the new thread. */
-	if (__pthread_threads_debug && __pthread_sig_debug > 0) {
-      PDEBUG("about to call raise(__pthread_sig_debug)\n");
+	if (__pthread_threads_debug && __pthread_sig_debug > 0)
+	{
+	  PDEBUG("about to call raise(__pthread_sig_debug)\n");
 	  raise(__pthread_sig_debug);
 	  raise(__pthread_sig_debug);
 	}
 	}
+        break;
       case REQ_KICK:
       case REQ_KICK:
 	/* This is just a prod to get the manager to reap some
 	/* This is just a prod to get the manager to reap some
 	   threads right away, avoiding a potential delay at shutdown. */
 	   threads right away, avoiding a potential delay at shutdown. */
@@ -279,6 +289,7 @@ int __pthread_manager_event(void *arg)
 }
 }
 
 
 /* Process creation */
 /* Process creation */
+
 static int
 static int
 __attribute__ ((noreturn))
 __attribute__ ((noreturn))
 pthread_start_thread(void *arg)
 pthread_start_thread(void *arg)
@@ -286,9 +297,16 @@ pthread_start_thread(void *arg)
   pthread_descr self = (pthread_descr) arg;
   pthread_descr self = (pthread_descr) arg;
   struct pthread_request request;
   struct pthread_request request;
   void * outcome;
   void * outcome;
+#if HP_TIMING_AVAIL
+  hp_timing_t tmpclock;
+#endif
   /* Initialize special thread_self processing, if any.  */
   /* Initialize special thread_self processing, if any.  */
 #ifdef INIT_THREAD_SELF
 #ifdef INIT_THREAD_SELF
   INIT_THREAD_SELF(self, self->p_nr);
   INIT_THREAD_SELF(self, self->p_nr);
+#endif
+#if HP_TIMING_AVAIL
+  HP_TIMING_NOW (tmpclock);
+  THREAD_SETMEM (self, p_cpuclock_offset, tmpclock);
 #endif
 #endif
   PDEBUG("\n");
   PDEBUG("\n");
   /* Make sure our pid field is initialized, just in case we get there
   /* Make sure our pid field is initialized, just in case we get there
@@ -363,12 +381,39 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
 
 
   if (attr != NULL && attr->__stackaddr_set)
   if (attr != NULL && attr->__stackaddr_set)
     {
     {
+#ifdef _STACK_GROWS_UP
       /* The user provided a stack. */
       /* The user provided a stack. */
+# ifdef USE_TLS
+      /* This value is not needed.  */
+      new_thread = (pthread_descr) attr->__stackaddr;
+      new_thread_bottom = (char *) new_thread;
+# else
+      new_thread = (pthread_descr) attr->__stackaddr;
+      new_thread_bottom = (char *) (new_thread + 1);
+# endif
+      guardaddr = attr->__stackaddr + attr->__stacksize;
+      guardsize = 0;
+#else
+      /* The user provided a stack.  For now we interpret the supplied
+	 address as 1 + the highest addr. in the stack segment.  If a
+	 separate register stack is needed, we place it at the low end
+	 of the segment, relying on the associated stacksize to
+	 determine the low end of the segment.  This differs from many
+	 (but not all) other pthreads implementations.  The intent is
+	 that on machines with a single stack growing toward higher
+	 addresses, stackaddr would be the lowest address in the stack
+	 segment, so that it is consistently close to the initial sp
+	 value. */
+# ifdef USE_TLS
+      new_thread = (pthread_descr) attr->__stackaddr;
+# else
       new_thread =
       new_thread =
         (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1;
         (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1;
+# endif
       new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;
       new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;
       guardaddr = NULL;
       guardaddr = NULL;
       guardsize = 0;
       guardsize = 0;
+#endif
       __pthread_nonstandard_stacks = 1;
       __pthread_nonstandard_stacks = 1;
     }
     }
   else
   else
@@ -493,7 +538,7 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
 
 
   /* First check whether we have to change the policy and if yes, whether
   /* First check whether we have to change the policy and if yes, whether
      we can  do this.  Normally this should be done by examining the
      we can  do this.  Normally this should be done by examining the
-     return value of the sched_setscheduler call in pthread_start_thread
+     return value of the __sched_setscheduler call in pthread_start_thread
      but this is hard to implement.  FIXME  */
      but this is hard to implement.  FIXME  */
   if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
   if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0)
     return EPERM;
     return EPERM;
@@ -546,8 +591,8 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
 	      sizeof (struct sched_param));
 	      sizeof (struct sched_param));
       break;
       break;
     case PTHREAD_INHERIT_SCHED:
     case PTHREAD_INHERIT_SCHED:
-      new_thread->p_start_args.schedpolicy = sched_getscheduler(father_pid);
-      sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
+      new_thread->p_start_args.schedpolicy = __sched_getscheduler(father_pid);
+      __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
       break;
       break;
     }
     }
     new_thread->p_priority =
     new_thread->p_priority =
@@ -588,17 +633,36 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
 	  __pthread_lock(new_thread->p_lock, NULL);
 	  __pthread_lock(new_thread->p_lock, NULL);
 
 
 	  /* We have to report this event.  */
 	  /* We have to report this event.  */
+#ifdef NEED_SEPARATE_REGISTER_STACK
+	  /* Perhaps this version should be used on all platforms. But
+	   this requires that __clone2 be uniformly supported
+	   everywhere.
+
+	   And there is some argument for changing the __clone2
+	   interface to pass sp and bsp instead, making it more IA64
+	   specific, but allowing stacks to grow outward from each
+	   other, to get less paging and fewer mmaps.  */
+	  pid = __clone2(pthread_start_thread_event,
+  		 (void **)new_thread_bottom,
+			 (char *)stack_addr - new_thread_bottom,
+			 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			 __pthread_sig_cancel, new_thread);
+#elif _STACK_GROWS_UP
+	  pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom,
+			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+			__pthread_sig_cancel, new_thread);
+#else
 	  pid = clone(pthread_start_thread_event, (void **) new_thread,
 	  pid = clone(pthread_start_thread_event, (void **) new_thread,
 			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
 			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
 			__pthread_sig_cancel, new_thread);
 			__pthread_sig_cancel, new_thread);
-
+#endif
 	  saved_errno = errno;
 	  saved_errno = errno;
 	  if (pid != -1)
 	  if (pid != -1)
 	    {
 	    {
 	      /* Now fill in the information about the new thread in
 	      /* Now fill in the information about the new thread in
-	         the newly created thread's data structure.  We cannot let
-	         the new thread do this since we don't know whether it was
-	         already scheduled when we send the event.  */
+		 the newly created thread's data structure.  We cannot let
+		 the new thread do this since we don't know whether it was
+		 already scheduled when we send the event.  */
 	      new_thread->p_eventbuf.eventdata = new_thread;
 	      new_thread->p_eventbuf.eventdata = new_thread;
 	      new_thread->p_eventbuf.eventnum = TD_CREATE;
 	      new_thread->p_eventbuf.eventnum = TD_CREATE;
 	      __pthread_last_event = new_thread;
 	      __pthread_last_event = new_thread;
@@ -619,9 +683,21 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
   if (pid == 0)
   if (pid == 0)
     {
     {
       PDEBUG("cloning new_thread = %p\n", new_thread);
       PDEBUG("cloning new_thread = %p\n", new_thread);
+#ifdef NEED_SEPARATE_REGISTER_STACK
+      pid = __clone2(pthread_start_thread,
+		     (void **)new_thread_bottom,
+                     (char *)stack_addr - new_thread_bottom,
+		     CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		     __pthread_sig_cancel, new_thread);
+#elif _STACK_GROWS_UP
+      pid = __clone(pthread_start_thread, (void *) new_thread_bottom,
+		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+		    __pthread_sig_cancel, new_thread);
+#else
       pid = clone(pthread_start_thread, (void **) new_thread,
       pid = clone(pthread_start_thread, (void **) new_thread,
 		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
 		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
 		    __pthread_sig_cancel, new_thread);
 		    __pthread_sig_cancel, new_thread);
+#endif /* !NEED_SEPARATE_REGISTER_STACK */
       saved_errno = errno;
       saved_errno = errno;
     }
     }
   /* Check if cloning succeeded */
   /* Check if cloning succeeded */
@@ -922,7 +998,7 @@ void __pthread_manager_adjust_prio(int thread_prio)
 
 
   if (thread_prio <= __pthread_manager_thread.p_priority) return;
   if (thread_prio <= __pthread_manager_thread.p_priority) return;
   param.sched_priority =
   param.sched_priority =
-    thread_prio < sched_get_priority_max(SCHED_FIFO)
+    thread_prio < __sched_get_priority_max(SCHED_FIFO)
     ? thread_prio + 1 : thread_prio;
     ? thread_prio + 1 : thread_prio;
   sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param);
   sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param);
   __pthread_manager_thread.p_priority = thread_prio;
   __pthread_manager_thread.p_priority = thread_prio;