[Encode] UTF-7 Support
[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) {\
16 PerlIO_printf(PerlIO_stderr(),"panic threads.h: TlsAlloc");\
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)) {\
34 PerlIO_printf(PerlIO_stderr(), "panic threads.h: pthread_key_create");\
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)) {\
43 PerlIO_printf(PerlIO_stderr(), "panic threads.h: pthread_key_create");\
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
47cb5ff9 509 pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );
68795e93 510 pthread_create( &thread->thr, &attr, Perl_ithread_run, (void *)thread);
47ba8780 511#endif
3ad0b7d6 512 }
82c40bf6 513#endif
62375a60 514 known_threads++;
58c2ef19 515 active_threads++;
516 MUTEX_UNLOCK(&create_destruct_mutex);
95393226 517 sv_2mortal(params);
3b1c3273 518
68795e93 519 return ithread_to_SV(aTHX_ obj, thread, classname, FALSE);
520}
47ba8780 521
68795e93 522SV*
523Perl_ithread_self (pTHX_ SV *obj, char* Class)
524{
525 ithread *thread;
20b634c2 526#ifdef OEMVS
527 void *ptr;
528 PERL_THREAD_GETSPECIFIC(self_key,ptr);
529 thread = (ithread *) ptr;
530#else
68795e93 531 PERL_THREAD_GETSPECIFIC(self_key,thread);
20b634c2 532#endif
68795e93 533 return ithread_to_SV(aTHX_ obj, thread, Class, TRUE);
47ba8780 534}
535
536/*
e1c44605 537 * Joins the thread this code needs to take the returnvalue from the
68795e93 538 * call_sv and send it back
b1edfb69 539 */
47ba8780 540
68795e93 541void
542Perl_ithread_CLONE(pTHX_ SV *obj)
543{
544 if (SvROK(obj))
545 {
546 ithread *thread = SV_to_ithread(aTHX_ obj);
547 }
548 else
549 {
436c6dd3 550 Perl_warn(aTHX_ "CLONE %" SVf,obj);
68795e93 551 }
47ba8780 552}
553
62375a60 554AV*
68795e93 555Perl_ithread_join(pTHX_ SV *obj)
556{
557 ithread *thread = SV_to_ithread(aTHX_ obj);
558 MUTEX_LOCK(&thread->mutex);
62375a60 559 if (thread->state & PERL_ITHR_DETACHED) {
a446a88f 560 MUTEX_UNLOCK(&thread->mutex);
561 Perl_croak(aTHX_ "Cannot join a detached thread");
562 }
62375a60 563 else if (thread->state & PERL_ITHR_JOINED) {
a446a88f 564 MUTEX_UNLOCK(&thread->mutex);
565 Perl_croak(aTHX_ "Thread already joined");
566 }
567 else {
e1c44605 568 AV* retparam;
47ba8780 569#ifdef WIN32
570 DWORD waitcode;
47ba8780 571#else
572 void *retval;
47ba8780 573#endif
47ba8780 574 MUTEX_UNLOCK(&thread->mutex);
68795e93 575#ifdef WIN32
576 waitcode = WaitForSingleObject(thread->handle, INFINITE);
577#else
578 pthread_join(thread->thr,&retval);
579#endif
47ba8780 580 MUTEX_LOCK(&thread->mutex);
e1c44605 581
62375a60 582 /* sv_dup over the args */
e1c44605 583 {
1d784c90 584 ithread* current_thread;
62375a60 585 AV* params = (AV*) SvRV(thread->params);
e1c44605 586 CLONE_PARAMS clone_params;
3275ba96 587 clone_params.stashes = newAV();
0405e91e 588 clone_params.flags |= CLONEf_JOIN_IN;
e1c44605 589 PL_ptr_table = ptr_table_new();
1d784c90 590 PERL_THREAD_GETSPECIFIC(self_key,current_thread);
591 PERL_THREAD_SETSPECIFIC(self_key,thread);
0405e91e 592
767c1403 593#if 0
0405e91e 594 {
595 I32 len = av_len(params)+1;
596 I32 i;
597 for(i = 0; i < len; i++) {
767c1403 598 sv_dump(SvRV(AvARRAY(params)[i]));
0405e91e 599 }
600 }
767c1403 601#endif
e1c44605 602 retparam = (AV*) sv_dup((SV*)params, &clone_params);
b4cb676b 603#if 0
0405e91e 604 {
605 I32 len = av_len(retparam)+1;
606 I32 i;
607 for(i = 0; i < len; i++) {
b4cb676b 608 sv_dump(SvRV(AvARRAY(retparam)[i]));
0405e91e 609 }
610 }
b4cb676b 611#endif
1d784c90 612 PERL_THREAD_SETSPECIFIC(self_key,current_thread);
3275ba96 613 SvREFCNT_dec(clone_params.stashes);
e1c44605 614 SvREFCNT_inc(retparam);
615 ptr_table_free(PL_ptr_table);
616 PL_ptr_table = NULL;
617
618 }
a446a88f 619 /* We have finished with it */
62375a60 620 thread->state |= PERL_ITHR_JOINED;
47ba8780 621 MUTEX_UNLOCK(&thread->mutex);
57b48062 622
e1c44605 623 return retparam;
68795e93 624 }
e1c44605 625 return (AV*)NULL;
47ba8780 626}
627
68795e93 628void
68795e93 629Perl_ithread_DESTROY(pTHX_ SV *sv)
630{
631 ithread *thread = SV_to_ithread(aTHX_ sv);
68795e93 632 sv_unmagic(SvRV(sv),PERL_MAGIC_shared_scalar);
633}
8222d950 634
73e09c8f 635#endif /* USE_ITHREADS */
e1c44605 636
68795e93 637MODULE = threads PACKAGE = threads PREFIX = ithread_
638PROTOTYPES: DISABLE
8222d950 639
73e09c8f 640#ifdef USE_ITHREADS
641
68795e93 642void
643ithread_new (classname, function_to_call, ...)
644char * classname
645SV * function_to_call
646CODE:
647{
648 AV* params = newAV();
649 if (items > 2) {
650 int i;
651 for(i = 2; i < items ; i++) {
95393226 652 av_push(params, SvREFCNT_inc(ST(i)));
68795e93 653 }
654 }
655 ST(0) = sv_2mortal(Perl_ithread_create(aTHX_ Nullsv, classname, function_to_call, newRV_noinc((SV*) params)));
656 XSRETURN(1);
657}
8222d950 658
68795e93 659void
678a9b6c 660ithread_list(char *classname)
661PPCODE:
662{
663 ithread *curr_thread;
664 MUTEX_LOCK(&create_destruct_mutex);
665 curr_thread = threads;
5eb9fe8f 666 if(curr_thread->tid != 0)
667 PUSHs( sv_2mortal(ithread_to_SV(aTHX_ NULL, curr_thread, classname, TRUE)));
678a9b6c 668 while(curr_thread) {
678a9b6c 669 curr_thread = curr_thread->next;
670 if(curr_thread == threads)
671 break;
6794f985 672 if(curr_thread->state & PERL_ITHR_DETACHED ||
5eb9fe8f 673 curr_thread->state & PERL_ITHR_JOINED)
674 continue;
675 PUSHs( sv_2mortal(ithread_to_SV(aTHX_ NULL, curr_thread, classname, TRUE)));
678a9b6c 676 }
677 MUTEX_UNLOCK(&create_destruct_mutex);
678}
679
680
681void
68795e93 682ithread_self(char *classname)
683CODE:
684{
685 ST(0) = sv_2mortal(Perl_ithread_self(aTHX_ Nullsv,classname));
686 XSRETURN(1);
687}
47ba8780 688
689int
68795e93 690ithread_tid(ithread *thread)
47ba8780 691
692void
68795e93 693ithread_join(SV *obj)
e1c44605 694PPCODE:
695{
696 AV* params = Perl_ithread_join(aTHX_ obj);
697 int i;
698 I32 len = AvFILL(params);
699 for (i = 0; i <= len; i++) {
1c3adb19 700 SV* tmp = av_shift(params);
701 XPUSHs(tmp);
702 sv_2mortal(tmp);
e1c44605 703 }
704 SvREFCNT_dec(params);
705}
706
f9dff5f5 707void
9d7debe1 708yield(...)
70f2e746 709CODE:
710{
711 YIELD;
712}
713
47ba8780 714
715void
68795e93 716ithread_detach(ithread *thread)
47ba8780 717
47ba8780 718void
68795e93 719ithread_DESTROY(SV *thread)
720
73e09c8f 721#endif /* USE_ITHREADS */
722
68795e93 723BOOT:
724{
73e09c8f 725#ifdef USE_ITHREADS
68795e93 726 ithread* thread;
e1c44605 727 PL_perl_destruct_level = 2;
68795e93 728 PERL_THREAD_ALLOC_SPECIFIC(self_key);
58c2ef19 729 MUTEX_INIT(&create_destruct_mutex);
730 MUTEX_LOCK(&create_destruct_mutex);
62375a60 731 PL_threadhook = &Perl_ithread_hook;
68795e93 732 thread = PerlMemShared_malloc(sizeof(ithread));
733 Zero(thread,1,ithread);
734 PL_perl_destruct_level = 2;
735 MUTEX_INIT(&thread->mutex);
736 threads = thread;
737 thread->next = thread;
738 thread->prev = thread;
739 thread->interp = aTHX;
740 thread->count = 1; /* imortal */
741 thread->tid = tid_counter++;
62375a60 742 known_threads++;
58c2ef19 743 active_threads++;
62375a60 744 thread->state = 1;
68795e93 745#ifdef WIN32
746 thread->thr = GetCurrentThreadId();
747#else
748 thread->thr = pthread_self();
749#endif
62375a60 750
68795e93 751 PERL_THREAD_SETSPECIFIC(self_key,thread);
58c2ef19 752 MUTEX_UNLOCK(&create_destruct_mutex);
73e09c8f 753#endif /* USE_ITHREADS */
68795e93 754}
755