pike.git / src / threads.c

version» Context lines:

pike.git/src/threads.c:2112:      #define THIS_MUTEX ((struct mutex_storage *)(CURRENT_STORAGE))         /* Note:    * No reference is kept to the key object, it is destructed if the    * mutex is destructed. The key pointer is set to zero by the    * key object when the key is destructed.    */    + struct key_storage; +    struct mutex_storage   {    COND_T condition; -  struct object *key; +  struct key_storage *key;    int num_waiting;   };      enum key_kind   {    KEY_UNINITIALIZED = 0,    KEY_INITIALIZED,   };      struct key_storage   { -  +  struct object *self; /* NOT reference-counted! */    struct mutex_storage *mut;    struct object *mutex_obj;    struct thread_state *owner;    struct object *owner_obj;    enum key_kind kind;   };      #define OB2KEY(X) ((struct key_storage *)((X)->storage))      /*! @class Mutex
pike.git/src/threads.c:2197:    *! matter how you look at it, so it was changed in 7.6. The old    *! behavior is retained in compatibility mode for applications that    *! explicitly destruct mutexes to unlock them.    *!    *! @seealso    *! @[trylock()]    */   void f_mutex_lock(INT32 args)   {    struct mutex_storage *m; +  struct key_storage *key;    struct object *o;    INT_TYPE type;       DEBUG_CHECK_THREAD();       m=THIS_MUTEX;    if(!args)    type=0;    else    get_all_args(NULL, args, "%i", &type);       switch(type)    {    default:    bad_arg_error("lock", args, 2, "int(0..2)", Pike_sp+1-args,    "Unknown mutex locking style: %"PRINTPIKEINT"d\n",type);          case 0:    case 2: -  if(m->key && OB2KEY(m->key)->owner == Pike_interpreter.thread_state) +  if(m->key && m->key->owner == Pike_interpreter.thread_state)    {    THREADS_FPRINTF(0,    "Recursive LOCK k:%p, m:%p(%p), t:%p\n", -  OB2KEY(m->key), m, OB2KEY(m->key)->mut, +  m->key, m, m->key->mut,    Pike_interpreter.thread_state);       if(type==0) Pike_error("Recursive mutex locks!\n");       pop_n_elems(args);    push_int(0);    return;    }    case 1:    break;
pike.git/src/threads.c:2270: Inside #if defined(PICKY_MUTEX)
  #ifdef PICKY_MUTEX    if (!Pike_fp->current_object->prog) {    free_object (o);    if (!m->num_waiting) {    co_destroy (&m->condition);    }    Pike_error ("Mutex was destructed while waiting for lock.\n");    }   #endif    -  m->key=o; +  m->key = OB2KEY(o);    OB2KEY(o)->mut=m;    add_ref (OB2KEY(o)->mutex_obj = Pike_fp->current_object);       DEBUG_CHECK_THREAD();       THREADS_FPRINTF(1, "LOCK k:%p, m:%p(%p), t:%p\n",    OB2KEY(o), m, OB2KEY(m->key)->mut,    Pike_interpreter.thread_state);    pop_n_elems(args);    push_object(o);
pike.git/src/threads.c:2296:    *! This function performs the same operation as @[lock()], but if the mutex    *! is already locked, it will return zero instead of sleeping until it's    *! unlocked.    *!    *! @seealso    *! @[lock()]    */   void f_mutex_trylock(INT32 args)   {    struct mutex_storage *m; +  struct key_storage *key;    struct object *o;    INT_TYPE type;    int i=0;       /* No reason to release the interpreter lock here    * since we aren't calling any functions that take time.    */       m=THIS_MUTEX;   
pike.git/src/threads.c:2318:    else    get_all_args(NULL, args, "%i", &type);       switch(type)    {    default:    bad_arg_error("trylock", args, 2, "int(0..2)", Pike_sp+1-args,    "Unknown mutex locking style: %"PRINTPIKEINT"d\n",type);       case 0: -  if(m->key && OB2KEY(m->key)->owner == Pike_interpreter.thread_state) +  if(m->key && m->key->owner == Pike_interpreter.thread_state)    {    Pike_error("Recursive mutex locks!\n");    }       case 2:    case 1:    break;    }       o=clone_object(mutex_key,0); -  +  key = OB2KEY(o);       if(!m->key)    { -  OB2KEY(o)->mut=m; -  add_ref (OB2KEY(o)->mutex_obj = Pike_fp->current_object); -  m->key=o; +  key->mut = m; +  add_ref (key->mutex_obj = Pike_fp->current_object); +  m->key = key;    i=1;    }       pop_n_elems(args);    if(i)    {    push_object(o);    } else {    /* NB: We know that mutex_key doesn't have an lfun:_destruct()    * that inhibits our destruct().
pike.git/src/threads.c:2366:    *!    *! @seealso    *! @[Thread()]    */   PMOD_EXPORT void f_mutex_locking_thread(INT32 args)   {    struct mutex_storage *m = THIS_MUTEX;       pop_n_elems(args);    -  if (m->key && OB2KEY(m->key)->owner) -  ref_push_object(OB2KEY(m->key)->owner->thread_obj); +  if (m->key && m->key->owner) +  ref_push_object(m->key->owner->thread_obj);    else    push_int(0);   }      /*! @decl Thread.MutexKey current_locking_key()    *!    *! This mutex method returns the key object currently governing    *! the lock on this mutex. 0 is returned if the mutex isn't locked.    *!    *! @seealso    *! @[Thread()]    */   PMOD_EXPORT void f_mutex_locking_key(INT32 args)   {    struct mutex_storage *m = THIS_MUTEX;       pop_n_elems(args);       if (m->key) -  ref_push_object(m->key); +  ref_push_object(m->key->self);    else    push_int(0);   }      /*! @decl protected string _sprintf(int c)    *!    *! Describes the mutex including the thread that currently holds the lock    *! (if any).    */   void f_mutex__sprintf (INT32 args)   {    struct mutex_storage *m = THIS_MUTEX;    int c = 0;    if(args>0 && TYPEOF(Pike_sp[-args]) == PIKE_T_INT)    c = Pike_sp[-args].u.integer;    pop_n_elems (args);    if(c != 'O') {    push_undefined();    return;    } -  if (m->key && OB2KEY(m->key)->owner) { +  if (m->key && m->key->owner) {    push_static_text("Thread.Mutex(/*locked by 0x"); -  push_int64(PTR_TO_INT(THREAD_T_TO_PTR(OB2KEY(m->key)->owner->id))); +  push_int64(PTR_TO_INT(THREAD_T_TO_PTR(m->key->owner->id)));    f_int2hex(1);    push_static_text("*/)");    f_add(3);    } else {    push_static_text("Thread.Mutex(/* Unlocked */)");    }   }      /*! @decl Condition cond()    *!
pike.git/src/threads.c:2451: Inside #if defined(PIKE_NULL_IS_SPECIAL)
   co_init(& THIS_MUTEX->condition);   #ifdef PIKE_NULL_IS_SPECIAL    THIS_MUTEX->key=0;    THIS_MUTEX->num_waiting = 0;   #endif   }      void exit_mutex_obj(struct object *UNUSED(o))   {    struct mutex_storage *m = THIS_MUTEX; -  struct object *key = m->key; +  struct key_storage *key = m->key;       THREADS_FPRINTF(1, "DESTROYING MUTEX m:%p\n", THIS_MUTEX);      #ifndef PICKY_MUTEX    if (key) {    /* The last key will destroy m->condition in its exit hook. */    THREADS_FPRINTF(1, "Destructed mutex is in use - delaying cleanup\n");    }    else {   #ifdef PIKE_DEBUG
pike.git/src/threads.c:2473: Inside #if undefined(PICKY_MUTEX)
   Pike_error ("key/num_waiting confusion.\n");   #endif    co_destroy(& m->condition);    }   #else    if(key) {    m->key=0;    /* NB: We know that mutex_key doesn't have an lfun:_destruct()    * that inhibits our destruct().    */ -  destruct(key); /* Will destroy m->condition if m->num_waiting is zero. */ +  destruct(key->self); /* Will destroy m->condition if m->num_waiting is zero. */    if(m->num_waiting)    {    THREADS_FPRINTF(1, "Destructed mutex is being waited on.\n");    THREADS_ALLOW();    /* 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);   
pike.git/src/threads.c:2527:    */   #define THIS_KEY ((struct key_storage *)(CURRENT_STORAGE))   void init_mutex_key_obj(struct object *UNUSED(o))   {    THREADS_FPRINTF(1, "KEY k:%p, t:%p\n",    THIS_KEY, Pike_interpreter.thread_state);   #ifdef PIKE_NULL_IS_SPECIAL    THIS_KEY->mut=0;    THIS_KEY->mutex_obj = NULL;   #endif +  THIS_KEY->self = Pike_fp->current_object;    THIS_KEY->owner = Pike_interpreter.thread_state;    THIS_KEY->owner_obj = Pike_interpreter.thread_state->thread_obj;    if (THIS_KEY->owner_obj)    add_ref(THIS_KEY->owner_obj);    THIS_KEY->kind = KEY_INITIALIZED;   }      void exit_mutex_key_obj(struct object *DEBUGUSED(o))   {    THREADS_FPRINTF(1, "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 key_storage *key = THIS_KEY;    struct object *mutex_obj;      #ifdef PIKE_DEBUG    /* Note: mut->key can be NULL if our corresponding mutex    * has been destructed.    */ -  if(mut->key && (mut->key != o)) +  if(mut->key && (mut->key != key))    Pike_fatal("Mutex unlock from wrong key %p != %p!\n", -  THIS_KEY->mut->key, o); +  mut->key, key);   #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;
pike.git/src/threads.c:3318:    *!    *! @note    *! Note also that any threads waiting on the condition will be    *! woken up when it gets destructed.    *!    *! @seealso    *! @[Mutex->lock()]    */   void f_cond_wait(INT32 args)   { -  struct object *key, *mutex_obj; +  struct object *key_obj, *mutex_obj;    struct mutex_storage *mut; -  +  struct key_storage *key;    struct pike_cond *c;    INT_TYPE seconds = 0, nanos = 0;       if(threads_disabled)    Pike_error("Cannot wait for conditions when threads are disabled!\n");       if (args <= 2) {    FLOAT_TYPE fsecs = 0.0; -  get_all_args(NULL, args, "%o.%F", &key, &fsecs); +  get_all_args(NULL, args, "%o.%F", &key_obj, &fsecs);    seconds = (INT_TYPE) fsecs;    nanos = (INT_TYPE)((fsecs - seconds)*1000000000);    } else {    /* FIXME: Support bignum nanos. */ -  get_all_args(NULL, args, "%o%i%i", &key, &seconds, &nanos); +  get_all_args(NULL, args, "%o%i%i", &key_obj, &seconds, &nanos);    }       c = THIS_COND;    -  if ((key->prog != mutex_key) || -  (!(OB2KEY(key)->kind)) || -  (!(mut = OB2KEY(key)->mut)) || -  (c->mutex_obj && OB2KEY(key)->mutex_obj && -  (OB2KEY(key)->mutex_obj != c->mutex_obj))) { +  if ((key_obj->prog != mutex_key) || +  (!((key = OB2KEY(key_obj))->kind)) || +  (!(mut = key->mut)) || +  (c->mutex_obj && key->mutex_obj && +  (key->mutex_obj != c->mutex_obj))) {    Pike_error("Bad argument 1 to wait()\n");    }       if(args > 1) {    pop_n_elems(args - 1);    args = 1;    }       /* Unlock mutex */ -  mutex_obj = OB2KEY(key)->mutex_obj; +  mutex_obj = key->mutex_obj;    mut->key=0; -  OB2KEY(key)->mut=0; -  OB2KEY(key)->mutex_obj = NULL; +  key->mut = NULL; +  key->mutex_obj = NULL;    co_signal(& mut->condition);       if (!c->mutex_obj) {    /* Lock the condition to the first mutex it is used together with. */    c->mutex_obj = mutex_obj;    add_ref(mutex_obj);    }       /* Wait and allow mutex operations */    SWAP_OUT_CURRENT_THREAD();
pike.git/src/threads.c:3388:       /* Lock mutex */    mut->num_waiting++;    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; -  OB2KEY(key)->mutex_obj = mutex_obj; +  key->mut = mut; +  key->mutex_obj = mutex_obj;    mut->num_waiting--;       pop_stack();    return;   }      /*! @decl void signal()    *!    *! @[signal()] wakes up one of the threads currently waiting for the    *! condition.