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.260 2008/07/16 00:34:22 mast Exp $ + || $Id: threads.c,v 1.261 2008/08/05 20:43:25 mast Exp $   */      #include "global.h"      PMOD_EXPORT int num_threads = 1;   PMOD_EXPORT int threads_disabled = 0;      /* #define PICKY_MUTEX */      #ifdef _REENTRANT
pike.git/src/threads.c:246: Inside #if defined(POSIX_THREADS)
   pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);       pthread_attr_init(&small_pattr);   #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE    pthread_attr_setstacksize(&small_pattr, 4096*sizeof(char *));   #endif    pthread_attr_setdetachstate(&small_pattr, PTHREAD_CREATE_DETACHED);   #endif   }    + static void cleanup_thread_state (struct thread_state *th); +    #ifndef CONFIGURE_TEST      #define THIS_THREAD ((struct thread_state *)CURRENT_STORAGE)      static struct callback *threads_evaluator_callback=0;      int th_running = 0;   #ifdef PIKE_DEBUG   int debug_interpreter_is_locked = 0;   THREAD_T debug_locking_thread;
pike.git/src/threads.c:951:       /* This thread is now officially dead. */       while(Pike_fp)    POP_PIKE_FRAME();       reset_evaluator();       low_cleanup_interpret(&thread_state->state);    +  if (!thread_state->thread_obj) +  /* Do this only if exit_thread_obj already has run. */ +  cleanup_thread_state (thread_state); +     thread_table_delete(thread_state);    EXIT_THREAD_STATE(thread_state);    Pike_interpreter.thread_state = thread_state = NULL;       /* Free ourselves.    * NB: This really ought to run in some other thread...    */       free_object(thread_obj);    thread_obj = NULL;
pike.git/src/threads.c:1816:    *! 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");    }    +  th->waiting++; +     THREADS_FPRINTF(0, (stderr,    "Thread->wait(): 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->wait(): 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); -  +  +  th->waiting--; +  +  if (!th->thread_obj) +  /* Do this only if exit_thread_obj already has run. */ +  cleanup_thread_state (th);   }      static int num_pending_interrupts = 0;   static struct callback *thread_interrupt_callback = NULL;      static void check_thread_interrupt(struct callback *foo,    void *bar, void *gazonk)   {    if (Pike_interpreter.thread_state->flags & THREAD_FLAG_SIGNAL_MASK) {    if (Pike_interpreter.thread_state->flags & THREAD_FLAG_TERM) {
pike.git/src/threads.c:1920:    push_int(0);   }      void init_thread_obj(struct object *o)   {    MEMSET(&THIS_THREAD->state, 0, sizeof(struct Pike_interpreter));    THIS_THREAD->thread_obj = Pike_fp->current_object;    THIS_THREAD->swapped = 0;    THIS_THREAD->status=THREAD_NOT_STARTED;    THIS_THREAD->flags = 0; +  THIS_THREAD->waiting = 0;    THIS_THREAD->result.type = T_INT;    THIS_THREAD->result.subtype = NUMBER_UNDEFINED;    THIS_THREAD->result.u.integer = 0;    co_init(& THIS_THREAD->status_change);    THIS_THREAD->thread_local=NULL;   #ifdef CPU_TIME_MIGHT_BE_THREAD_LOCAL    THIS_THREAD->auto_gc_time = 0;   #endif   }    -  - void exit_thread_obj(struct object *o) + static void cleanup_thread_state (struct thread_state *th)   { -  + #ifdef PIKE_DEBUG +  if (th->thread_obj) Pike_fatal ("Thread state still active.\n"); + #endif +  +  /* Don't clean up if the thread is running or if someone is waiting +  * on status_change. They should call cleanup_thread_state later. */ +  if (th->status == THREAD_RUNNING || th->waiting) +  return; +     if (THIS_THREAD->flags & THREAD_FLAG_SIGNAL_MASK) {    Pike_interpreter.thread_state->flags &= ~THREAD_FLAG_SIGNAL_MASK;    if (!--num_pending_interrupts) {    remove_callback(thread_interrupt_callback);    thread_interrupt_callback = NULL;    }    } -  +  +  co_destroy(& THIS_THREAD->status_change); +  th_destroy(& THIS_THREAD->id); + } +  + void exit_thread_obj(struct object *o) + { +  THIS_THREAD->thread_obj = NULL; +  +  cleanup_thread_state (THIS_THREAD); +     if(THIS_THREAD->thread_local != NULL) {    free_mapping(THIS_THREAD->thread_local);    THIS_THREAD->thread_local = NULL;    } -  co_destroy(& THIS_THREAD->status_change); -  th_destroy(& THIS_THREAD->id); -  THIS_THREAD->thread_obj = NULL; +    }      /*! @endclass    */      static void thread_was_recursed(struct object *o)   {    struct thread_state *tmp=THIS_THREAD;    if(tmp->thread_local != NULL)    gc_recurse_mapping(tmp->thread_local);