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