This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Don't recurse from threads to threads/shared (since
[perl5.git] / ext / threads / threads.xs
CommitLineData
68795e93
NIS
1#define PERL_NO_GET_CONTEXT
2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
5
73e09c8f
JH
6#ifdef USE_ITHREADS
7
68795e93
NIS
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
IZ
21#ifdef OS2
22typedef perl_os_thread pthread_t;
23#else
68795e93 24#include <pthread.h>
5c728af0 25#endif
68795e93
NIS
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
NIS
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
NIS
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
NIS
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
NIS
86
87I32 tid_counter = 0;
62375a60 88I32 known_threads = 0;
58c2ef19 89I32 active_threads = 0;
68795e93
NIS
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
NIS
97{
98 MUTEX_LOCK(&thread->mutex);
62375a60
NIS
99 if (!thread->next) {
100 Perl_croak(aTHX_ "panic: destruct destroyed thread %p (%s)",thread, why);
101 }
68795e93
NIS
102 if (thread->count != 0) {
103 MUTEX_UNLOCK(&thread->mutex);
d1400e48 104 return;
68795e93 105 }
58c2ef19 106 MUTEX_LOCK(&create_destruct_mutex);
68795e93
NIS
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
AB
113 thread->next->prev = thread->prev;
114 thread->prev->next = thread->next;
68795e93
NIS
115 if (threads == thread) {
116 threads = thread->next;
117 }
62375a60
NIS
118 thread->next = NULL;
119 thread->prev = NULL;
68795e93 120 }
62375a60
NIS
121 known_threads--;
122 assert( known_threads >= 0 );
ba14dd9a 123#if 0
62375a60
NIS
124 Perl_warn(aTHX_ "destruct %d @ %p by %p now %d",
125 thread->tid,thread->interp,aTHX, known_threads);
ba14dd9a 126#endif
62375a60
NIS
127 MUTEX_UNLOCK(&create_destruct_mutex);
128 /* Thread is now disowned */
c2f2a82b
AB
129
130 if(thread->interp) {
1c3adb19 131 dTHXa(thread->interp);
c2f2a82b 132 ithread* current_thread;
68795e93 133 PERL_SET_CONTEXT(thread->interp);
c2f2a82b
AB
134 PERL_THREAD_GETSPECIFIC(self_key,current_thread);
135 PERL_THREAD_SETSPECIFIC(self_key,thread);
3b1c3273
AB
136
137
138
1c3adb19 139 SvREFCNT_dec(thread->params);
3b1c3273
AB
140
141
142
1c3adb19 143 thread->params = Nullsv;
c2f2a82b
AB
144 perl_destruct(thread->interp);
145 perl_free(thread->interp);
68795e93 146 thread->interp = NULL;
c2f2a82b
AB
147 PERL_THREAD_SETSPECIFIC(self_key,current_thread);
148
68795e93 149 }
d1400e48 150 MUTEX_UNLOCK(&thread->mutex);
1c3adb19
AB
151 MUTEX_DESTROY(&thread->mutex);
152 PerlMemShared_free(thread);
1d784c90 153
64821230 154 PERL_SET_CONTEXT(aTHX);
68795e93
NIS
155}
156
62375a60
NIS
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
NIS
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
NIS
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
AB
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
AB
219 else {
220 MUTEX_UNLOCK(&thread->mutex);
221 }
62375a60
NIS
222 }
223 else {
224 MUTEX_UNLOCK(&thread->mutex);
225 }
68795e93
NIS
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
NIS
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
AB
254
255#ifdef WIN32
68795e93
NIS
256THREAD_RET_TYPE
257Perl_ithread_run(LPVOID arg) {
47ba8780 258#else
68795e93
NIS
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
NIS
267#if 0
268 /* Far from clear messing with ->thr child-side is a good idea */
269 MUTEX_LOCK(&thread->mutex);
47ba8780
AB
270#ifdef WIN32
271 thread->thr = GetCurrentThreadId();
272#else
273 thread->thr = pthread_self();
274#endif
68795e93
NIS
275 MUTEX_UNLOCK(&thread->mutex);
276#endif
47ba8780 277
47ba8780 278 PL_perl_destruct_level = 2;
4f896ddc 279
47ba8780 280 {
68795e93
NIS
281 AV* params = (AV*) SvRV(thread->params);
282 I32 len = av_len(params)+1;
47ba8780
AB
283 int i;
284 dSP;
47ba8780
AB
285 ENTER;
286 SAVETMPS;
287 PUSHMARK(SP);
68795e93
NIS
288 for(i = 0; i < len; i++) {
289 XPUSHs(av_shift(params));
47ba8780
AB
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
AB
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
AB
302 FREETMPS;
303 LEAVE;
68795e93 304 SvREFCNT_dec(thread->init_function);
47ba8780
AB
305 }
306
fd58862f 307 PerlIO_flush((PerlIO*)NULL);
68795e93 308 MUTEX_LOCK(&thread->mutex);
62375a60
NIS
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
NIS
315 MUTEX_UNLOCK(&thread->mutex);
316 }
91604d21
AB
317 MUTEX_LOCK(&create_destruct_mutex);
318 active_threads--;
319 assert( active_threads >= 0 );
320 MUTEX_UNLOCK(&create_destruct_mutex);
321
47ba8780
AB
322#ifdef WIN32
323 return (DWORD)0;
e8f2bb9a
JH
324#else
325 return 0;
47ba8780 326#endif
68795e93
NIS
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
NIS
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
NIS
349ithread *
350SV_to_ithread(pTHX_ SV *sv)
351{
352 ithread *thread;
353 if (SvROK(sv))
354 {
355 thread = INT2PTR(ithread*, SvIV(SvRV(sv)));
356 }
357 else
358 {
359 PERL_THREAD_GETSPECIFIC(self_key,thread);
360 }
361 return thread;
47ba8780
AB
362}
363
47ba8780 364/*
68795e93
NIS
365 * iThread->create(); ( aka iThread->new() )
366 * Called in context of parent thread
b1edfb69 367 */
47ba8780 368
68795e93
NIS
369SV *
370Perl_ithread_create(pTHX_ SV *obj, char* classname, SV* init_function, SV* params)
371{
372 ithread* thread;
373 CLONE_PARAMS clone_param;
1d784c90 374 ithread* current_thread;
3b1c3273
AB
375
376 SV** tmps_tmp = PL_tmps_stack;
377 I32 tmps_ix = PL_tmps_ix;
378
1d784c90 379 PERL_THREAD_GETSPECIFIC(self_key,current_thread);
58c2ef19 380 MUTEX_LOCK(&create_destruct_mutex);
68795e93
NIS
381 thread = PerlMemShared_malloc(sizeof(ithread));
382 Zero(thread,1,ithread);
383 thread->next = threads;
384 thread->prev = threads->prev;
f42ad631 385 threads->prev = thread;
68795e93
NIS
386 thread->prev->next = thread;
387 /* Set count to 1 immediately in case thread exits before
388 * we return to caller !
389 */
390 thread->count = 1;
391 MUTEX_INIT(&thread->mutex);
392 thread->tid = tid_counter++;
a446a88f 393 thread->gimme = GIMME_V;
4f896ddc 394
68795e93
NIS
395 /* "Clone" our interpreter into the thread's interpreter
396 * This gives thread access to "static data" and code.
397 */
47ba8780 398
68795e93 399 PerlIO_flush((PerlIO*)NULL);
1d784c90 400 PERL_THREAD_SETSPECIFIC(self_key,thread);
3b1c3273
AB
401
402
403
47ba8780 404#ifdef WIN32
68795e93 405 thread->interp = perl_clone(aTHX, CLONEf_KEEP_PTR_TABLE | CLONEf_CLONE_HOST);
47ba8780 406#else
68795e93 407 thread->interp = perl_clone(aTHX, CLONEf_KEEP_PTR_TABLE);
47ba8780 408#endif
ba14dd9a 409 /* perl_clone leaves us in new interpreter's context.
c8dae523 410 As it is tricky to spot an implicit aTHX, create a new scope
a446a88f 411 with aTHX matching the context for the duration of
ba14dd9a
NIS
412 our work for new interpreter.
413 */
414 {
415 dTHXa(thread->interp);
58c2ef19 416 /* Here we remove END blocks since they should only run
62375a60 417 in the thread they are created
58c2ef19
NIS
418 */
419 SvREFCNT_dec(PL_endav);
420 PL_endav = newAV();
d1400e48 421 clone_param.flags = 0;
ba14dd9a
NIS
422 thread->init_function = sv_dup(init_function, &clone_param);
423 if (SvREFCNT(thread->init_function) == 0) {
424 SvREFCNT_inc(thread->init_function);
d1400e48 425 }
3b1c3273
AB
426
427
ba14dd9a
NIS
428
429 thread->params = sv_dup(params, &clone_param);
430 SvREFCNT_inc(thread->params);
3b1c3273
AB
431
432
433 /* The code below checks that anything living on
434 the tmps stack and has been cloned (so it lives in the
435 ptr_table) has a refcount higher than 0
436
437 If the refcount is 0 it means that a something on the
438 stack/context was holding a reference to it and
439 since we init_stacks() in perl_clone that won't get
440 cleaned and we will get a leaked scalar.
441 The reason it was cloned was that it lived on the
442 @_ stack.
443
444 Example of this can be found in bugreport 15837
445 where calls in the parameter list end up as a temp
446
447 One could argue that this fix should be in perl_clone
448 */
449
450
451 while (tmps_ix > 0) {
452 SV* sv = (SV*)ptr_table_fetch(PL_ptr_table, tmps_tmp[tmps_ix]);
453 tmps_ix--;
454 if (sv && SvREFCNT(sv) == 0) {
455 SvREFCNT_inc(sv);
456 SvREFCNT_dec(sv);
457 }
458 }
459
460
461
ba14dd9a
NIS
462 SvTEMP_off(thread->init_function);
463 ptr_table_free(PL_ptr_table);
464 PL_ptr_table = NULL;
ffb29f90 465 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
ba14dd9a 466 }
1d784c90 467 PERL_THREAD_SETSPECIFIC(self_key,current_thread);
68795e93 468 PERL_SET_CONTEXT(aTHX);
47ba8780 469
68795e93 470 /* Start the thread */
47ba8780
AB
471
472#ifdef WIN32
473
68795e93 474 thread->handle = CreateThread(NULL, 0, Perl_ithread_run,
47ba8780
AB
475 (LPVOID)thread, 0, &thread->thr);
476
82c40bf6 477#else
fa26028c
AB
478 {
479 static pthread_attr_t attr;
480 static int attr_inited = 0;
fa26028c
AB
481 static int attr_joinable = PTHREAD_CREATE_JOINABLE;
482 if (!attr_inited) {
483 attr_inited = 1;
484 pthread_attr_init(&attr);
485 }
486# ifdef PTHREAD_ATTR_SETDETACHSTATE
487 PTHREAD_ATTR_SETDETACHSTATE(&attr, attr_joinable);
488# endif
3eb37d38
AB
489# ifdef THREAD_CREATE_NEEDS_STACK
490 if(pthread_attr_setstacksize(&attr, THREAD_CREATE_NEEDS_STACK))
491 croak("panic: pthread_attr_setstacksize failed");
492# endif
493
3ad0b7d6 494#ifdef OLD_PTHREADS_API
68795e93 495 pthread_create( &thread->thr, attr, Perl_ithread_run, (void *)thread);
47ba8780 496#else
68795e93 497 pthread_create( &thread->thr, &attr, Perl_ithread_run, (void *)thread);
47ba8780 498#endif
3ad0b7d6 499 }
82c40bf6 500#endif
62375a60 501 known_threads++;
58c2ef19
NIS
502 active_threads++;
503 MUTEX_UNLOCK(&create_destruct_mutex);
95393226 504 sv_2mortal(params);
3b1c3273 505
68795e93
NIS
506 return ithread_to_SV(aTHX_ obj, thread, classname, FALSE);
507}
47ba8780 508
68795e93
NIS
509SV*
510Perl_ithread_self (pTHX_ SV *obj, char* Class)
511{
512 ithread *thread;
513 PERL_THREAD_GETSPECIFIC(self_key,thread);
514 return ithread_to_SV(aTHX_ obj, thread, Class, TRUE);
47ba8780
AB
515}
516
517/*
e1c44605 518 * Joins the thread this code needs to take the returnvalue from the
68795e93 519 * call_sv and send it back
b1edfb69 520 */
47ba8780 521
68795e93
NIS
522void
523Perl_ithread_CLONE(pTHX_ SV *obj)
524{
525 if (SvROK(obj))
526 {
527 ithread *thread = SV_to_ithread(aTHX_ obj);
528 }
529 else
530 {
436c6dd3 531 Perl_warn(aTHX_ "CLONE %" SVf,obj);
68795e93 532 }
47ba8780
AB
533}
534
62375a60 535AV*
68795e93
NIS
536Perl_ithread_join(pTHX_ SV *obj)
537{
538 ithread *thread = SV_to_ithread(aTHX_ obj);
539 MUTEX_LOCK(&thread->mutex);
62375a60 540 if (thread->state & PERL_ITHR_DETACHED) {
a446a88f
NIS
541 MUTEX_UNLOCK(&thread->mutex);
542 Perl_croak(aTHX_ "Cannot join a detached thread");
543 }
62375a60 544 else if (thread->state & PERL_ITHR_JOINED) {
a446a88f
NIS
545 MUTEX_UNLOCK(&thread->mutex);
546 Perl_croak(aTHX_ "Thread already joined");
547 }
548 else {
e1c44605 549 AV* retparam;
47ba8780
AB
550#ifdef WIN32
551 DWORD waitcode;
47ba8780
AB
552#else
553 void *retval;
47ba8780 554#endif
47ba8780 555 MUTEX_UNLOCK(&thread->mutex);
68795e93
NIS
556#ifdef WIN32
557 waitcode = WaitForSingleObject(thread->handle, INFINITE);
558#else
559 pthread_join(thread->thr,&retval);
560#endif
47ba8780 561 MUTEX_LOCK(&thread->mutex);
e1c44605 562
62375a60 563 /* sv_dup over the args */
e1c44605 564 {
1d784c90 565 ithread* current_thread;
62375a60 566 AV* params = (AV*) SvRV(thread->params);
e1c44605 567 CLONE_PARAMS clone_params;
3275ba96 568 clone_params.stashes = newAV();
0405e91e 569 clone_params.flags |= CLONEf_JOIN_IN;
e1c44605 570 PL_ptr_table = ptr_table_new();
1d784c90
AB
571 PERL_THREAD_GETSPECIFIC(self_key,current_thread);
572 PERL_THREAD_SETSPECIFIC(self_key,thread);
0405e91e 573
767c1403 574#if 0
0405e91e
AB
575 {
576 I32 len = av_len(params)+1;
577 I32 i;
578 for(i = 0; i < len; i++) {
767c1403 579 sv_dump(SvRV(AvARRAY(params)[i]));
0405e91e
AB
580 }
581 }
767c1403 582#endif
e1c44605 583 retparam = (AV*) sv_dup((SV*)params, &clone_params);
b4cb676b 584#if 0
0405e91e
AB
585 {
586 I32 len = av_len(retparam)+1;
587 I32 i;
588 for(i = 0; i < len; i++) {
b4cb676b 589 sv_dump(SvRV(AvARRAY(retparam)[i]));
0405e91e
AB
590 }
591 }
b4cb676b 592#endif
1d784c90 593 PERL_THREAD_SETSPECIFIC(self_key,current_thread);
3275ba96 594 SvREFCNT_dec(clone_params.stashes);
e1c44605
AB
595 SvREFCNT_inc(retparam);
596 ptr_table_free(PL_ptr_table);
597 PL_ptr_table = NULL;
598
599 }
a446a88f 600 /* We have finished with it */
62375a60 601 thread->state |= PERL_ITHR_JOINED;
47ba8780 602 MUTEX_UNLOCK(&thread->mutex);
9684265f 603 sv_unmagic(SvRV(obj),PERL_MAGIC_shared_scalar);
e1c44605 604 return retparam;
68795e93 605 }
e1c44605 606 return (AV*)NULL;
47ba8780
AB
607}
608
68795e93 609void
68795e93
NIS
610Perl_ithread_DESTROY(pTHX_ SV *sv)
611{
612 ithread *thread = SV_to_ithread(aTHX_ sv);
68795e93
NIS
613 sv_unmagic(SvRV(sv),PERL_MAGIC_shared_scalar);
614}
8222d950 615
73e09c8f 616#endif /* USE_ITHREADS */
e1c44605 617
68795e93
NIS
618MODULE = threads PACKAGE = threads PREFIX = ithread_
619PROTOTYPES: DISABLE
8222d950 620
73e09c8f
JH
621#ifdef USE_ITHREADS
622
68795e93
NIS
623void
624ithread_new (classname, function_to_call, ...)
625char * classname
626SV * function_to_call
627CODE:
628{
629 AV* params = newAV();
630 if (items > 2) {
631 int i;
632 for(i = 2; i < items ; i++) {
95393226 633 av_push(params, SvREFCNT_inc(ST(i)));
68795e93
NIS
634 }
635 }
636 ST(0) = sv_2mortal(Perl_ithread_create(aTHX_ Nullsv, classname, function_to_call, newRV_noinc((SV*) params)));
637 XSRETURN(1);
638}
8222d950 639
68795e93 640void
678a9b6c
AB
641ithread_list(char *classname)
642PPCODE:
643{
644 ithread *curr_thread;
645 MUTEX_LOCK(&create_destruct_mutex);
646 curr_thread = threads;
5eb9fe8f
AB
647 if(curr_thread->tid != 0)
648 PUSHs( sv_2mortal(ithread_to_SV(aTHX_ NULL, curr_thread, classname, TRUE)));
678a9b6c 649 while(curr_thread) {
678a9b6c
AB
650 curr_thread = curr_thread->next;
651 if(curr_thread == threads)
652 break;
6794f985 653 if(curr_thread->state & PERL_ITHR_DETACHED ||
5eb9fe8f
AB
654 curr_thread->state & PERL_ITHR_JOINED)
655 continue;
656 PUSHs( sv_2mortal(ithread_to_SV(aTHX_ NULL, curr_thread, classname, TRUE)));
678a9b6c
AB
657 }
658 MUTEX_UNLOCK(&create_destruct_mutex);
659}
660
661
662void
68795e93
NIS
663ithread_self(char *classname)
664CODE:
665{
666 ST(0) = sv_2mortal(Perl_ithread_self(aTHX_ Nullsv,classname));
667 XSRETURN(1);
668}
47ba8780
AB
669
670int
68795e93 671ithread_tid(ithread *thread)
47ba8780
AB
672
673void
68795e93 674ithread_join(SV *obj)
e1c44605
AB
675PPCODE:
676{
677 AV* params = Perl_ithread_join(aTHX_ obj);
678 int i;
679 I32 len = AvFILL(params);
680 for (i = 0; i <= len; i++) {
1c3adb19
AB
681 SV* tmp = av_shift(params);
682 XPUSHs(tmp);
683 sv_2mortal(tmp);
e1c44605
AB
684 }
685 SvREFCNT_dec(params);
686}
687
f9dff5f5 688void
9d7debe1 689yield(...)
70f2e746
DM
690CODE:
691{
692 YIELD;
693}
694
47ba8780
AB
695
696void
68795e93 697ithread_detach(ithread *thread)
47ba8780 698
47ba8780 699void
68795e93
NIS
700ithread_DESTROY(SV *thread)
701
73e09c8f
JH
702#endif /* USE_ITHREADS */
703
68795e93
NIS
704BOOT:
705{
73e09c8f 706#ifdef USE_ITHREADS
68795e93 707 ithread* thread;
e1c44605 708 PL_perl_destruct_level = 2;
68795e93 709 PERL_THREAD_ALLOC_SPECIFIC(self_key);
58c2ef19
NIS
710 MUTEX_INIT(&create_destruct_mutex);
711 MUTEX_LOCK(&create_destruct_mutex);
62375a60 712 PL_threadhook = &Perl_ithread_hook;
68795e93
NIS
713 thread = PerlMemShared_malloc(sizeof(ithread));
714 Zero(thread,1,ithread);
715 PL_perl_destruct_level = 2;
716 MUTEX_INIT(&thread->mutex);
717 threads = thread;
718 thread->next = thread;
719 thread->prev = thread;
720 thread->interp = aTHX;
721 thread->count = 1; /* imortal */
722 thread->tid = tid_counter++;
62375a60 723 known_threads++;
58c2ef19 724 active_threads++;
62375a60 725 thread->state = 1;
68795e93
NIS
726#ifdef WIN32
727 thread->thr = GetCurrentThreadId();
728#else
729 thread->thr = pthread_self();
730#endif
62375a60 731
68795e93 732 PERL_THREAD_SETSPECIFIC(self_key,thread);
58c2ef19 733 MUTEX_UNLOCK(&create_destruct_mutex);
73e09c8f 734#endif /* USE_ITHREADS */
68795e93
NIS
735}
736