pike.git / src / threads.c

version» Context lines:

pike.git/src/threads.c:1:   #include "global.h" - RCSID("$Id: threads.c,v 1.56 1998/02/19 05:15:20 per Exp $"); + RCSID("$Id: threads.c,v 1.57 1998/02/27 20:09:04 marcus Exp $");      int num_threads = 1;   int threads_disabled = 0;      #ifdef _REENTRANT   #include "threads.h"   #include "array.h"   #include "object.h"   #include "pike_macros.h"   #include "callback.h"
pike.git/src/threads.c:131:      #endif         #define THIS_THREAD ((struct thread_state *)fp->current_storage)      struct object *thread_id;   static struct callback *threads_evaluator_callback=0;   int thread_id_result_variable;    - MUTEX_T interpreter_lock; + MUTEX_T interpreter_lock, thread_table_lock;   struct program *mutex_key = 0;   struct program *thread_id_prog = 0;   #ifdef POSIX_THREADS   pthread_attr_t pattr;   pthread_attr_t small_pattr;   #endif      struct thread_starter   {    struct object *id;    struct array *args;   };    -  +  + /* Thread hashtable */ +  + #define THREAD_TABLE_SIZE 127 /* Totally arbitrary prime */ +  + static struct thread_state *thread_table_chains[THREAD_TABLE_SIZE]; +  + void thread_table_init() + { +  INT32 x; +  for(x=0; x<THREAD_TABLE_SIZE; x++) +  thread_table_chains[x] = NULL; + } +  + unsigned INT32 thread_table_hash(THREAD_T *tid) + { +  return hashmem((unsigned char *)tid, sizeof(*tid), 16) % THREAD_TABLE_SIZE; + } +  + void thread_table_insert(struct object *o) + { +  struct thread_state *s = (struct thread_state *)o->storage; +  unsigned INT32 h = thread_table_hash(&s->id); +  mt_lock( & thread_table_lock ); +  if((s->hashlink = thread_table_chains[h]) != NULL) +  s->hashlink->backlink = &s->hashlink; +  thread_table_chains[h] = s; +  s->backlink = &thread_table_chains[h]; +  mt_unlock( & thread_table_lock ); + } +  + void thread_table_delete(struct object *o) + { +  struct thread_state *s = (struct thread_state *)o->storage; +  mt_lock( & thread_table_lock ); +  if(s->hashlink != NULL) +  s->hashlink->backlink = s->backlink; +  *(s->backlink) = s->hashlink; +  mt_unlock( & thread_table_lock ); + } +  + struct thread_state *thread_state_for_id(THREAD_T tid) + { +  unsigned INT32 h = thread_table_hash(&tid); +  struct thread_state *s = NULL; +  mt_lock( & thread_table_lock ); +  if(thread_table_chains[h] == NULL) { +  /* NULL result */ +  } else if((s=thread_table_chains[h])->id == tid) { +  /* Quick return */ +  } else { +  while((s = s->hashlink) != NULL) +  if(s->id == tid) +  break; +  if(s != NULL) { +  /* Move the thread_state to the head of the chain, in case +  we want to search for it again */ +  +  /* Unlink */ +  if(s->hashlink != NULL) +  s->hashlink->backlink = s->backlink; +  *(s->backlink) = s->hashlink; +  /* And relink at the head of the chain */ +  if((s->hashlink = thread_table_chains[h]) != NULL) +  s->hashlink->backlink = &s->hashlink; +  thread_table_chains[h] = s; +  s->backlink = &thread_table_chains[h]; +  } +  } +  mt_unlock( & thread_table_lock ); +  return s; +  /* NOTEZ BIEN: Return value only guaranteed to remain valid as long +  as you have the interpreter lock, unless tid == th_self() */ + } +  + struct object *thread_for_id(THREAD_T tid) + { +  struct thread_state *s = thread_state_for_id(tid); +  return (s == NULL? NULL : +  (struct object *)(((char *)s)-((((struct object *)NULL)->storage)- +  ((char*)NULL)))); +  /* See NB in thread_state_for_id. Lifespan of result can be prolonged +  by incrementing refcount though. */ + } +  + void f_all_threads(INT32 args) + { +  /* Return an unordered array containing all threads that was running +  at the time this function was invoked */ +  +  INT32 x; +  struct svalue *oldsp; +  struct thread_state *s; +  +  pop_n_elems(args); +  oldsp = sp; +  mt_lock( & thread_table_lock ); +  for(x=0; x<THREAD_TABLE_SIZE; x++) +  for(s=thread_table_chains[x]; s; s=s->hashlink) { +  struct object *o = +  (struct object *)(((char *)s)-((((struct object *)NULL)->storage)- +  ((char*)NULL))); +  o->refs++; +  push_object(o); +  } +  mt_unlock( & thread_table_lock ); +  f_aggregate(sp-oldsp); + } +  +    static void check_threads(struct callback *cb, void *arg, void * arg2)   {    static int div_;    if(div_++ & 255) return;       THREADS_ALLOW();       /* Allow other threads to run */       THREADS_DISALLOW();
pike.git/src/threads.c:212:       ((struct thread_state *)(thread_id->storage))->status=THREAD_EXITED;    co_signal(& ((struct thread_state *)(thread_id->storage))->status_change);       free((char *)data); /* Moved by per, to avoid some bugs.... */    UNSETJMP(back);       THREADS_FPRINTF((stderr,"THREADS_ALLOW() Thread %08x done\n",    (unsigned int)thread_id));    +  thread_table_delete(thread_id);    free_object(thread_id);    thread_id=0;    cleanup_interpret();    num_threads--;    if(!num_threads && threads_evaluator_callback)    {    remove_callback(threads_evaluator_callback);    threads_evaluator_callback=0;    }    mt_unlock(& interpreter_lock);
pike.git/src/threads.c:248:    arg->id=clone_object(thread_id_prog,0);    ((struct thread_state *)arg->id->storage)->status=THREAD_RUNNING;       tmp=th_create(&((struct thread_state *)arg->id->storage)->id,    new_thread_func,    arg);       if(!tmp)    {    num_threads++; +  thread_table_insert(arg->id);       if(!threads_evaluator_callback)    {    threads_evaluator_callback=add_to_callback(&evaluator_callbacks,    check_threads, 0,0);    }   #ifdef UNIX_THREADS    if((num_lwps==1) || num_threads/3 > num_lwps)    th_setconcurrency(++num_lwps);   #endif
pike.git/src/threads.c:595:    THREADS_FPRINTF((stderr, "THREADS_DISALLOW() Initializing threads.\n"));      #ifdef POSIX_THREADS   #ifdef HAVE_PTHREAD_INIT    pthread_init();   #endif /* HAVE_PTHREAD_INIT */   #endif /* POSIX_THREADS */       mt_init( & interpreter_lock);    mt_lock( & interpreter_lock); +  mt_init( & thread_table_lock); +  thread_table_init();   #ifdef POSIX_THREADS    pthread_attr_init(&pattr);   #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE    pthread_attr_setstacksize(&pattr, 1024 * 1204);   #endif    pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);       pthread_attr_init(&small_pattr);   #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE    pthread_attr_setstacksize(&small_pattr, 32768);
pike.git/src/threads.c:618:   #endif       add_efun("thread_create",f_thread_create,"function(mixed ...:object)",    OPT_SIDE_EFFECT);   #ifdef UNIX_THREADS    add_efun("thread_set_concurrency",f_thread_set_concurrency,    "function(int:void)", OPT_SIDE_EFFECT);   #endif    add_efun("this_thread",f_this_thread,"function(:object)",    OPT_EXTERNAL_DEPEND); +  add_efun("all_threads",f_all_threads,"function(:array(object))", +  OPT_EXTERNAL_DEPEND);       start_new_program();    add_storage(sizeof(struct mutex_storage));    add_function("lock",f_mutex_lock,"function(int|void:object)",0);    add_function("trylock",f_mutex_trylock,"function(int|void:object)",0);    set_init_callback(init_mutex_obj);    set_exit_callback(exit_mutex_obj);    end_class("mutex", 0);       start_new_program();
pike.git/src/threads.c:668:   #endif    set_init_callback(init_thread_obj);    set_exit_callback(exit_thread_obj);    thread_id_prog=end_program();    if(!mutex_key)    fatal("Failed to initialize thread program!\n");       thread_id=clone_object(thread_id_prog,0);    SWAP_OUT_THREAD((struct thread_state *)thread_id->storage); /* Init struct */    ((struct thread_state *)thread_id->storage)->swapped=0; +  ((struct thread_state *)thread_id->storage)->id=th_self(); +  thread_table_insert(thread_id);   }      void th_cleanup(void)   {    if(mutex_key)    {    free_program(mutex_key);    mutex_key=0;    }