diff options
Diffstat (limited to 'libpthread/linuxthreads/manager.c')
| -rw-r--r-- | libpthread/linuxthreads/manager.c | 68 | 
1 files changed, 66 insertions, 2 deletions
diff --git a/libpthread/linuxthreads/manager.c b/libpthread/linuxthreads/manager.c index 5d355e107..78858eb65 100644 --- a/libpthread/linuxthreads/manager.c +++ b/libpthread/linuxthreads/manager.c @@ -38,6 +38,16 @@  #include "semaphore.h"  #include "debug.h" /* PDEBUG, added by StS */ + +/* poll() is not supported in kernel <= 2.0, therefore is __NR_poll is + * not available, we assume an old Linux kernel is in use and we will + * use select() instead. */ +#include <sys/syscall.h> +#ifndef __NR_poll +# define USE_SELECT +#endif + +  /* Array of active threads. Entry 0 is reserved for the initial thread. */  struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =  { { LOCK_INITIALIZER, &__pthread_initial_thread, 0}, @@ -104,7 +114,12 @@ static void pthread_kill_all_threads(int sig, int main_thread_also);  int __pthread_manager(void *arg)  {    int reqfd = (int) (long int) arg; +#ifdef USE_SELECT +  struct timeval tv; +  fd_set fd; +#else    struct pollfd ufd; +#endif    sigset_t mask;    int n;    struct pthread_request request; @@ -126,14 +141,23 @@ int __pthread_manager(void *arg)    /* Synchronize debugging of the thread manager */    n = __libc_read(reqfd, (char *)&request, sizeof(request));    ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG); +#ifndef USE_SELECT    ufd.fd = reqfd;    ufd.events = POLLIN; +#endif    /* Enter server loop */    while(1) { +#ifdef USE_SELECT +    tv.tv_sec = 2; +    tv.tv_usec = 0; +    FD_ZERO (&fd); +    FD_SET (reqfd, &fd); +    n = select (reqfd + 1, &fd, NULL, NULL, &tv); +#else  PDEBUG("before poll\n");      n = poll(&ufd, 1, 2000);  PDEBUG("after poll\n"); - +#endif      /* Check for termination of the main thread */      if (getppid() == 1) {        pthread_kill_all_threads(SIGKILL, 0); @@ -145,7 +169,13 @@ PDEBUG("after poll\n");        pthread_reap_children();      }      /* Read and execute request */ -    if (n == 1 && (ufd.revents & POLLIN)) { +#ifdef USE_SELECT +    if (n == 1) +#else +    if (n == 1 && (ufd.revents & POLLIN)) +#endif +    { +  PDEBUG("before __libc_read\n");        n = __libc_read(reqfd, (char *)&request, sizeof(request));  PDEBUG("after __libc_read, n=%d\n", n); @@ -488,6 +518,18 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,    /* Do the cloning.  We have to use two different functions depending       on whether we are debugging or not.  */    pid = 0;     /* Note that the thread never can have PID zero.  */ + + +  /* ******************************************************** */ +  /*  This code was moved from below to cope with running threads +   *  on uClinux systems.  See comment below... +   * Insert new thread in doubly linked list of active threads */  +  new_thread->p_prevlive = __pthread_main_thread; +  new_thread->p_nextlive = __pthread_main_thread->p_nextlive; +  __pthread_main_thread->p_nextlive->p_prevlive = new_thread; +  __pthread_main_thread->p_nextlive = new_thread; +  /* ********************************************************* */ +    if (report_events)      {        /* See whether the TD_CREATE event bit is set in any of the @@ -535,6 +577,14 @@ PDEBUG("cloning new_thread = %p\n", new_thread);  		  __pthread_sig_cancel, new_thread);    /* Check if cloning succeeded */    if (pid == -1) { +    /********************************************************  +     * Code inserted to remove the thread from our list of active +     * threads in case of failure (needed to cope with uClinux),  +     * See comment below. */ +    new_thread->p_nextlive->p_prevlive = new_thread->p_prevlive; +    new_thread->p_prevlive->p_nextlive = new_thread->p_nextlive; +    /********************************************************/ +      /* Free the stack if we allocated it */      if (attr == NULL || !attr->__stackaddr_set)        { @@ -553,11 +603,25 @@ PDEBUG("cloning new_thread = %p\n", new_thread);      return errno;    }  PDEBUG("new thread pid = %d\n", pid); + +#if 0 +  /* *********************************************************** +   This code has been moved before the call to clone().  In uClinux, +   the use of wait on a semaphore is dependant upon that the child so +   the child must be in the active threads list. This list is used in +   pthread_find_self() to get the pthread_descr of self. So, if the +   child calls sem_wait before this code is executed , it will hang +   forever and initial_thread will instead be posted by a sem_post +   call. */ +    /* Insert new thread in doubly linked list of active threads */    new_thread->p_prevlive = __pthread_main_thread;    new_thread->p_nextlive = __pthread_main_thread->p_nextlive;    __pthread_main_thread->p_nextlive->p_prevlive = new_thread;    __pthread_main_thread->p_nextlive = new_thread; +  /************************************************************/ +#endif +    /* Set pid field of the new thread, in case we get there before the       child starts. */    new_thread->p_pid = pid;  | 
