07513e1996-10-04Fredrik Hübinette (Hubbe) #include "global.h"
c5b96b1997-11-11Henrik Grubbström (Grubba) RCSID("$Id: threads.c,v 1.47 1997/11/11 04:02:45 grubba Exp $");
a29e021996-10-15Fredrik Hübinette (Hubbe)  int num_threads = 1; int threads_disabled = 0; #ifdef _REENTRANT
07513e1996-10-04Fredrik Hübinette (Hubbe) #include "threads.h" #include "array.h" #include "object.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
a29e021996-10-15Fredrik Hübinette (Hubbe) #include "callback.h"
9c6f7d1997-04-15Fredrik Hübinette (Hubbe) #include "builtin_functions.h" #include "constants.h"
be478c1997-08-30Henrik Grubbström (Grubba) #include "program.h"
c5b96b1997-11-11Henrik Grubbström (Grubba) #include "gc.h"
07513e1996-10-04Fredrik Hübinette (Hubbe) 
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) struct object *thread_id;
a29e021996-10-15Fredrik Hübinette (Hubbe) static struct callback *threads_evaluator_callback=0;
07513e1996-10-04Fredrik Hübinette (Hubbe) 
fe76ce1997-09-08Fredrik Hübinette (Hubbe) MUTEX_T interpreter_lock;
07513e1996-10-04Fredrik Hübinette (Hubbe) struct program *mutex_key = 0;
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) struct program *thread_id_prog = 0;
97ffe41997-01-26Per Hedbor #ifdef POSIX_THREADS
07513e1996-10-04Fredrik Hübinette (Hubbe) pthread_attr_t pattr;
97ffe41997-01-26Per Hedbor #endif
07513e1996-10-04Fredrik Hübinette (Hubbe) 
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) struct thread_starter { struct object *id; struct array *args; };
9ef9a31996-11-16Fredrik Hübinette (Hubbe) static void check_threads(struct callback *cb, void *arg, void * arg2)
a29e021996-10-15Fredrik Hübinette (Hubbe) {
0a861b1997-09-17Fredrik Hübinette (Hubbe)  static int div_; if(div_++ & 255) return;
a29e021996-10-15Fredrik Hübinette (Hubbe)  THREADS_ALLOW(); /* Allow other threads to run */ THREADS_DISALLOW(); }
07513e1996-10-04Fredrik Hübinette (Hubbe) void *new_thread_func(void * data) {
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  struct thread_starter arg = *(struct thread_starter *)data;
07513e1996-10-04Fredrik Hübinette (Hubbe)  JMP_BUF back;
725ba91996-10-12Fredrik Hübinette (Hubbe)  INT32 tmp;
b1b51f1996-10-11Fredrik Hübinette (Hubbe) 
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  THREADS_FPRINTF((stderr,"THREADS_DISALLOW() Thread %08x created...\n", (unsigned int)arg.id));
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  if((tmp=mt_lock( & interpreter_lock)))
725ba91996-10-12Fredrik Hübinette (Hubbe)  fatal("Failed to lock interpreter, errno %d\n",tmp);
07513e1996-10-04Fredrik Hübinette (Hubbe)  init_interpreter();
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  thread_id=arg.id;
a7fef41997-09-03Per Hedbor  SWAP_OUT_THREAD((struct thread_state *)thread_id->storage); /* Init struct */ ((struct thread_state *)thread_id->storage)->swapped=0;
07513e1996-10-04Fredrik Hübinette (Hubbe) 
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  THREADS_FPRINTF((stderr,"THREAD %08x INITED\n",(unsigned int)thread_id));
07513e1996-10-04Fredrik Hübinette (Hubbe)  if(SETJMP(back)) {
b48cc31996-10-09Fredrik Hübinette (Hubbe)  ONERROR tmp; SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
07513e1996-10-04Fredrik Hübinette (Hubbe)  assign_svalue_no_free(sp++, & throw_value); APPLY_MASTER("handle_error", 1); pop_stack();
b48cc31996-10-09Fredrik Hübinette (Hubbe)  UNSET_ONERROR(tmp);
07513e1996-10-04Fredrik Hübinette (Hubbe)  } else {
725ba91996-10-12Fredrik Hübinette (Hubbe)  INT32 args=arg.args->size;
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  push_array_items(arg.args); arg.args=0;
97ffe41997-01-26Per Hedbor  f_call_function(args); pop_stack(); /* Discard the return value. /Per */
07513e1996-10-04Fredrik Hübinette (Hubbe)  }
4bdad01997-09-01Per Hedbor  free((char *)data); /* Moved by per, to avoid some bugs.... */
07513e1996-10-04Fredrik Hübinette (Hubbe)  UNSETJMP(back);
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  destruct(thread_id);
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  THREADS_FPRINTF((stderr,"THREADS_ALLOW() Thread %08x done\n", (unsigned int)thread_id));
b1b51f1996-10-11Fredrik Hübinette (Hubbe) 
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  free_object(thread_id); thread_id=0;
07513e1996-10-04Fredrik Hübinette (Hubbe)  cleanup_interpret(); num_threads--;
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  if(!num_threads && threads_evaluator_callback)
a29e021996-10-15Fredrik Hübinette (Hubbe)  { remove_callback(threads_evaluator_callback); threads_evaluator_callback=0; }
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  mt_unlock(& interpreter_lock);
07513e1996-10-04Fredrik Hübinette (Hubbe)  th_exit(0);
9c8b2d1997-04-20Henrik Grubbström (Grubba)  /* NOT_REACHED, but removes a warning */ return(NULL);
07513e1996-10-04Fredrik Hübinette (Hubbe) }
97ffe41997-01-26Per Hedbor #ifdef UNIX_THREADS int num_lwps = 1; #endif
b1b51f1996-10-11Fredrik Hübinette (Hubbe) 
07513e1996-10-04Fredrik Hübinette (Hubbe) void f_thread_create(INT32 args) {
97ffe41997-01-26Per Hedbor  THREAD_T dummy;
b1b51f1996-10-11Fredrik Hübinette (Hubbe)  struct thread_starter *arg;
07513e1996-10-04Fredrik Hübinette (Hubbe)  int tmp;
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  arg=ALLOC_STRUCT(thread_starter); arg->args=aggregate_array(args);
e709751997-03-12Fredrik Hübinette (Hubbe)  arg->id=clone_object(thread_id_prog,0);
b2a0fb1997-02-06Henrik Grubbström (Grubba) 
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  tmp=th_create(&dummy,new_thread_func,arg);
b2a0fb1997-02-06Henrik Grubbström (Grubba) 
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  if(!tmp) { num_threads++;
a29e021996-10-15Fredrik Hübinette (Hubbe) 
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  if(!threads_evaluator_callback)
a29e021996-10-15Fredrik Hübinette (Hubbe)  { threads_evaluator_callback=add_to_callback(&evaluator_callbacks, check_threads, 0,0); }
97ffe41997-01-26Per Hedbor #ifdef UNIX_THREADS if((num_lwps==1) || num_threads/3 > num_lwps) th_setconcurrency(++num_lwps); #endif
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  push_object(arg->id); arg->id->refs++;
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  THREADS_FPRINTF((stderr,"THREAD_CREATE -> t:%08x\n",(unsigned int)arg->id));
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  } else { free_object(arg->id); free_array(arg->args); free((char *)arg);
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  error("Failed to create thread.\n");
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  } }
1e4a641997-09-03Martin Stjernholm #ifdef UNIX_THREADS
97ffe41997-01-26Per Hedbor void f_thread_set_concurrency(INT32 args) { int c=1; if(args) c=sp[-args].u.integer; else error("No argument to thread_set_concurrency(int concurrency);\n"); pop_n_elems(args);
09dceb1997-09-01Per Hedbor  num_lwps=c;
97ffe41997-01-26Per Hedbor  th_setconcurrency(c); }
1e4a641997-09-03Martin Stjernholm #endif
97ffe41997-01-26Per Hedbor 
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) void f_this_thread(INT32 args) { pop_n_elems(args); push_object(thread_id); thread_id->refs++;
07513e1996-10-04Fredrik Hübinette (Hubbe) }
5988921996-10-05Fredrik Hübinette (Hubbe) #define THIS_MUTEX ((struct mutex_storage *)(fp->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 mutex_storage { COND_T condition; struct object *key; }; struct key_storage { struct mutex_storage *mut;
09dceb1997-09-01Per Hedbor  struct object *owner;
4bdad01997-09-01Per Hedbor  int initialized;
5988921996-10-05Fredrik Hübinette (Hubbe) }; #define OB2KEY(X) ((struct key_storage *)((X)->storage))
07513e1996-10-04Fredrik Hübinette (Hubbe)  void f_mutex_lock(INT32 args) {
5988921996-10-05Fredrik Hübinette (Hubbe)  struct mutex_storage *m;
07513e1996-10-04Fredrik Hübinette (Hubbe)  struct object *o;
5988921996-10-05Fredrik Hübinette (Hubbe) 
07513e1996-10-04Fredrik Hübinette (Hubbe)  m=THIS_MUTEX;
46d7bf1997-09-03Henrik Grubbström (Grubba)  /* Needs to be cloned here, since create() * might use threads. */
65df5c1997-09-01Per Hedbor  o=clone_object(mutex_key,0);
852ce91997-09-08Fredrik Hübinette (Hubbe)  if(!args || IS_ZERO(sp-args))
4bdad01997-09-01Per Hedbor  {
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  if(m->key && OB2KEY(m->key)->owner == thread_id) { THREADS_FPRINTF((stderr, "Recursive LOCK k:%08x, m:%08x(%08x), t:%08x\n", (unsigned int)OB2KEY(m->key), (unsigned int)m, (unsigned int)OB2KEY(m->key)->mut, (unsigned int) thread_id)); free_object(o); error("Recursive mutex locks!\n"); }
4bdad01997-09-01Per Hedbor  }
0a861b1997-09-17Fredrik Hübinette (Hubbe)  if(m->key)
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  {
b504ed1997-09-21Fredrik Hübinette (Hubbe)  SWAP_OUT_CURRENT_THREAD(); do
0a861b1997-09-17Fredrik Hübinette (Hubbe)  {
b504ed1997-09-21Fredrik Hübinette (Hubbe)  THREADS_FPRINTF((stderr,"WAITING TO LOCK m:%08x\n",(unsigned int)m)); co_wait(& m->condition, & interpreter_lock); }while(m->key); SWAP_IN_CURRENT_THREAD();
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  }
5988921996-10-05Fredrik Hübinette (Hubbe)  m->key=o;
46d7bf1997-09-03Henrik Grubbström (Grubba)  OB2KEY(o)->mut=m;
fe76ce1997-09-08Fredrik Hübinette (Hubbe) 
46d7bf1997-09-03Henrik Grubbström (Grubba)  THREADS_FPRINTF((stderr, "LOCK k:%08x, m:%08x(%08x), t:%08x\n", (unsigned int)OB2KEY(o), (unsigned int)m, (unsigned int)OB2KEY(m->key)->mut, (unsigned int)thread_id));
65d3c31997-09-08Fredrik Hübinette (Hubbe)  pop_n_elems(args);
07513e1996-10-04Fredrik Hübinette (Hubbe)  push_object(o); } void f_mutex_trylock(INT32 args) {
5988921996-10-05Fredrik Hübinette (Hubbe)  struct mutex_storage *m; struct object *o; int i=0;
07513e1996-10-04Fredrik Hübinette (Hubbe) 
e709751997-03-12Fredrik Hübinette (Hubbe)  o=clone_object(mutex_key,0);
07513e1996-10-04Fredrik Hübinette (Hubbe)  m=THIS_MUTEX;
4bdad01997-09-01Per Hedbor 
46d7bf1997-09-03Henrik Grubbström (Grubba)  /* No reason to release the interpreter lock here * since we aren't calling any functions that take time. */
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  if(!args || IS_ZERO(sp-args))
65df5c1997-09-01Per Hedbor  {
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  if(m->key && OB2KEY(m->key)->owner == thread_id) { free_object(o); error("Recursive mutex locks!\n"); }
65df5c1997-09-01Per Hedbor  }
50fd181997-09-17Fredrik Hübinette (Hubbe) 
5988921996-10-05Fredrik Hübinette (Hubbe)  if(!m->key) {
e4293f1997-04-17Fredrik Hübinette (Hubbe)  OB2KEY(o)->mut=m;
5988921996-10-05Fredrik Hübinette (Hubbe)  m->key=o; i=1; }
4bdad01997-09-01Per Hedbor 
65d3c31997-09-08Fredrik Hübinette (Hubbe)  pop_n_elems(args);
07513e1996-10-04Fredrik Hübinette (Hubbe)  if(i) { push_object(o); } else {
5988921996-10-05Fredrik Hübinette (Hubbe)  destruct(o); free_object(o);
07513e1996-10-04Fredrik Hübinette (Hubbe)  push_int(0); } }
5988921996-10-05Fredrik Hübinette (Hubbe) void init_mutex_obj(struct object *o) { co_init(& THIS_MUTEX->condition); THIS_MUTEX->key=0; }
07513e1996-10-04Fredrik Hübinette (Hubbe) 
5988921996-10-05Fredrik Hübinette (Hubbe) void exit_mutex_obj(struct object *o) {
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  THREADS_FPRINTF((stderr,"DESTROYING MUTEX m:%08x\n",(unsigned int)THIS_MUTEX));
5988921996-10-05Fredrik Hübinette (Hubbe)  if(THIS_MUTEX->key) destruct(THIS_MUTEX->key);
88fe361997-09-04Per Hedbor  THIS_MUTEX->key=0;
5988921996-10-05Fredrik Hübinette (Hubbe)  co_destroy(& THIS_MUTEX->condition); } #define THIS_KEY ((struct key_storage *)(fp->current_storage)) void init_mutex_key_obj(struct object *o) {
46d7bf1997-09-03Henrik Grubbström (Grubba)  THREADS_FPRINTF((stderr, "KEY k:%08x, o:%08x\n", (unsigned int)THIS_KEY, (unsigned int)thread_id));
5988921996-10-05Fredrik Hübinette (Hubbe)  THIS_KEY->mut=0;
46d7bf1997-09-03Henrik Grubbström (Grubba)  THIS_KEY->owner=thread_id; thread_id->refs++;
5988921996-10-05Fredrik Hübinette (Hubbe)  THIS_KEY->initialized=1; }
07513e1996-10-04Fredrik Hübinette (Hubbe)  void exit_mutex_key_obj(struct object *o) {
46d7bf1997-09-03Henrik Grubbström (Grubba)  THREADS_FPRINTF((stderr, "UNLOCK k:%08x m:(%08x) t:%08x o:%08x\n", (unsigned int)THIS_KEY, (unsigned int)THIS_KEY->mut, (unsigned int)thread_id, (unsigned int)THIS_KEY->owner));
5988921996-10-05Fredrik Hübinette (Hubbe)  if(THIS_KEY->mut)
07513e1996-10-04Fredrik Hübinette (Hubbe)  {
03b1fe1997-09-06Per Hedbor  struct mutex_storage *mut = THIS_KEY->mut;
c113871997-09-15Henrik Grubbström (Grubba) 
5988921996-10-05Fredrik Hübinette (Hubbe) #ifdef DEBUG
03b1fe1997-09-06Per Hedbor  if(mut->key != o) fatal("Mutex unlock from wrong key %p != %p!\n",THIS_KEY->mut->key,o);
5988921996-10-05Fredrik Hübinette (Hubbe) #endif
03b1fe1997-09-06Per Hedbor  mut->key=0;
46d7bf1997-09-03Henrik Grubbström (Grubba)  if (THIS_KEY->owner) { free_object(THIS_KEY->owner); THIS_KEY->owner=0; }
5988921996-10-05Fredrik Hübinette (Hubbe)  THIS_KEY->mut=0; THIS_KEY->initialized=0;
c113871997-09-15Henrik Grubbström (Grubba)  co_signal(& mut->condition);
07513e1996-10-04Fredrik Hübinette (Hubbe)  } } #define THIS_COND ((COND_T *)(fp->current_storage)) void f_cond_wait(INT32 args) { COND_T *c;
5988921996-10-05Fredrik Hübinette (Hubbe)  struct object *key;
07513e1996-10-04Fredrik Hübinette (Hubbe)  if(args > 1) pop_n_elems(args - 1);
5988921996-10-05Fredrik Hübinette (Hubbe)  c=THIS_COND; if(args > 0)
07513e1996-10-04Fredrik Hübinette (Hubbe)  {
5988921996-10-05Fredrik Hübinette (Hubbe)  struct mutex_storage *mut; if(sp[-1].type != T_OBJECT)
07513e1996-10-04Fredrik Hübinette (Hubbe)  error("Bad argument 1 to condition->wait()\n");
5988921996-10-05Fredrik Hübinette (Hubbe)  key=sp[-1].u.object; if(key->prog != mutex_key) error("Bad argument 1 to condition->wait()\n"); mut=OB2KEY(key)->mut;
88fe361997-09-04Per Hedbor  if(!mut) error("Bad argument 1 to condition->wait()\n");
368d4a1997-09-03Per Hedbor 
5988921996-10-05Fredrik Hübinette (Hubbe)  /* Unlock mutex */ mut->key=0; OB2KEY(key)->mut=0; co_signal(& mut->condition);
88fe361997-09-04Per Hedbor 
5988921996-10-05Fredrik Hübinette (Hubbe)  /* Wait and allow mutex operations */
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  SWAP_OUT_CURRENT_THREAD(); co_wait(c, &interpreter_lock);
88fe361997-09-04Per Hedbor 
5988921996-10-05Fredrik Hübinette (Hubbe)  if(OB2KEY(key)->initialized) { /* Lock mutex */
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  while(mut->key) co_wait(& mut->condition, &interpreter_lock);
5988921996-10-05Fredrik Hübinette (Hubbe)  mut->key=key; OB2KEY(key)->mut=mut; }
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  SWAP_IN_CURRENT_THREAD();
07513e1996-10-04Fredrik Hübinette (Hubbe)  pop_stack();
5988921996-10-05Fredrik Hübinette (Hubbe)  } else {
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  SWAP_OUT_CURRENT_THREAD(); co_wait(c, &interpreter_lock); SWAP_IN_CURRENT_THREAD();
07513e1996-10-04Fredrik Hübinette (Hubbe)  } } void f_cond_signal(INT32 args) { pop_n_elems(args); co_signal(THIS_COND); } void f_cond_broadcast(INT32 args) { pop_n_elems(args); co_broadcast(THIS_COND); } void init_cond_obj(struct object *o) { co_init(THIS_COND); } void exit_cond_obj(struct object *o) { co_destroy(THIS_COND); }
a7fef41997-09-03Per Hedbor void f_thread_backtrace(INT32 args) { struct thread_state *foo = (struct thread_state *)fp->current_object->storage; struct thread_state *bar = (struct thread_state *)thread_id->storage; struct svalue *osp = sp; pop_n_elems(args); if(foo->sp) { SWAP_OUT_THREAD(bar); SWAP_IN_THREAD(foo); sp=osp; f_backtrace(0); osp=sp; sp=foo->sp; SWAP_OUT_THREAD(foo); SWAP_IN_THREAD(bar); sp=osp; } else { push_int(0); f_allocate(1); } } void init_thread_obj(struct object *o) { MEMSET(o->storage, 0, sizeof(struct thread_state)); }
f6d0171997-10-15Fredrik Hübinette (Hubbe) #ifdef DEBUG static void thread_was_marked(struct object *o) { struct thread_state *tmp=(struct thread_state *)(o->storage); if(tmp->swapped) {
4694111997-11-07Fredrik Hübinette (Hubbe)  debug_gc_xmark_svalues(tmp->evaluator_stack,tmp->sp-tmp->evaluator_stack-1,"idle thread stack");
f6d0171997-10-15Fredrik Hübinette (Hubbe)  } } #endif
be478c1997-08-30Henrik Grubbström (Grubba) void th_init(void)
07513e1996-10-04Fredrik Hübinette (Hubbe) {
e4419e1997-02-06Fredrik Hübinette (Hubbe)  struct program *tmp;
46d7bf1997-09-03Henrik Grubbström (Grubba)  INT32 mutex_key_offset;
e4419e1997-02-06Fredrik Hübinette (Hubbe)  #ifdef SGI_SPROC_THREADS #error /* Need to specify a filename */ us_cookie = usinit(""); #endif /* SGI_SPROC_THREADS */
12ae2f1997-09-05Henrik Grubbström (Grubba)  THREADS_FPRINTF((stderr, "THREADS_DISALLOW() Initializing threads.\n"));
fed8de1997-10-05Henrik Grubbström (Grubba)  #ifdef POSIX_THREADS #ifdef HAVE_PTHREAD_INIT pthread_init(); #endif /* HAVE_PTHREAD_INIT */ #endif /* POSIX_THREADS */
12ae2f1997-09-05Henrik Grubbström (Grubba)  mt_init( & interpreter_lock);
e4419e1997-02-06Fredrik Hübinette (Hubbe)  mt_lock( & interpreter_lock); #ifdef POSIX_THREADS pthread_attr_init(&pattr); #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE pthread_attr_setstacksize(&pattr, 2 * 1024 * 1204); #endif pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED); #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);
07513e1996-10-04Fredrik Hübinette (Hubbe)  start_new_program();
5988921996-10-05Fredrik Hübinette (Hubbe)  add_storage(sizeof(struct mutex_storage));
fe76ce1997-09-08Fredrik Hübinette (Hubbe)  add_function("lock",f_mutex_lock,"function(int|void:object)",0); add_function("trylock",f_mutex_trylock,"function(int|void:object)",0);
07513e1996-10-04Fredrik Hübinette (Hubbe)  set_init_callback(init_mutex_obj); set_exit_callback(exit_mutex_obj);
b98eb31997-02-11Henrik Grubbström (Grubba)  end_class("mutex", 0);
07513e1996-10-04Fredrik Hübinette (Hubbe)  start_new_program();
46d7bf1997-09-03Henrik Grubbström (Grubba)  mutex_key_offset = add_storage(sizeof(struct key_storage)); /* This is needed to allow the gc to find the possible circular reference. * It also allows a process to take over ownership of a key. */ map_variable("_owner", "object", 0, mutex_key_offset + OFFSETOF(key_storage, owner), T_OBJECT);
5988921996-10-05Fredrik Hübinette (Hubbe)  set_init_callback(init_mutex_key_obj);
07513e1996-10-04Fredrik Hübinette (Hubbe)  set_exit_callback(exit_mutex_key_obj);
e4419e1997-02-06Fredrik Hübinette (Hubbe)  mutex_key=end_program();
b504ed1997-09-21Fredrik Hübinette (Hubbe)  mutex_key->flags|=PROG_DESTRUCT_IMMEDIATE;
f839fa1997-02-28Fredrik Hübinette (Hubbe)  if(!mutex_key) fatal("Failed to initialize mutex_key program!\n");
07513e1996-10-04Fredrik Hübinette (Hubbe)  start_new_program(); add_storage(sizeof(COND_T)); add_function("wait",f_cond_wait,"function(void|object:void)",0); add_function("signal",f_cond_signal,"function(:void)",0); add_function("broadcast",f_cond_broadcast,"function(:void)",0); set_init_callback(init_cond_obj); set_exit_callback(exit_cond_obj);
b98eb31997-02-11Henrik Grubbström (Grubba)  end_class("condition", 0);
6d1a5e1996-10-07Fredrik Hübinette (Hubbe)  start_new_program();
a7fef41997-09-03Per Hedbor  add_storage(sizeof(struct thread_state)); add_function("backtrace",f_thread_backtrace,"function(:array)",0);
f6d0171997-10-15Fredrik Hübinette (Hubbe) #ifdef DEBUG set_gc_mark_callback(thread_was_marked); #endif
a7fef41997-09-03Per Hedbor  set_init_callback(init_thread_obj);
e4419e1997-02-06Fredrik Hübinette (Hubbe)  thread_id_prog=end_program();
f839fa1997-02-28Fredrik Hübinette (Hubbe)  if(!mutex_key) fatal("Failed to initialize thread program!\n");
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) 
e709751997-03-12Fredrik Hübinette (Hubbe)  thread_id=clone_object(thread_id_prog,0);
03b1fe1997-09-06Per Hedbor  SWAP_OUT_THREAD((struct thread_state *)thread_id->storage); /* Init struct */ ((struct thread_state *)thread_id->storage)->swapped=0;
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) void th_cleanup(void)
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) { if(mutex_key) { free_program(mutex_key); mutex_key=0; } if(thread_id_prog) { free_program(thread_id_prog); thread_id_prog=0; } if(thread_id) { destruct(thread_id); free_object(thread_id); thread_id=0; }
07513e1996-10-04Fredrik Hübinette (Hubbe) } #endif