[uClibc]pthreads patches

Arne Jonsson arne.jonsson at i3micro.com
Tue Oct 22 06:20:02 UTC 2002


Hello!

We are using pthreads quite heavily and have experienced some races and
have therefore made some changes to the code in order for our
application to work correctly.
I'm a little curious why nobody else have experienced problems, we
surely can't be the only one using pthreads and uClinux 2.0.38?

In the patches below is also some code changing the system call poll to
select as the poll call isn't supported in 2.0 kernel.

Would it be possible to introduce some means to indicate which kernel
version the uClibc is to be used against, I believe this is necessary as
the kernels seems to disagree on the system calls supported (and other
stuff)? 

The patches are made against manager.c and pthread.c in 0.9.15 but the
latest version in CVS seems to be the same as in 0.9.15.

Best regards,
/Arne Jonsson

-- 
Arne Jonsson
i3 micro technology AB
Phone:+46-8-506 388 00
Fax:  +46-8-506 388 75
-------------- next part --------------
*** libpthread/linuxthreads/manager.c.submit_to_uclibc.org	Mon Oct 21 16:50:22 2002
--- libpthread/linuxthreads/manager.c.org	Wed Feb 20 10:18:44 2002
***************
*** 14,22 ****
  
  /* The "thread manager" thread: manages creation and termination of threads */
  
- /* poll is not supported in kernel <= 2.0, therefore substituted using select */
- //#define USE_SELECT
- 
  /* mods for uClibc: getpwd and getpagesize are the syscalls */
  #define __getpid getpid
  #define __getpagesize getpagesize
--- 14,19 ----
***************
*** 107,118 ****
  int __pthread_manager(void *arg)
  {
    int reqfd = (int) (long int) arg;
- #ifndef USE_SELECT
    struct pollfd ufd;
- #else
-   struct timeval tv;
-   fd_set fd;
- #endif
    sigset_t mask;
    int n;
    struct pthread_request request;
--- 104,110 ----
***************
*** 134,156 ****
    /* 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) {
- #ifndef USE_SELECT
  PDEBUG("before poll\n");
      n = poll(&ufd, 1, 2000);
  PDEBUG("after poll\n");
! #else
!     tv.tv_sec = 2;
!     tv.tv_usec = 0;
!     FD_ZERO (&fd);
!     FD_SET (reqfd, &fd);
!     n = select (reqfd + 1, &fd, NULL, NULL, &tv);
! #endif
      /* Check for termination of the main thread */
      if (getppid() == 1) {
        pthread_kill_all_threads(SIGKILL, 0);
--- 126,139 ----
    /* Synchronize debugging of the thread manager */
    n = __libc_read(reqfd, (char *)&request, sizeof(request));
    ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG);
    ufd.fd = reqfd;
    ufd.events = POLLIN;
    /* Enter server loop */
    while(1) {
  PDEBUG("before poll\n");
      n = poll(&ufd, 1, 2000);
  PDEBUG("after poll\n");
! 
      /* Check for termination of the main thread */
      if (getppid() == 1) {
        pthread_kill_all_threads(SIGKILL, 0);
***************
*** 162,173 ****
        pthread_reap_children();
      }
      /* Read and execute request */
- #ifndef USE_SELECT
      if (n == 1 && (ufd.revents & POLLIN)) {
- #else
-     if (n == 1) {
- #endif
- 
  PDEBUG("before __libc_read\n");
        n = __libc_read(reqfd, (char *)&request, sizeof(request));
  PDEBUG("after __libc_read, n=%d\n", n);
--- 145,151 ----
***************
*** 510,527 ****
    /* 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 is moved from below, 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
--- 488,493 ----
***************
*** 569,581 ****
  		  __pthread_sig_cancel, new_thread);
    /* Check if cloning succeeded */
    if (pid == -1) {
-     /********************************************************/
-     // Code inserted to unlink in case of failure, see comment below!
-     /* Remove thread from list of active threads */
-     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)
        {
--- 535,540 ----
***************
*** 594,614 ****
      return errno;
    }
  PDEBUG("new thread pid = %d\n", pid);
!   /* ***********************************************************
!    This code is moved to before clone (). Because, in uClinux,
!    the use of wait on a semaphore is dependant upon that 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;
-   *********************************************************** */
- 
    /* Set pid field of the new thread, in case we get there before the
       child starts. */
    new_thread->p_pid = pid;
--- 553,563 ----
      return errno;
    }
  PDEBUG("new thread pid = %d\n", pid);
!   /* 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;
    /* Set pid field of the new thread, in case we get there before the
       child starts. */
    new_thread->p_pid = pid;

-------------- next part --------------
*** libpthread/linuxthreads/pthread.c.submit_to_uclibc.org	Tue Oct 22 07:16:37 2002
--- libpthread/linuxthreads/pthread.c.org	Fri Aug 30 11:12:15 2002
***************
*** 14,22 ****
  
  /* Thread creation, initialization, and basic low-level routines */
  
- /* Use changed __pthread_find_self */
- #define FIND_SELF
- 
  #define __FORCE_GLIBC
  #include <features.h>
  #include <errno.h>
--- 14,19 ----
***************
*** 491,507 ****
  pthread_descr __pthread_find_self()
  {
    char * sp = CURRENT_STACK_FRAME;
- #ifdef FIND_SELF
-   pthread_descr th = __pthread_initial_thread.p_nextlive ;
- 
-   while (th != &__pthread_initial_thread) {
-     if ((sp <= (char*)th ) && ( sp >= __pthread_handles[th->p_nr].h_bottom)) {
-       return th;
-     }
-     th = th->p_nextlive ;
-   }
-   return NULL;
- #else
    pthread_handle h;
  
    /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is
--- 488,493 ----
***************
*** 517,523 ****
  #endif
  
    return h->h_descr;
- #endif /* FIND_SELF */
  }
  
  #endif
--- 503,508 ----



More information about the uClibc mailing list