diff --git a/doc/builtin/this_thread b/doc/builtin/this_thread new file mode 100644 index 0000000000000000000000000000000000000000..f898ec49eef31cab5a258da3ff992f85e2cc85f8 --- /dev/null +++ b/doc/builtin/this_thread @@ -0,0 +1,11 @@ +NAME + this_thread - return thread id + +SYNTAX + object thread_id(); + +DESCRIPTION + This function returns the object that identifies this thread. + +SEE ALSO + thread_create diff --git a/doc/builtin/thread_create b/doc/builtin/thread_create index 4431df6271c46c6d7272ace1f40d38722b40c959..5d384b262586aedef8af3a01b8d3eeb15a5acca5 100644 --- a/doc/builtin/thread_create +++ b/doc/builtin/thread_create @@ -2,7 +2,7 @@ NAME thread_create - create a thread SYNTAX - int thread_create(function f, mixed ... args); + object thread_create(function f, mixed ... args); DESCRIPTION This function creates a new thread which will run simultaneously @@ -10,10 +10,11 @@ DESCRIPTION f with the arguments args. When f returns the thread will cease to exist. All Pike functions are 'thread safe' meanting that running a function at the same time from different threads will not corrupt - any internal data in the Pike process. + any internal data in the Pike process. The returned value will be + the same as the return value of this_thread() for the new thread. NOTA BENE This function is only available on systems with POSIX threads support. SEE ALSO - /precompiled/mutex, /precompiled/condition \ No newline at end of file + /precompiled/mutex, /precompiled/condition, this_thread \ No newline at end of file diff --git a/src/main.c b/src/main.c index d1afd4c6afc357be93d908fdc8a00ef7685e5788..99e2e9ff1e77a2f90554c539faa335e896302b5f 100644 --- a/src/main.c +++ b/src/main.c @@ -267,6 +267,8 @@ void exit_main() void cleanup_pike_types(); void cleanup_program(); + th_cleanup(); + cleanup_objects(); exit_signals(); exit_lex(); diff --git a/src/threads.c b/src/threads.c index a2cdb2df9f9e3579cedf6a480e3020bd326f3eff..03e3aee60b26afed0243741feddcd9ef5be4ba61 100644 --- a/src/threads.c +++ b/src/threads.c @@ -2,26 +2,36 @@ #include "threads.h" #include "array.h" #include "object.h" +#include "macros.h" int num_threads = 1; int threads_disabled = 0; +struct object *thread_id; #ifdef _REENTRANT MUTEX_T interpreter_lock; struct program *mutex_key = 0; +struct program *thread_id_prog = 0; pthread_attr_t pattr; +struct thread_starter +{ + struct object *id; + struct array *args; +}; + void *new_thread_func(void * data) { + struct thread_starter arg = *(struct thread_starter *)data; JMP_BUF back; - struct array *foo; INT32 args; - foo=(struct array *)data; - args=foo->size; + free((char *)data); + args=arg.args->size; mt_lock( & interpreter_lock); init_interpreter(); + thread_id=arg.id; if(SETJMP(back)) { @@ -31,38 +41,62 @@ void *new_thread_func(void * data) pop_stack(); automatic_fatal=0; } else { - push_array_items(foo); + push_array_items(arg.args); + arg.args=0; f_call_function(args); + } UNSETJMP(back); + destruct(thread_id); + free_object(thread_id); + thread_id=0; + cleanup_interpret(); - mt_unlock(& interpreter_lock); num_threads--; + mt_unlock(& interpreter_lock); th_exit(0); } void f_thread_create(INT32 args) { + struct thread_starter *arg; pthread_t dummy; int tmp; - struct array *a=aggregate_array(args); - num_threads++; - tmp=th_create(&dummy,new_thread_func,a); - if(tmp) num_threads--; - push_int(tmp); + arg=ALLOC_STRUCT(thread_starter); + arg->args=aggregate_array(args); + arg->id=clone(thread_id_prog,0); + tmp=th_create(&dummy,new_thread_func,arg); + if(!tmp) + { + num_threads++; + push_object(arg->id); + arg->id->refs++; + } else { + free_object(arg->id); + free_array(arg->args); + free((char *)arg); + push_int(0); + } +} + +void f_this_thread(INT32 args) +{ + pop_n_elems(args); + push_object(thread_id); + thread_id->refs++; } void th_init() { - thr_setconcurrency(9); mt_lock( & interpreter_lock); pthread_attr_init(&pattr); pthread_attr_setstacksize(&pattr, 2 * 1024 * 1204); pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED); add_efun("thread_create",f_thread_create,"function(mixed ...:int)",OPT_SIDE_EFFECT); + add_efun("this_thread",f_this_thread,"function(:object)",OPT_EXTERNAL_DEPEND); } @@ -246,6 +280,7 @@ void th_init_programs() set_init_callback(init_mutex_key_obj); set_exit_callback(exit_mutex_key_obj); mutex_key=end_c_program("/precompiled/mutex_key"); + mutex_key->refs++; start_new_program(); add_storage(sizeof(COND_T)); @@ -255,6 +290,34 @@ void th_init_programs() set_init_callback(init_cond_obj); set_exit_callback(exit_cond_obj); end_c_program("/precompiled/condition"); + + start_new_program(); + thread_id_prog=end_c_program("/precompiled/thread"); + thread_id_prog->refs++; + + thread_id=clone(thread_id_prog,0); +} + +void th_cleanup() +{ + 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; + } } #endif diff --git a/src/threads.h b/src/threads.h index 3653fade56c17af3df90808a83deaa727f8ca1a6..b143f3ecb5bbcbadedb4799742e79afe2d702860 100644 --- a/src/threads.h +++ b/src/threads.h @@ -13,6 +13,8 @@ #endif extern int num_threads; +struct object; +extern struct object *thread_id; #define MUTEX_T pthread_mutex_t #define mt_init(X) pthread_mutex_init((X),0) @@ -44,6 +46,7 @@ struct thread_state { int evaluator_stack_malloced; int mark_stack_malloced; JMP_BUF *recoveries; + struct object * thread_id; }; #define THREADS_ALLOW() \ @@ -60,6 +63,7 @@ struct thread_state { _tmp.recoveries=recoveries; \ _tmp.evaluator_stack_malloced=evaluator_stack_malloced; \ _tmp.mark_stack_malloced=mark_stack_malloced; \ + _tmp.thread_id = thread_id; \ mt_unlock(& interpreter_lock); \ } @@ -74,13 +78,18 @@ struct thread_state { recoveries=_tmp.recoveries; \ evaluator_stack_malloced=_tmp.evaluator_stack_malloced; \ mark_stack_malloced=_tmp.mark_stack_malloced; \ + thread_id = _tmp.thread_id; \ } \ } while(0) /* Prototypes begin here */ +struct thread_starter; void *new_thread_func(void * data); void f_thread_create(INT32 args); +void f_this_thread(); void th_init(); +struct mutex_storage; +struct key_storage; void f_mutex_lock(INT32 args); void f_mutex_trylock(INT32 args); void init_mutex_obj(struct object *o); @@ -93,6 +102,7 @@ void f_cond_broadcast(INT32 args); void init_cond_obj(struct object *o); void exit_cond_obj(struct object *o); void th_init_programs(); +void th_cleanup(); /* Prototypes end here */ #else @@ -102,6 +112,7 @@ void th_init_programs(); #define THREADS_ALLOW() #define THREADS_DISALLOW() #define th_init() +#define th_cleanup() #define th_init_programs() #endif