Make Perl_ithread_self() a bit more helpful when
[p5sagit/p5-mst-13.2.git] / ext / threads / threads.xs
CommitLineData
68795e93 1#define PERL_NO_GET_CONTEXT
2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5
73e09c8f 6#ifdef USE_ITHREADS
7
68795e93 8#ifdef WIN32
9#include <windows.h>
10#include <win32thread.h>
11#define PERL_THREAD_SETSPECIFIC(k,v) TlsSetValue(k,v)
12#define PERL_THREAD_GETSPECIFIC(k,v) v = TlsGetValue(k)
13#define PERL_THREAD_ALLOC_SPECIFIC(k) \
14STMT_START {\
15 if((k = TlsAlloc()) == TLS_OUT_OF_INDEXES) {\
ddcc6fdc 16 PerlIO_printf(PerlIO_stderr(),"panic threads.xs: TlsAlloc");\
68795e93 17 exit(1);\
18 }\
19} STMT_END
20#else
5c728af0 21#ifdef OS2
22typedef perl_os_thread pthread_t;
23#else
68795e93 24#include <pthread.h>
5c728af0 25#endif
68795e93 26#include <thread.h>
27
28#define PERL_THREAD_SETSPECIFIC(k,v) pthread_setspecific(k,v)
29#ifdef OLD_PTHREADS_API
30#define PERL_THREAD_DETACH(t) pthread_detach(&(t))
31#define PERL_THREAD_GETSPECIFIC(k,v) pthread_getspecific(k,&v)
32#define PERL_THREAD_ALLOC_SPECIFIC(k) STMT_START {\
33 if(pthread_keycreate(&(k),0)) {\
ddcc6fdc 34 PerlIO_printf(PerlIO_stderr(), "panic threads.xs: pthread_key_create");\
68795e93 35 exit(1);\
36 }\
37} STMT_END
38#else
39#define PERL_THREAD_DETACH(t) pthread_detach((t))
40#define PERL_THREAD_GETSPECIFIC(k,v) v = pthread_getspecific(k)
41#define PERL_THREAD_ALLOC_SPECIFIC(k) STMT_START {\
42 if(pthread_key_create(&(k),0)) {\
ddcc6fdc 43 PerlIO_printf(PerlIO_stderr(), "panic threads.xs: pthread_key_create");\
68795e93 44 exit(1);\
45 }\
46} STMT_END
47#endif
48#endif
49
62375a60 50/* Values for 'state' member */
51#define PERL_ITHR_JOINABLE 0
52#define PERL_ITHR_DETACHED 1
53#define PERL_ITHR_FINISHED 4
54#define PERL_ITHR_JOINED 2
55
68795e93 56typedef struct ithread_s {
57 struct ithread_s *next; /* next thread in the list */
58 struct ithread_s *prev; /* prev thread in the list */
59 PerlInterpreter *interp; /* The threads interpreter */
60 I32 tid; /* threads module's thread id */
61 perl_mutex mutex; /* mutex for updating things in this struct */
62 I32 count; /* how many SVs have a reference to us */
62375a60 63 signed char state; /* are we detached ? */
a446a88f 64 int gimme; /* Context of create */
68795e93 65 SV* init_function; /* Code to run */
66 SV* params; /* args to pass function */
67#ifdef WIN32
68 DWORD thr; /* OS's idea if thread id */
69 HANDLE handle; /* OS's waitable handle */
70#else
71 pthread_t thr; /* OS's handle for the thread */
72#endif
73} ithread;
74
75ithread *threads;
76
77/* Macros to supply the aTHX_ in an embed.h like manner */
78#define ithread_join(thread) Perl_ithread_join(aTHX_ thread)
79#define ithread_DESTROY(thread) Perl_ithread_DESTROY(aTHX_ thread)
80#define ithread_CLONE(thread) Perl_ithread_CLONE(aTHX_ thread)
81#define ithread_detach(thread) Perl_ithread_detach(aTHX_ thread)
82#define ithread_tid(thread) ((thread)->tid)
f9dff5f5 83#define ithread_yield(thread) (YIELD);
68795e93 84
58c2ef19 85static perl_mutex create_destruct_mutex; /* protects the creation and destruction of threads*/
68795e93 86
87I32 tid_counter = 0;
62375a60 88I32 known_threads = 0;
58c2ef19 89I32 active_threads = 0;
68795e93 90perl_key self_key;
91
92/*
93 * Clear up after thread is done with
94 */
95void
62375a60 96Perl_ithread_destruct (pTHX_ ithread* thread, const char *why)
68795e93 97{
98 MUTEX_LOCK(&thread->mutex);
62375a60 99 if (!thread->next) {
100 Perl_croak(aTHX_ "panic: destruct destroyed thread %p (%s)",thread, why);
101 }
68795e93 102 if (thread->count != 0) {
103 MUTEX_UNLOCK(&thread->mutex);
d1400e48 104 return;
68795e93 105 }
58c2ef19 106 MUTEX_LOCK(&create_destruct_mutex);
68795e93 107 /* Remove from circular list of threads */
108 if (thread->next == thread) {
109 /* last one should never get here ? */
110 threads = NULL;
111 }
112 else {
f42ad631 113 thread->next->prev = thread->prev;
114 thread->prev->next = thread->next;
68795e93 115 if (threads == thread) {
116 threads = thread->next;
117 }
62375a60 118 thread->next = NULL;
119 thread->prev = NULL;
68795e93 120 }
62375a60 121 known_threads--;
122 assert( known_threads >= 0 );
ba14dd9a 123#if 0
62375a60 124 Perl_warn(aTHX_ "destruct %d @ %p by %p now %d",
125 thread->tid,thread->interp,aTHX, known_threads);
ba14dd9a 126#endif
62375a60 127 MUTEX_UNLOCK(&create_destruct_mutex);
128 /* Thread is now disowned */
c2f2a82b 129
130 if(thread->interp) {
1c3adb19 131 dTHXa(thread->interp);
c2f2a82b 132 ithread* current_thread;
68795e93 133 PERL_SET_CONTEXT(thread->interp);
c2f2a82b 134 PERL_THREAD_GETSPECIFIC(self_key,current_thread);
135 PERL_THREAD_SETSPECIFIC(self_key,thread);
3b1c3273 136
137
138
1c3adb19 139 SvREFCNT_dec(thread->params);
3b1c3273 140
141
142
1c3adb19 143 thread->params = Nullsv;
c2f2a82b 144 perl_destruct(thread->interp);
145 perl_free(thread->interp);
68795e93 146 thread->interp = NULL;
c2f2a82b 147 PERL_THREAD_SETSPECIFIC(self_key,current_thread);
148
68795e93 149 }
d1400e48 150 MUTEX_UNLOCK(&thread->mutex);
1c3adb19 151 MUTEX_DESTROY(&thread->mutex);
152 PerlMemShared_free(thread);
1d784c90 153
64821230 154 PERL_SET_CONTEXT(aTHX);
68795e93 155}
156
62375a60 157int
158Perl_ithread_hook(pTHX)
159{
160 int veto_cleanup = 0;
161 MUTEX_LOCK(&create_destruct_mutex);
162 if (aTHX == PL_curinterp && active_threads != 1) {
3c42a367 163 Perl_warn(aTHX_ "A thread exited while %" IVdf " threads were running",
436c6dd3 164 (IV)active_threads);
62375a60 165 veto_cleanup = 1;
166 }
167 MUTEX_UNLOCK(&create_destruct_mutex);
168 return veto_cleanup;
169}
170
171void
172Perl_ithread_detach(pTHX_ ithread *thread)
173{
174 MUTEX_LOCK(&thread->mutex);
175 if (!(thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED))) {
176 thread->state |= PERL_ITHR_DETACHED;
177#ifdef WIN32
178 CloseHandle(thread->handle);
179 thread->handle = 0;
180#else
181 PERL_THREAD_DETACH(thread->thr);
182#endif
183 }
184 if ((thread->state & PERL_ITHR_FINISHED) &&
185 (thread->state & PERL_ITHR_DETACHED)) {
186 MUTEX_UNLOCK(&thread->mutex);
187 Perl_ithread_destruct(aTHX_ thread, "detach");
188 }
189 else {
190 MUTEX_UNLOCK(&thread->mutex);
191 }
192}
68795e93 193
194/* MAGIC (in mg.h sense) hooks */
195
196int
197ithread_mg_get(pTHX_ SV *sv, MAGIC *mg)
198{
199 ithread *thread = (ithread *) mg->mg_ptr;
200 SvIVX(sv) = PTR2IV(thread);
201 SvIOK_on(sv);
202 return 0;
203}
204
205int
206ithread_mg_free(pTHX_ SV *sv, MAGIC *mg)
207{
208 ithread *thread = (ithread *) mg->mg_ptr;
209 MUTEX_LOCK(&thread->mutex);
68795e93 210 thread->count--;
62375a60 211 if (thread->count == 0) {
1c3adb19 212 if(thread->state & PERL_ITHR_FINISHED &&
213 (thread->state & PERL_ITHR_DETACHED ||
214 thread->state & PERL_ITHR_JOINED))
215 {
216 MUTEX_UNLOCK(&thread->mutex);
217 Perl_ithread_destruct(aTHX_ thread, "no reference");
218 }
1ea20f42 219 else {
220 MUTEX_UNLOCK(&thread->mutex);
221 }
62375a60 222 }
223 else {
224 MUTEX_UNLOCK(&thread->mutex);
225 }
68795e93 226 return 0;
227}
228
229int
230ithread_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
231{
232 ithread *thread = (ithread *) mg->mg_ptr;
233 MUTEX_LOCK(&thread->mutex);
68795e93 234 thread->count++;
235 MUTEX_UNLOCK(&thread->mutex);
236 return 0;
237}
238
239MGVTBL ithread_vtbl = {
240 ithread_mg_get, /* get */
241 0, /* set */
242 0, /* len */
243 0, /* clear */
244 ithread_mg_free, /* free */
245 0, /* copy */
246 ithread_mg_dup /* dup */
247};
248
47ba8780 249
47ba8780 250/*
b1edfb69 251 * Starts executing the thread. Needs to clean up memory a tad better.
68795e93 252 * Passed as the C level function to run in the new thread
b1edfb69 253 */
47ba8780 254
255#ifdef WIN32
68795e93 256THREAD_RET_TYPE
257Perl_ithread_run(LPVOID arg) {
47ba8780 258#else
68795e93 259void*
260Perl_ithread_run(void * arg) {
47ba8780 261#endif
5b414d21 262 ithread* thread = (ithread*) arg;
47ba8780 263 dTHXa(thread->interp);
47ba8780 264 PERL_SET_CONTEXT(thread->interp);
68795e93 265 PERL_THREAD_SETSPECIFIC(self_key,thread);
47ba8780 266
68795e93 267#if 0
268 /* Far from clear messing with ->thr child-side is a good idea */
269 MUTEX_LOCK(&thread->mutex);
47ba8780 270#ifdef WIN32
271 thread->thr = GetCurrentThreadId();
272#else
273 thread->thr = pthread_self();
274#endif
68795e93 275 MUTEX_UNLOCK(&thread->mutex);
276#endif
47ba8780 277
47ba8780 278 PL_perl_destruct_level = 2;
4f896ddc 279
47ba8780 280 {
68795e93 281 AV* params = (AV*) SvRV(thread->params);
282 I32 len = av_len(params)+1;
47ba8780 283 int i;
284 dSP;
47ba8780 285 ENTER;
286 SAVETMPS;
287 PUSHMARK(SP);
68795e93 288 for(i = 0; i < len; i++) {
289 XPUSHs(av_shift(params));
47ba8780 290 }
291 PUTBACK;
a446a88f 292 len = call_sv(thread->init_function, thread->gimme|G_EVAL);
0405e91e 293
68795e93 294 SPAGAIN;
a446a88f 295 for (i=len-1; i >= 0; i--) {
e1c44605 296 SV *sv = POPs;
297 av_store(params, i, SvREFCNT_inc(sv));
a446a88f 298 }
a446a88f 299 if (SvTRUE(ERRSV)) {
6b3c7930 300 Perl_warn(aTHX_ "thread failed to start: %" SVf, ERRSV);
a446a88f 301 }
47ba8780 302 FREETMPS;
303 LEAVE;
68795e93 304 SvREFCNT_dec(thread->init_function);
47ba8780 305 }
306
fd58862f 307 PerlIO_flush((PerlIO*)NULL);
68795e93 308 MUTEX_LOCK(&thread->mutex);
62375a60 309 thread->state |= PERL_ITHR_FINISHED;
310
311 if (thread->state & PERL_ITHR_DETACHED) {
47ba8780 312 MUTEX_UNLOCK(&thread->mutex);
62375a60 313 Perl_ithread_destruct(aTHX_ thread, "detached finish");
47ba8780 314 } else {
62375a60 315 MUTEX_UNLOCK(&thread->mutex);
316 }
91604d21 317 MUTEX_LOCK(&create_destruct_mutex);
318 active_threads--;
319 assert( active_threads >= 0 );
320 MUTEX_UNLOCK(&create_destruct_mutex);
321
47ba8780 322#ifdef WIN32
323 return (DWORD)0;
e8f2bb9a 324#else
325 return 0;
47ba8780 326#endif
68795e93 327}
328
329SV *
330ithread_to_SV(pTHX_ SV *obj, ithread *thread, char *classname, bool inc)
331{
332 SV *sv;
333 MAGIC *mg;
334 if (inc) {
335 MUTEX_LOCK(&thread->mutex);
336 thread->count++;
68795e93 337 MUTEX_UNLOCK(&thread->mutex);
338 }
339 if (!obj)
340 obj = newSV(0);
341 sv = newSVrv(obj,classname);
342 sv_setiv(sv,PTR2IV(thread));
343 mg = sv_magicext(sv,Nullsv,PERL_MAGIC_shared_scalar,&ithread_vtbl,(char *)thread,0);
344 mg->mg_flags |= MGf_DUP;
345 SvREADONLY_on(sv);
346 return obj;
347}
47ba8780 348
68795e93 349ithread *
350SV_to_ithread(pTHX_ SV *sv)
351{
352 ithread *thread;
20b634c2 353#ifdef OEMVS
354 void *ptr;
355#endif
68795e93 356 if (SvROK(sv))
357 {
358 thread = INT2PTR(ithread*, SvIV(SvRV(sv)));
359 }
360 else
361 {
20b634c2 362#ifdef OEMVS
363 PERL_THREAD_GETSPECIFIC(self_key,ptr);
364 thread = (ithread *) ptr;
365#else
68795e93 366 PERL_THREAD_GETSPECIFIC(self_key,thread);
20b634c2 367#endif
68795e93 368 }
369 return thread;
47ba8780 370}
371
47ba8780 372/*
68795e93 373 * iThread->create(); ( aka iThread->new() )
374 * Called in context of parent thread
b1edfb69 375 */
47ba8780 376
68795e93 377SV *
378Perl_ithread_create(pTHX_ SV *obj, char* classname, SV* init_function, SV* params)
379{
380 ithread* thread;
381 CLONE_PARAMS clone_param;
1d784c90 382 ithread* current_thread;
3b1c3273 383
384 SV** tmps_tmp = PL_tmps_stack;
385 I32 tmps_ix = PL_tmps_ix;
386
1d784c90 387 PERL_THREAD_GETSPECIFIC(self_key,current_thread);
58c2ef19 388 MUTEX_LOCK(&create_destruct_mutex);
68795e93 389 thread = PerlMemShared_malloc(sizeof(ithread));
390 Zero(thread,1,ithread);
391 thread->next = threads;
392 thread->prev = threads->prev;
f42ad631 393 threads->prev = thread;
68795e93 394 thread->prev->next = thread;
395 /* Set count to 1 immediately in case thread exits before
396 * we return to caller !
397 */
398 thread->count = 1;
399 MUTEX_INIT(&thread->mutex);
400 thread->tid = tid_counter++;
a446a88f 401 thread->gimme = GIMME_V;
4f896ddc 402
68795e93 403 /* "Clone" our interpreter into the thread's interpreter
404 * This gives thread access to "static data" and code.
405 */
47ba8780 406
68795e93 407 PerlIO_flush((PerlIO*)NULL);
1d784c90 408 PERL_THREAD_SETSPECIFIC(self_key,thread);
3b1c3273 409
9c98058e 410 SAVEBOOL(PL_srand_called); /* Save this so it becomes the correct
411 value */
412 PL_srand_called = FALSE; /* Set it to false so we can detect
413 if it gets set during the clone */
3b1c3273 414
47ba8780 415#ifdef WIN32
68795e93 416 thread->interp = perl_clone(aTHX, CLONEf_KEEP_PTR_TABLE | CLONEf_CLONE_HOST);
47ba8780 417#else
68795e93 418 thread->interp = perl_clone(aTHX, CLONEf_KEEP_PTR_TABLE);
47ba8780 419#endif
ba14dd9a 420 /* perl_clone leaves us in new interpreter's context.
c8dae523 421 As it is tricky to spot an implicit aTHX, create a new scope
a446a88f 422 with aTHX matching the context for the duration of
ba14dd9a 423 our work for new interpreter.
424 */
425 {
426 dTHXa(thread->interp);
9c98058e 427
58c2ef19 428 /* Here we remove END blocks since they should only run
62375a60 429 in the thread they are created
58c2ef19 430 */
431 SvREFCNT_dec(PL_endav);
432 PL_endav = newAV();
d1400e48 433 clone_param.flags = 0;
ba14dd9a 434 thread->init_function = sv_dup(init_function, &clone_param);
435 if (SvREFCNT(thread->init_function) == 0) {
436 SvREFCNT_inc(thread->init_function);
d1400e48 437 }
3b1c3273 438
439
ba14dd9a 440
441 thread->params = sv_dup(params, &clone_param);
442 SvREFCNT_inc(thread->params);
3b1c3273 443
444
445 /* The code below checks that anything living on
446 the tmps stack and has been cloned (so it lives in the
447 ptr_table) has a refcount higher than 0
448
449 If the refcount is 0 it means that a something on the
450 stack/context was holding a reference to it and
451 since we init_stacks() in perl_clone that won't get
452 cleaned and we will get a leaked scalar.
453 The reason it was cloned was that it lived on the
454 @_ stack.
455
456 Example of this can be found in bugreport 15837
457 where calls in the parameter list end up as a temp
458
459 One could argue that this fix should be in perl_clone
460 */
461
462
463 while (tmps_ix > 0) {
464 SV* sv = (SV*)ptr_table_fetch(PL_ptr_table, tmps_tmp[tmps_ix]);
465 tmps_ix--;
466 if (sv && SvREFCNT(sv) == 0) {
467 SvREFCNT_inc(sv);
468 SvREFCNT_dec(sv);
469 }
470 }
471
472
473
ba14dd9a 474 SvTEMP_off(thread->init_function);
475 ptr_table_free(PL_ptr_table);
476 PL_ptr_table = NULL;
ffb29f90 477 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
ba14dd9a 478 }
1d784c90 479 PERL_THREAD_SETSPECIFIC(self_key,current_thread);
68795e93 480 PERL_SET_CONTEXT(aTHX);
47ba8780 481
68795e93 482 /* Start the thread */
47ba8780 483
484#ifdef WIN32
485
68795e93 486 thread->handle = CreateThread(NULL, 0, Perl_ithread_run,
47ba8780 487 (LPVOID)thread, 0, &thread->thr);
488
82c40bf6 489#else
fa26028c 490 {
491 static pthread_attr_t attr;
492 static int attr_inited = 0;
fa26028c 493 static int attr_joinable = PTHREAD_CREATE_JOINABLE;
494 if (!attr_inited) {
495 attr_inited = 1;
496 pthread_attr_init(&attr);
497 }
498# ifdef PTHREAD_ATTR_SETDETACHSTATE
499 PTHREAD_ATTR_SETDETACHSTATE(&attr, attr_joinable);
500# endif
3eb37d38 501# ifdef THREAD_CREATE_NEEDS_STACK
502 if(pthread_attr_setstacksize(&attr, THREAD_CREATE_NEEDS_STACK))
503 croak("panic: pthread_attr_setstacksize failed");
504# endif
505
3ad0b7d6 506#ifdef OLD_PTHREADS_API
68795e93 507 pthread_create( &thread->thr, attr, Perl_ithread_run, (void *)thread);
47ba8780 508#else
19a077f6 509# ifdef PTHREAD_SCOPE_SYSTEM
47cb5ff9 510 pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );
19a077f6 511# endif
68795e93 512 pthread_create( &thread->thr, &attr, Perl_ithread_run, (void *)thread);
47ba8780 513#endif
3ad0b7d6 514 }
82c40bf6 515#endif
62375a60 516 known_threads++;
58c2ef19 517 active_threads++;
518 MUTEX_UNLOCK(&create_destruct_mutex);
95393226 519 sv_2mortal(params);
3b1c3273 520
68795e93 521 return ithread_to_SV(aTHX_ obj, thread, classname, FALSE);
522}
47ba8780 523
68795e93 524SV*
525Perl_ithread_self (pTHX_ SV *obj, char* Class)
526{
527 ithread *thread;
20b634c2 528#ifdef OEMVS
529 void *ptr;
530 PERL_THREAD_GETSPECIFIC(self_key,ptr);
531 thread = (ithread *) ptr;
532#else
68795e93 533 PERL_THREAD_GETSPECIFIC(self_key,thread);
20b634c2 534#endif
fe53aa5b 535 if (thread)
536 return ithread_to_SV(aTHX_ obj, thread, Class, TRUE);
537 else
538 Perl_croak(aTHX_ "panic: cannot find thread data");
47ba8780 539}
540
541/*
e1c44605 542 * Joins the thread this code needs to take the returnvalue from the
68795e93 543 * call_sv and send it back
b1edfb69 544 */
47ba8780 545
68795e93 546void
547Perl_ithread_CLONE(pTHX_ SV *obj)
548{
549 if (SvROK(obj))
550 {
551 ithread *thread = SV_to_ithread(aTHX_ obj);
552 }
553 else
554 {
436c6dd3 555 Perl_warn(aTHX_ "CLONE %" SVf,obj);
68795e93 556 }
47ba8780 557}
558
62375a60 559AV*
68795e93 560Perl_ithread_join(pTHX_ SV *obj)
561{
562 ithread *thread = SV_to_ithread(aTHX_ obj);
563 MUTEX_LOCK(&thread->mutex);
62375a60 564 if (thread->state & PERL_ITHR_DETACHED) {
a446a88f 565 MUTEX_UNLOCK(&thread->mutex);
566 Perl_croak(aTHX_ "Cannot join a detached thread");
567 }
62375a60 568 else if (thread->state & PERL_ITHR_JOINED) {
a446a88f 569 MUTEX_UNLOCK(&thread->mutex);
570 Perl_croak(aTHX_ "Thread already joined");
571 }
572 else {
e1c44605 573 AV* retparam;
47ba8780 574#ifdef WIN32
575 DWORD waitcode;
47ba8780 576#else
577 void *retval;
47ba8780 578#endif
47ba8780 579 MUTEX_UNLOCK(&thread->mutex);
68795e93 580#ifdef WIN32
581 waitcode = WaitForSingleObject(thread->handle, INFINITE);
582#else
583 pthread_join(thread->thr,&retval);
584#endif
47ba8780 585 MUTEX_LOCK(&thread->mutex);
e1c44605 586
62375a60 587 /* sv_dup over the args */
e1c44605 588 {
1d784c90 589 ithread* current_thread;
62375a60 590 AV* params = (AV*) SvRV(thread->params);
e1c44605 591 CLONE_PARAMS clone_params;
3275ba96 592 clone_params.stashes = newAV();
0405e91e 593 clone_params.flags |= CLONEf_JOIN_IN;
e1c44605 594 PL_ptr_table = ptr_table_new();
1d784c90 595 PERL_THREAD_GETSPECIFIC(self_key,current_thread);
596 PERL_THREAD_SETSPECIFIC(self_key,thread);
0405e91e 597
767c1403 598#if 0
0405e91e 599 {
600 I32 len = av_len(params)+1;
601 I32 i;
602 for(i = 0; i < len; i++) {
767c1403 603 sv_dump(SvRV(AvARRAY(params)[i]));
0405e91e 604 }
605 }
767c1403 606#endif
e1c44605 607 retparam = (AV*) sv_dup((SV*)params, &clone_params);
b4cb676b 608#if 0
0405e91e 609 {
610 I32 len = av_len(retparam)+1;
611 I32 i;
612 for(i = 0; i < len; i++) {
b4cb676b 613 sv_dump(SvRV(AvARRAY(retparam)[i]));
0405e91e 614 }
615 }
b4cb676b 616#endif
1d784c90 617 PERL_THREAD_SETSPECIFIC(self_key,current_thread);
3275ba96 618 SvREFCNT_dec(clone_params.stashes);
e1c44605 619 SvREFCNT_inc(retparam);
620 ptr_table_free(PL_ptr_table);
621 PL_ptr_table = NULL;
622
623 }
a446a88f 624 /* We have finished with it */
62375a60 625 thread->state |= PERL_ITHR_JOINED;
47ba8780 626 MUTEX_UNLOCK(&thread->mutex);
57b48062 627
e1c44605 628 return retparam;
68795e93 629 }
e1c44605 630 return (AV*)NULL;
47ba8780 631}
632
68795e93 633void
68795e93 634Perl_ithread_DESTROY(pTHX_ SV *sv)
635{
636 ithread *thread = SV_to_ithread(aTHX_ sv);
68795e93 637 sv_unmagic(SvRV(sv),PERL_MAGIC_shared_scalar);
638}
8222d950 639
73e09c8f 640#endif /* USE_ITHREADS */
e1c44605 641
68795e93 642MODULE = threads PACKAGE = threads PREFIX = ithread_
643PROTOTYPES: DISABLE
8222d950 644
73e09c8f 645#ifdef USE_ITHREADS
646
68795e93 647void
648ithread_new (classname, function_to_call, ...)
649char * classname
650SV * function_to_call
651CODE:
652{
653 AV* params = newAV();
654 if (items > 2) {
655 int i;
656 for(i = 2; i < items ; i++) {
95393226 657 av_push(params, SvREFCNT_inc(ST(i)));
68795e93 658 }
659 }
660 ST(0) = sv_2mortal(Perl_ithread_create(aTHX_ Nullsv, classname, function_to_call, newRV_noinc((SV*) params)));
661 XSRETURN(1);
662}
8222d950 663
68795e93 664void
678a9b6c 665ithread_list(char *classname)
666PPCODE:
667{
668 ithread *curr_thread;
669 MUTEX_LOCK(&create_destruct_mutex);
670 curr_thread = threads;
5eb9fe8f 671 if(curr_thread->tid != 0)
672 PUSHs( sv_2mortal(ithread_to_SV(aTHX_ NULL, curr_thread, classname, TRUE)));
678a9b6c 673 while(curr_thread) {
678a9b6c 674 curr_thread = curr_thread->next;
675 if(curr_thread == threads)
676 break;
6794f985 677 if(curr_thread->state & PERL_ITHR_DETACHED ||
5eb9fe8f 678 curr_thread->state & PERL_ITHR_JOINED)
679 continue;
680 PUSHs( sv_2mortal(ithread_to_SV(aTHX_ NULL, curr_thread, classname, TRUE)));
678a9b6c 681 }
682 MUTEX_UNLOCK(&create_destruct_mutex);
683}
684
685
686void
68795e93 687ithread_self(char *classname)
688CODE:
689{
690 ST(0) = sv_2mortal(Perl_ithread_self(aTHX_ Nullsv,classname));
691 XSRETURN(1);
692}
47ba8780 693
694int
68795e93 695ithread_tid(ithread *thread)
47ba8780 696
697void
68795e93 698ithread_join(SV *obj)
e1c44605 699PPCODE:
700{
701 AV* params = Perl_ithread_join(aTHX_ obj);
702 int i;
703 I32 len = AvFILL(params);
704 for (i = 0; i <= len; i++) {
1c3adb19 705 SV* tmp = av_shift(params);
706 XPUSHs(tmp);
707 sv_2mortal(tmp);
e1c44605 708 }
709 SvREFCNT_dec(params);
710}
711
f9dff5f5 712void
9d7debe1 713yield(...)
70f2e746 714CODE:
715{
716 YIELD;
717}
718
47ba8780 719
720void
68795e93 721ithread_detach(ithread *thread)
47ba8780 722
47ba8780 723void
68795e93 724ithread_DESTROY(SV *thread)
725
73e09c8f 726#endif /* USE_ITHREADS */
727
68795e93 728BOOT:
729{
73e09c8f 730#ifdef USE_ITHREADS
68795e93 731 ithread* thread;
e1c44605 732 PL_perl_destruct_level = 2;
68795e93 733 PERL_THREAD_ALLOC_SPECIFIC(self_key);
58c2ef19 734 MUTEX_INIT(&create_destruct_mutex);
735 MUTEX_LOCK(&create_destruct_mutex);
62375a60 736 PL_threadhook = &Perl_ithread_hook;
68795e93 737 thread = PerlMemShared_malloc(sizeof(ithread));
738 Zero(thread,1,ithread);
739 PL_perl_destruct_level = 2;
740 MUTEX_INIT(&thread->mutex);
741 threads = thread;
742 thread->next = thread;
743 thread->prev = thread;
744 thread->interp = aTHX;
745 thread->count = 1; /* imortal */
746 thread->tid = tid_counter++;
62375a60 747 known_threads++;
58c2ef19 748 active_threads++;
62375a60 749 thread->state = 1;
68795e93 750#ifdef WIN32
751 thread->thr = GetCurrentThreadId();
752#else
753 thread->thr = pthread_self();
754#endif
62375a60 755
68795e93 756 PERL_THREAD_SETSPECIFIC(self_key,thread);
58c2ef19 757 MUTEX_UNLOCK(&create_destruct_mutex);
73e09c8f 758#endif /* USE_ITHREADS */
68795e93 759}
760