pike.git / src / threads.c

version» Context lines:

pike.git/src/threads.c:1:   /*   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: threads.c,v 1.231 2004/04/21 19:25:23 mast Exp $ + || $Id: threads.c,v 1.232 2004/04/23 13:43:30 grubba Exp $   */      #ifndef CONFIGURE_TEST   #include "global.h" - RCSID("$Id: threads.c,v 1.231 2004/04/21 19:25:23 mast Exp $"); + RCSID("$Id: threads.c,v 1.232 2004/04/23 13:43:30 grubba Exp $");      PMOD_EXPORT int num_threads = 1;   PMOD_EXPORT int threads_disabled = 0;   #endif /* !CONFIGURE_TEST */      /* #define PICKY_MUTEX */      #ifdef _REENTRANT      #ifndef CONFIGURE_TEST    -  + /* #define VERBOSE_THREADS_DEBUG */ +    #include "threads.h"   #include "array.h"   #include "mapping.h"   #include "object.h"   #include "pike_macros.h"   #include "callback.h"   #include "builtin_functions.h"   #include "constants.h"   #include "program.h"   #include "program_id.h"
pike.git/src/threads.c:991:    * so that we can avoid races.    *    * The main race is the one on current_object,    * since it at this point only has one reference.    *    * We also want the stuff in arg to be copied properly    * before we exit the function...    */    SWAP_OUT_CURRENT_THREAD();    while (thread_state->status == THREAD_NOT_STARTED) { -  THREADS_FPRINTF(0, (stderr, "THREAD_CREATE waiting...\n")); +  THREADS_FPRINTF(0, (stderr, "THREAD_CREATE %p waiting...\n", +  thread_state));    low_co_wait_interpreter(&thread_state->status_change);    }    SWAP_IN_CURRENT_THREAD();    } else {    free_array(arg.args);    Pike_error("Failed to create thread (errno = %d).\n", tmp);    }       THREADS_FPRINTF(0, (stderr, "THREAD_CREATE -> t:%08x\n",    (unsigned int)thread_state));
pike.git/src/threads.c:1320:   void init_mutex_obj(struct object *o)   {    co_init(& THIS_MUTEX->condition);    THIS_MUTEX->key=0;    THIS_MUTEX->num_waiting = 0;   }      void exit_mutex_obj(struct object *o)   {    struct mutex_storage *m = THIS_MUTEX; +  struct object *key = m->key;       THREADS_FPRINTF(1, (stderr, "DESTROYING MUTEX m:%p\n", THIS_MUTEX));    -  if(m->key) { -  destruct(m->key); +  if(key) {    m->key=0; -  +  destruct(key);    if(m->num_waiting)    {    THREADS_FPRINTF(1, (stderr, "DESTRUCTED MUTEX IS BEING WAITED ON\n"));   #ifdef PICKY_MUTEX    /* exit_mutex_key_obj has already signalled, but since the    * waiting threads will throw an error instead of making a new    * lock we need to double it to a broadcast. The last thread    * that stops waiting will destroy m->condition. */    co_broadcast (&m->condition);   #else
pike.git/src/threads.c:1382:   }      void exit_mutex_key_obj(struct object *o)   {    THREADS_FPRINTF(1, (stderr, "UNLOCK k:%p m:(%p) t:%p o:%p\n",    THIS_KEY, THIS_KEY->mut,    Pike_interpreter.thread_state, THIS_KEY->owner));    if(THIS_KEY->mut)    {    struct mutex_storage *mut = THIS_KEY->mut; +  struct object *mutex_obj;      #ifdef PIKE_DEBUG -  if(mut->key != o) -  Pike_fatal("Mutex unlock from wrong key %p != %p!\n",THIS_KEY->mut->key,o); +  /* Note: mut->key can be NULL if our corresponding mutex +  * has been destructed. +  */ +  if(mut->key && (mut->key != o)) +  Pike_fatal("Mutex unlock from wrong key %p != %p!\n", +  THIS_KEY->mut->key, o);   #endif    mut->key=0;    if (THIS_KEY->owner) {    THIS_KEY->owner = NULL;    }    if (THIS_KEY->owner_obj) {    free_object(THIS_KEY->owner_obj);    THIS_KEY->owner_obj=0;    }    THIS_KEY->mut=0;    THIS_KEY->initialized=0; -  +  mutex_obj = THIS_KEY->mutex_obj; +  THIS_KEY->mutex_obj = NULL;    if (mut->num_waiting) -  co_signal(& mut->condition); +  co_signal(&mut->condition);   #ifndef PICKY_MUTEX -  else if (!THIS_KEY->mutex_obj->prog) +  else if (!mutex_obj->prog)    co_destroy (&mut->condition);   #endif -  free_object (THIS_KEY->mutex_obj); -  THIS_KEY->mutex_obj = NULL; +  free_object(mutex_obj);    }   }      /*! @endclass    */      #define THIS_COND ((COND_T *)(CURRENT_STORAGE))      /*! @class Condition    *!
pike.git/src/threads.c:1480:    if(args > 1) {    pop_n_elems(args - 1);    args = 1;    }       c = THIS_COND;       /* Unlock mutex */    mut->key=0;    OB2KEY(key)->mut=0; +  mut->num_waiting++;    co_signal(& mut->condition);       /* Wait and allow mutex operations */    SWAP_OUT_CURRENT_THREAD();    co_wait_interpreter(c);    SWAP_IN_CURRENT_THREAD();       /* Lock mutex */    while(mut->key) {    SWAP_OUT_CURRENT_THREAD();    co_wait_interpreter(& mut->condition);    SWAP_IN_CURRENT_THREAD();    check_threads_etc();    }    mut->key=key;    OB2KEY(key)->mut=mut; -  +  mut->num_waiting--;       pop_stack();    return;   }      /*! @decl void signal()    *!    *! @[signal()] wakes up one of the threads currently waiting for the    *! condition.    *!
pike.git/src/threads.c:1618:    *! the value returned from the thread function.    */   static void f_thread_id_result(INT32 args)   {    struct thread_state *th=THIS_THREAD;       if (threads_disabled) {    Pike_error("Cannot wait for threads when threads are disabled!\n");    }    +  THREADS_FPRINTF(0, (stderr, +  "Thread->result(): Waiting for thread %p (state:%d).\n", +  th, th->status));    while(th->status != THREAD_EXITED) {    SWAP_OUT_CURRENT_THREAD();    co_wait_interpreter(&th->status_change);    SWAP_IN_CURRENT_THREAD();    check_threads_etc(); -  +  THREADS_FPRINTF(0, +  (stderr, +  "Thread->result(): Waiting for thread %p (state:%d).\n", +  th, th->status));    }       assign_svalue_no_free(Pike_sp, &th->result);    Pike_sp++;    dmalloc_touch_svalue(Pike_sp-1);   }      void init_thread_obj(struct object *o)   {    MEMSET(&THIS_THREAD->state, 0, sizeof(struct Pike_interpreter));