threads 1.46
[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"
4dcb9e53 5/* Workaround for XSUB.h bug under WIN32 */
6#ifdef WIN32
7# undef setjmp
c608f8c0 8# if !defined(__BORLANDC__)
9# define setjmp(x) _setjmp(x)
10# endif
4dcb9e53 11#endif
0f1612a7 12#ifdef HAS_PPPORT_H
404aaa48 13# define NEED_PL_signals
0f1612a7 14# define NEED_newRV_noinc
15# define NEED_sv_2pv_nolen
16# include "ppport.h"
17# include "threads.h"
18#endif
68795e93 19
73e09c8f 20#ifdef USE_ITHREADS
21
68795e93 22#ifdef WIN32
fc04eb16 23# include <windows.h>
514612b7 24 /* Supposed to be in Winbase.h */
25# ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
26# define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
27# endif
fc04eb16 28# include <win32thread.h>
68795e93 29#else
fc04eb16 30# ifdef OS2
5c728af0 31typedef perl_os_thread pthread_t;
fc04eb16 32# else
33# include <pthread.h>
34# endif
35# include <thread.h>
36# define PERL_THREAD_SETSPECIFIC(k,v) pthread_setspecific(k,v)
37# ifdef OLD_PTHREADS_API
38# define PERL_THREAD_DETACH(t) pthread_detach(&(t))
39# else
40# define PERL_THREAD_DETACH(t) pthread_detach((t))
41# endif
467f3f08 42#endif
d305c2c9 43#if !defined(HAS_GETPAGESIZE) && defined(I_SYS_PARAM)
44# include <sys/param.h>
45#endif
68795e93 46
62375a60 47/* Values for 'state' member */
69a9b4b8 48#define PERL_ITHR_JOINABLE 0
49#define PERL_ITHR_DETACHED 1
50#define PERL_ITHR_JOINED 2
51#define PERL_ITHR_FINISHED 4
52#define PERL_ITHR_THREAD_EXIT_ONLY 8
fc04eb16 53
54typedef struct _ithread {
55 struct _ithread *next; /* Next thread in the list */
56 struct _ithread *prev; /* Prev thread in the list */
57 PerlInterpreter *interp; /* The threads interpreter */
58 UV tid; /* Threads module's thread id */
59 perl_mutex mutex; /* Mutex for updating things in this struct */
9feacc09 60 int count; /* How many SVs have a reference to us */
fc04eb16 61 int state; /* Detached, joined, finished, etc. */
62 int gimme; /* Context of create */
63 SV *init_function; /* Code to run */
64 SV *params; /* Args to pass function */
68795e93 65#ifdef WIN32
fc04eb16 66 DWORD thr; /* OS's idea if thread id */
67 HANDLE handle; /* OS's waitable handle */
68795e93 68#else
fc04eb16 69 pthread_t thr; /* OS's handle for the thread */
68795e93 70#endif
514612b7 71 IV stack_size;
68795e93 72} ithread;
73
fc04eb16 74
5c6ff896 75#define MY_CXT_KEY "threads::_cxt" XS_VERSION
628ab322 76
77typedef struct {
861d5cbe 78 /* Used by Perl interpreter for thread context switching */
79 ithread *context;
628ab322 80} my_cxt_t;
81
82START_MY_CXT
83
68795e93 84
5c6ff896 85#define MY_POOL_KEY "threads::_pool" XS_VERSION
68795e93 86
5c6ff896 87typedef struct {
88 /* Structure for 'main' thread
89 * Also forms the 'base' for the doubly-linked list of threads */
90 ithread main_thread;
91
92 /* Protects the creation and destruction of threads*/
93 perl_mutex create_destruct_mutex;
94
95 UV tid_counter;
96 IV joinable_threads;
97 IV running_threads;
98 IV detached_threads;
99 IV default_stack_size;
100 IV page_size;
101} my_pool_t;
102
103#define dMY_POOL \
104 SV *my_pool_sv = *hv_fetch(PL_modglobal, MY_POOL_KEY, \
105 sizeof(MY_POOL_KEY)-1, TRUE); \
106 my_pool_t *my_poolp = INT2PTR(my_pool_t*, SvUV(my_pool_sv))
107
108#define MY_POOL (*my_poolp)
c05ae023 109
110
fc04eb16 111/* Used by Perl interpreter for thread context switching */
861d5cbe 112STATIC void
fc04eb16 113S_ithread_set(pTHX_ ithread *thread)
c05ae023 114{
628ab322 115 dMY_CXT;
861d5cbe 116 MY_CXT.context = thread;
c05ae023 117}
118
861d5cbe 119STATIC ithread *
fc04eb16 120S_ithread_get(pTHX)
121{
628ab322 122 dMY_CXT;
861d5cbe 123 return (MY_CXT.context);
c05ae023 124}
125
126
fc04eb16 127/* Free any data (such as the Perl interpreter) attached to an ithread
128 * structure. This is a bit like undef on SVs, where the SV isn't freed,
129 * but the PVX is. Must be called with thread->mutex already held.
2e676467 130 */
861d5cbe 131STATIC void
fc04eb16 132S_ithread_clear(pTHX_ ithread *thread)
2e676467 133{
134 PerlInterpreter *interp;
fc04eb16 135
ead32952 136 assert((thread->state & PERL_ITHR_FINISHED) &&
137 (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED)));
2e676467 138
139 interp = thread->interp;
140 if (interp) {
fc04eb16 141 dTHXa(interp);
142
143 PERL_SET_CONTEXT(interp);
144 S_ithread_set(aTHX_ thread);
f2cba68d 145
fc04eb16 146 SvREFCNT_dec(thread->params);
147 thread->params = Nullsv;
2e676467 148
fc04eb16 149 perl_destruct(interp);
9ca4d7fd 150 perl_free(interp);
fc04eb16 151 thread->interp = NULL;
2e676467 152 }
fc04eb16 153
2e676467 154 PERL_SET_CONTEXT(aTHX);
155}
156
68795e93 157
fc04eb16 158/* Free an ithread structure and any attached data if its count == 0 */
861d5cbe 159STATIC void
fc04eb16 160S_ithread_destruct(pTHX_ ithread *thread)
68795e93 161{
5c6ff896 162 dMY_POOL;
163
385d56e4 164#ifdef WIN32
fc04eb16 165 HANDLE handle;
385d56e4 166#endif
fea7688c 167 /* Return if thread is still being used */
fc04eb16 168 if (thread->count != 0) {
fc04eb16 169 return;
170 }
9feacc09 171
fc04eb16 172 /* Main thread (0) is immortal and should never get here */
173 assert(thread->tid != 0);
174
175 /* Remove from circular list of threads */
5c6ff896 176 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
fc04eb16 177 thread->next->prev = thread->prev;
178 thread->prev->next = thread->next;
179 thread->next = NULL;
180 thread->prev = NULL;
5c6ff896 181 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
c2f2a82b 182
fc04eb16 183 /* Thread is now disowned */
9ca4d7fd 184 MUTEX_LOCK(&thread->mutex);
fc04eb16 185 S_ithread_clear(aTHX_ thread);
385d56e4 186
187#ifdef WIN32
fc04eb16 188 handle = thread->handle;
189 thread->handle = NULL;
385d56e4 190#endif
fc04eb16 191 MUTEX_UNLOCK(&thread->mutex);
192 MUTEX_DESTROY(&thread->mutex);
385d56e4 193
c7667023 194#ifdef WIN32
fea7688c 195 if (handle) {
fc04eb16 196 CloseHandle(handle);
fea7688c 197 }
c7667023 198#endif
385d56e4 199
fc04eb16 200 /* Call PerlMemShared_free() in the context of the "first" interpreter
201 * per http://www.nntp.perl.org/group/perl.perl5.porters/110772
202 */
5c6ff896 203 aTHX = MY_POOL.main_thread.interp;
fc04eb16 204 PerlMemShared_free(thread);
68795e93 205}
206
fc04eb16 207
69a9b4b8 208/* Warn if exiting with any unjoined threads */
861d5cbe 209STATIC int
69a9b4b8 210S_exit_warning(pTHX)
62375a60 211{
5c6ff896 212 dMY_POOL;
213
60bd5ef6 214 int veto_cleanup;
69a9b4b8 215
5c6ff896 216 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
217 veto_cleanup = (MY_POOL.running_threads || MY_POOL.joinable_threads);
218 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
60bd5ef6 219
220 if (veto_cleanup) {
fc04eb16 221 if (ckWARN_d(WARN_THREADS)) {
4dcb9e53 222 Perl_warn(aTHX_ "Perl exited with active threads:\n\t%"
223 IVdf " running and unjoined\n\t%"
224 IVdf " finished and unjoined\n\t%"
225 IVdf " running and detached\n",
5c6ff896 226 MY_POOL.running_threads,
227 MY_POOL.joinable_threads,
228 MY_POOL.detached_threads);
fc04eb16 229 }
62375a60 230 }
69a9b4b8 231
fc04eb16 232 return (veto_cleanup);
62375a60 233}
234
69a9b4b8 235/* Called on exit from main thread */
236int
237Perl_ithread_hook(pTHX)
238{
5c6ff896 239 dMY_POOL;
240
241 int veto_cleanup = 0;
242
243 if (aTHX == MY_POOL.main_thread.interp) {
244 veto_cleanup = S_exit_warning(aTHX);
245 if (! veto_cleanup) {
246 MUTEX_DESTROY(&MY_POOL.create_destruct_mutex);
247 }
248 }
249
250 return (veto_cleanup);
69a9b4b8 251}
252
68795e93 253
254/* MAGIC (in mg.h sense) hooks */
255
256int
257ithread_mg_get(pTHX_ SV *sv, MAGIC *mg)
258{
fc04eb16 259 ithread *thread = (ithread *)mg->mg_ptr;
45977657 260 SvIV_set(sv, PTR2IV(thread));
68795e93 261 SvIOK_on(sv);
fc04eb16 262 return (0);
68795e93 263}
264
265int
266ithread_mg_free(pTHX_ SV *sv, MAGIC *mg)
267{
f2cba68d 268 ithread *thread = (ithread *)mg->mg_ptr;
269 int cleanup;
270
68795e93 271 MUTEX_LOCK(&thread->mutex);
f2cba68d 272 cleanup = ((--thread->count == 0) &&
273 (thread->state & PERL_ITHR_FINISHED) &&
274 (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED)));
275 MUTEX_UNLOCK(&thread->mutex);
276
fea7688c 277 if (cleanup) {
f2cba68d 278 S_ithread_destruct(aTHX_ thread);
fea7688c 279 }
fc04eb16 280 return (0);
68795e93 281}
282
283int
284ithread_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
285{
fc04eb16 286 ithread *thread = (ithread *)mg->mg_ptr;
68795e93 287 MUTEX_LOCK(&thread->mutex);
68795e93 288 thread->count++;
289 MUTEX_UNLOCK(&thread->mutex);
fc04eb16 290 return (0);
68795e93 291}
292
293MGVTBL ithread_vtbl = {
fc04eb16 294 ithread_mg_get, /* get */
295 0, /* set */
296 0, /* len */
297 0, /* clear */
298 ithread_mg_free, /* free */
299 0, /* copy */
300 ithread_mg_dup /* dup */
68795e93 301};
302
47ba8780 303
514612b7 304/* Provided default, minimum and rational stack sizes */
861d5cbe 305STATIC IV
306S_good_stack_size(pTHX_ IV stack_size)
514612b7 307{
5c6ff896 308 dMY_POOL;
309
514612b7 310 /* Use default stack size if no stack size specified */
fea7688c 311 if (! stack_size) {
5c6ff896 312 return (MY_POOL.default_stack_size);
fea7688c 313 }
514612b7 314
315#ifdef PTHREAD_STACK_MIN
316 /* Can't use less than minimum */
317 if (stack_size < PTHREAD_STACK_MIN) {
4dcb9e53 318 if (ckWARN(WARN_THREADS)) {
514612b7 319 Perl_warn(aTHX_ "Using minimum thread stack size of %" IVdf, (IV)PTHREAD_STACK_MIN);
320 }
321 return (PTHREAD_STACK_MIN);
322 }
323#endif
324
325 /* Round up to page size boundary */
5c6ff896 326 if (MY_POOL.page_size <= 0) {
d305c2c9 327#if defined(HAS_SYSCONF) && (defined(_SC_PAGESIZE) || defined(_SC_MMAP_PAGE_SIZE))
514612b7 328 SETERRNO(0, SS_NORMAL);
d305c2c9 329# ifdef _SC_PAGESIZE
5c6ff896 330 MY_POOL.page_size = sysconf(_SC_PAGESIZE);
d305c2c9 331# else
5c6ff896 332 MY_POOL.page_size = sysconf(_SC_MMAP_PAGE_SIZE);
d305c2c9 333# endif
5c6ff896 334 if ((long)MY_POOL.page_size < 0) {
514612b7 335 if (errno) {
336 SV * const error = get_sv("@", FALSE);
337 (void)SvUPGRADE(error, SVt_PV);
338 Perl_croak(aTHX_ "PANIC: sysconf: %s", SvPV_nolen(error));
339 } else {
340 Perl_croak(aTHX_ "PANIC: sysconf: pagesize unknown");
341 }
342 }
d305c2c9 343#else
344# ifdef HAS_GETPAGESIZE
5c6ff896 345 MY_POOL.page_size = getpagesize();
514612b7 346# else
d305c2c9 347# if defined(I_SYS_PARAM) && defined(PAGESIZE)
5c6ff896 348 MY_POOL.page_size = PAGESIZE;
d305c2c9 349# else
5c6ff896 350 MY_POOL.page_size = 8192; /* A conservative default */
d305c2c9 351# endif
514612b7 352# endif
5c6ff896 353 if (MY_POOL.page_size <= 0) {
354 Perl_croak(aTHX_ "PANIC: bad pagesize %" IVdf, (IV)MY_POOL.page_size);
fea7688c 355 }
514612b7 356#endif
357 }
5c6ff896 358 stack_size = ((stack_size + (MY_POOL.page_size - 1)) / MY_POOL.page_size) * MY_POOL.page_size;
514612b7 359
360 return (stack_size);
361}
362
363
fc04eb16 364/* Starts executing the thread.
365 * Passed as the C level function to run in the new thread.
b1edfb69 366 */
47ba8780 367#ifdef WIN32
861d5cbe 368STATIC THREAD_RET_TYPE
fc04eb16 369S_ithread_run(LPVOID arg)
47ba8780 370#else
861d5cbe 371STATIC void *
fc04eb16 372S_ithread_run(void * arg)
47ba8780 373#endif
fc04eb16 374{
375 ithread *thread = (ithread *)arg;
69a9b4b8 376 int jmp_rc = 0;
377 I32 oldscope;
378 int exit_app = 0;
379 int exit_code = 0;
fc04eb16 380 int cleanup;
f2cba68d 381
69a9b4b8 382 dJMPENV;
383
fc04eb16 384 dTHXa(thread->interp);
47ba8780 385
5c6ff896 386 dMY_POOL;
387
9ca4d7fd 388 /* Blocked until ->create() call finishes */
fc04eb16 389 MUTEX_LOCK(&thread->mutex);
fc04eb16 390 MUTEX_UNLOCK(&thread->mutex);
9ca4d7fd 391
392 PERL_SET_CONTEXT(thread->interp);
393 S_ithread_set(aTHX_ thread);
47ba8780 394
fc04eb16 395 PL_perl_destruct_level = 2;
f2cba68d 396
fc04eb16 397 {
398 AV *params = (AV *)SvRV(thread->params);
399 int len = (int)av_len(params)+1;
400 int ii;
401
402 dSP;
403 ENTER;
404 SAVETMPS;
405
406 /* Put args on the stack */
407 PUSHMARK(SP);
408 for (ii=0; ii < len; ii++) {
409 XPUSHs(av_shift(params));
410 }
411 PUTBACK;
412
4dcb9e53 413 oldscope = PL_scopestack_ix;
414 JMPENV_PUSH(jmp_rc);
415 if (jmp_rc == 0) {
416 /* Run the specified function */
417 len = (int)call_sv(thread->init_function, thread->gimme|G_EVAL);
418 } else if (jmp_rc == 2) {
69a9b4b8 419 /* Thread exited */
420 exit_app = 1;
421 exit_code = STATUS_CURRENT;
4dcb9e53 422 while (PL_scopestack_ix > oldscope) {
423 LEAVE;
424 }
425 }
426 JMPENV_POP;
fc04eb16 427
428 /* Remove args from stack and put back in params array */
429 SPAGAIN;
430 for (ii=len-1; ii >= 0; ii--) {
431 SV *sv = POPs;
4dcb9e53 432 if (jmp_rc == 0) {
433 av_store(params, ii, SvREFCNT_inc(sv));
434 }
fc04eb16 435 }
436
4dcb9e53 437 FREETMPS;
438 LEAVE;
439
fc04eb16 440 /* Check for failure */
441 if (SvTRUE(ERRSV) && ckWARN_d(WARN_THREADS)) {
4dcb9e53 442 oldscope = PL_scopestack_ix;
443 JMPENV_PUSH(jmp_rc);
444 if (jmp_rc == 0) {
69a9b4b8 445 /* Warn that thread died */
4dcb9e53 446 Perl_warn(aTHX_ "Thread %" UVuf " terminated abnormally: %" SVf, thread->tid, ERRSV);
447 } else if (jmp_rc == 2) {
69a9b4b8 448 /* Warn handler exited */
449 exit_app = 1;
450 exit_code = STATUS_CURRENT;
4dcb9e53 451 while (PL_scopestack_ix > oldscope) {
452 LEAVE;
453 }
454 }
455 JMPENV_POP;
fc04eb16 456 }
457
fc04eb16 458 /* Release function ref */
459 SvREFCNT_dec(thread->init_function);
460 thread->init_function = Nullsv;
461 }
62375a60 462
fc04eb16 463 PerlIO_flush((PerlIO *)NULL);
464
5c6ff896 465 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
fc04eb16 466 MUTEX_LOCK(&thread->mutex);
467 /* Mark as finished */
468 thread->state |= PERL_ITHR_FINISHED;
69a9b4b8 469 /* Clear exit flag if required */
fea7688c 470 if (thread->state & PERL_ITHR_THREAD_EXIT_ONLY) {
69a9b4b8 471 exit_app = 0;
fea7688c 472 }
fc04eb16 473 /* Cleanup if detached */
474 cleanup = (thread->state & PERL_ITHR_DETACHED);
475 MUTEX_UNLOCK(&thread->mutex);
476
69a9b4b8 477 /* Adjust thread status counts */
4dcb9e53 478 if (cleanup) {
5c6ff896 479 MY_POOL.detached_threads--;
4dcb9e53 480 } else {
5c6ff896 481 MY_POOL.running_threads--;
482 MY_POOL.joinable_threads++;
5168baf3 483 }
5c6ff896 484 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
69a9b4b8 485
486 /* Exit application if required */
487 if (exit_app) {
488 oldscope = PL_scopestack_ix;
489 JMPENV_PUSH(jmp_rc);
490 if (jmp_rc == 0) {
491 /* Warn if there are unjoined threads */
492 S_exit_warning(aTHX);
493 } else if (jmp_rc == 2) {
494 /* Warn handler exited */
495 exit_code = STATUS_CURRENT;
496 while (PL_scopestack_ix > oldscope) {
497 LEAVE;
498 }
499 }
500 JMPENV_POP;
501
502 my_exit(exit_code);
503 }
504
505 /* Clean up detached thread */
fea7688c 506 if (cleanup) {
69a9b4b8 507 S_ithread_destruct(aTHX_ thread);
fea7688c 508 }
91604d21 509
47ba8780 510#ifdef WIN32
fc04eb16 511 return ((DWORD)0);
e8f2bb9a 512#else
fc04eb16 513 return (0);
47ba8780 514#endif
68795e93 515}
516
fc04eb16 517
518/* Type conversion helper functions */
fea7688c 519
861d5cbe 520STATIC SV *
521S_ithread_to_SV(pTHX_ SV *obj, ithread *thread, char *classname, bool inc)
68795e93 522{
523 SV *sv;
524 MAGIC *mg;
fc04eb16 525
9ca4d7fd 526 /* If incrementing thread ref count, then call within mutex lock */
68795e93 527 if (inc) {
fc04eb16 528 MUTEX_LOCK(&thread->mutex);
529 thread->count++;
530 MUTEX_UNLOCK(&thread->mutex);
531 }
532
533 if (! obj) {
534 obj = newSV(0);
68795e93 535 }
fc04eb16 536
537 sv = newSVrv(obj, classname);
538 sv_setiv(sv, PTR2IV(thread));
539 mg = sv_magicext(sv, Nullsv, PERL_MAGIC_shared_scalar, &ithread_vtbl, (char *)thread, 0);
68795e93 540 mg->mg_flags |= MGf_DUP;
541 SvREADONLY_on(sv);
fc04eb16 542
543 return (obj);
68795e93 544}
47ba8780 545
861d5cbe 546STATIC ithread *
547S_SV_to_ithread(pTHX_ SV *sv)
68795e93 548{
fc04eb16 549 /* Argument is a thread */
550 if (SvROK(sv)) {
551 return (INT2PTR(ithread *, SvIV(SvRV(sv))));
552 }
553 /* Argument is classname, therefore return current thread */
554 return (S_ithread_get(aTHX));
47ba8780 555}
556
47ba8780 557
fc04eb16 558/* threads->create()
559 * Called in context of parent thread.
5c6ff896 560 * Called with MY_POOL.create_destruct_mutex locked. (Unlocked on error.)
fc04eb16 561 */
861d5cbe 562STATIC ithread *
fc04eb16 563S_ithread_create(
9ca4d7fd 564 pTHX_ SV *init_function,
514612b7 565 IV stack_size,
9d9ff5b1 566 int gimme,
69a9b4b8 567 int exit_opt,
fc04eb16 568 SV *params)
68795e93 569{
5c6ff896 570 dMY_POOL;
571
fc04eb16 572 ithread *thread;
573 CLONE_PARAMS clone_param;
574 ithread *current_thread = S_ithread_get(aTHX);
3b1c3273 575
fc04eb16 576 SV **tmps_tmp = PL_tmps_stack;
577 IV tmps_ix = PL_tmps_ix;
d94006e8 578#ifndef WIN32
fc04eb16 579 int rc_stack_size = 0;
580 int rc_thread_create = 0;
d94006e8 581#endif
3b1c3273 582
5c6ff896 583 /* Allocate thread structure in context of the main threads interpreter */
584 {
585 PERL_SET_CONTEXT(MY_POOL.main_thread.interp);
586 thread = (ithread *)PerlMemShared_malloc(sizeof(ithread));
587 }
588 PERL_SET_CONTEXT(aTHX);
fc04eb16 589 if (!thread) {
5c6ff896 590 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
fc04eb16 591 PerlLIO_write(PerlIO_fileno(Perl_error_log), PL_no_mem, strlen(PL_no_mem));
592 my_exit(1);
593 }
594 Zero(thread, 1, ithread);
595
596 /* Add to threads list */
5c6ff896 597 thread->next = &MY_POOL.main_thread;
598 thread->prev = MY_POOL.main_thread.prev;
599 MY_POOL.main_thread.prev = thread;
fc04eb16 600 thread->prev->next = thread;
c05ae023 601
fc04eb16 602 /* Set count to 1 immediately in case thread exits before
603 * we return to caller!
604 */
605 thread->count = 1;
606
9ca4d7fd 607 /* Block new thread until ->create() call finishes */
fc04eb16 608 MUTEX_INIT(&thread->mutex);
9ca4d7fd 609 MUTEX_LOCK(&thread->mutex);
610
5c6ff896 611 thread->tid = MY_POOL.tid_counter++;
861d5cbe 612 thread->stack_size = S_good_stack_size(aTHX_ stack_size);
9d9ff5b1 613 thread->gimme = gimme;
69a9b4b8 614 thread->state = exit_opt;
fc04eb16 615
616 /* "Clone" our interpreter into the thread's interpreter.
617 * This gives thread access to "static data" and code.
618 */
619 PerlIO_flush((PerlIO *)NULL);
620 S_ithread_set(aTHX_ thread);
621
622 SAVEBOOL(PL_srand_called); /* Save this so it becomes the correct value */
623 PL_srand_called = FALSE; /* Set it to false so we can detect if it gets
624 set during the clone */
3b1c3273 625
47ba8780 626#ifdef WIN32
fc04eb16 627 thread->interp = perl_clone(aTHX, CLONEf_KEEP_PTR_TABLE | CLONEf_CLONE_HOST);
47ba8780 628#else
fc04eb16 629 thread->interp = perl_clone(aTHX, CLONEf_KEEP_PTR_TABLE);
47ba8780 630#endif
47ba8780 631
fc04eb16 632 /* perl_clone() leaves us in new interpreter's context. As it is tricky
633 * to spot an implicit aTHX, create a new scope with aTHX matching the
634 * context for the duration of our work for new interpreter.
635 */
636 {
637 dTHXa(thread->interp);
638
639 MY_CXT_CLONE;
640
641 /* Here we remove END blocks since they should only run in the thread
642 * they are created
643 */
644 SvREFCNT_dec(PL_endav);
645 PL_endav = newAV();
404aaa48 646
f2e0bb91 647 if (SvPOK(init_function)) {
648 thread->init_function = newSV(0);
649 sv_copypv(thread->init_function, init_function);
650 } else {
651 clone_param.flags = 0;
652 thread->init_function = sv_dup(init_function, &clone_param);
653 if (SvREFCNT(thread->init_function) == 0) {
d4315dd6 654 SvREFCNT_inc_void(thread->init_function);
f2e0bb91 655 }
fc04eb16 656 }
657
658 thread->params = sv_dup(params, &clone_param);
d4315dd6 659 SvREFCNT_inc_void(thread->params);
fc04eb16 660
661 /* The code below checks that anything living on the tmps stack and
662 * has been cloned (so it lives in the ptr_table) has a refcount
663 * higher than 0.
664 *
665 * If the refcount is 0 it means that a something on the stack/context
666 * was holding a reference to it and since we init_stacks() in
667 * perl_clone that won't get cleaned and we will get a leaked scalar.
668 * The reason it was cloned was that it lived on the @_ stack.
669 *
670 * Example of this can be found in bugreport 15837 where calls in the
671 * parameter list end up as a temp.
672 *
673 * One could argue that this fix should be in perl_clone.
674 */
675 while (tmps_ix > 0) {
676 SV* sv = (SV*)ptr_table_fetch(PL_ptr_table, tmps_tmp[tmps_ix]);
677 tmps_ix--;
678 if (sv && SvREFCNT(sv) == 0) {
d4315dd6 679 SvREFCNT_inc_void(sv);
fc04eb16 680 SvREFCNT_dec(sv);
681 }
682 }
683
684 SvTEMP_off(thread->init_function);
685 ptr_table_free(PL_ptr_table);
686 PL_ptr_table = NULL;
687 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
688 }
689 S_ithread_set(aTHX_ current_thread);
690 PERL_SET_CONTEXT(aTHX);
691
692 /* Create/start the thread */
47ba8780 693#ifdef WIN32
fc04eb16 694 thread->handle = CreateThread(NULL,
514612b7 695 (DWORD)thread->stack_size,
fc04eb16 696 S_ithread_run,
697 (LPVOID)thread,
514612b7 698 STACK_SIZE_PARAM_IS_A_RESERVATION,
fc04eb16 699 &thread->thr);
82c40bf6 700#else
fc04eb16 701 {
861d5cbe 702 STATIC pthread_attr_t attr;
703 STATIC int attr_inited = 0;
704 STATIC int attr_joinable = PTHREAD_CREATE_JOINABLE;
fc04eb16 705 if (! attr_inited) {
706 pthread_attr_init(&attr);
707 attr_inited = 1;
708 }
709
fa26028c 710# ifdef PTHREAD_ATTR_SETDETACHSTATE
fc04eb16 711 /* Threads start out joinable */
712 PTHREAD_ATTR_SETDETACHSTATE(&attr, attr_joinable);
fa26028c 713# endif
fc04eb16 714
514612b7 715# ifdef _POSIX_THREAD_ATTR_STACKSIZE
fc04eb16 716 /* Set thread's stack size */
514612b7 717 if (thread->stack_size > 0) {
718 rc_stack_size = pthread_attr_setstacksize(&attr, (size_t)thread->stack_size);
719 }
3eb37d38 720# endif
721
fc04eb16 722 /* Create the thread */
723 if (! rc_stack_size) {
724# ifdef OLD_PTHREADS_API
725 rc_thread_create = pthread_create(&thread->thr,
726 attr,
727 S_ithread_run,
728 (void *)thread);
729# else
730# if defined(HAS_PTHREAD_ATTR_SETSCOPE) && defined(PTHREAD_SCOPE_SYSTEM)
731 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
732# endif
733 rc_thread_create = pthread_create(&thread->thr,
734 &attr,
735 S_ithread_run,
736 (void *)thread);
19a077f6 737# endif
fc04eb16 738 }
514612b7 739
740# ifdef _POSIX_THREAD_ATTR_STACKSIZE
741 /* Try to get thread's actual stack size */
742 {
743 size_t stacksize;
58a3a76c 744#ifdef HPUX1020
745 stacksize = pthread_attr_getstacksize(attr);
746#else
747 if (! pthread_attr_getstacksize(&attr, &stacksize))
748#endif
749 if (stacksize > 0) {
514612b7 750 thread->stack_size = (IV)stacksize;
751 }
514612b7 752 }
753# endif
fc04eb16 754 }
82c40bf6 755#endif
bcd9ca9b 756
fc04eb16 757 /* Check for errors */
d94006e8 758#ifdef WIN32
fc04eb16 759 if (thread->handle == NULL) {
d94006e8 760#else
fc04eb16 761 if (rc_stack_size || rc_thread_create) {
d94006e8 762#endif
9ca4d7fd 763 /* Must unlock mutex for destruct call */
5c6ff896 764 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
fc04eb16 765 sv_2mortal(params);
766 S_ithread_destruct(aTHX_ thread);
d94006e8 767#ifndef WIN32
514612b7 768 if (ckWARN_d(WARN_THREADS)) {
fea7688c 769 if (rc_stack_size) {
514612b7 770 Perl_warn(aTHX_ "Thread creation failed: pthread_attr_setstacksize(%" IVdf ") returned %d", thread->stack_size, rc_stack_size);
fea7688c 771 } else {
514612b7 772 Perl_warn(aTHX_ "Thread creation failed: pthread_create returned %d", rc_thread_create);
fea7688c 773 }
514612b7 774 }
d94006e8 775#endif
9ca4d7fd 776 return (NULL);
fc04eb16 777 }
778
5c6ff896 779 MY_POOL.running_threads++;
fc04eb16 780 sv_2mortal(params);
9ca4d7fd 781 return (thread);
68795e93 782}
47ba8780 783
73e09c8f 784#endif /* USE_ITHREADS */
e1c44605 785
fcea4b7c 786
fc04eb16 787MODULE = threads PACKAGE = threads PREFIX = ithread_
68795e93 788PROTOTYPES: DISABLE
8222d950 789
73e09c8f 790#ifdef USE_ITHREADS
791
68795e93 792void
f4cc38af 793ithread_create(...)
794 PREINIT:
795 char *classname;
514612b7 796 ithread *thread;
f4cc38af 797 SV *function_to_call;
798 AV *params;
514612b7 799 HV *specs;
800 IV stack_size;
9d9ff5b1 801 int context;
69a9b4b8 802 int exit_opt;
803 SV *thread_exit_only;
9d9ff5b1 804 char *str;
514612b7 805 int idx;
f4cc38af 806 int ii;
5c6ff896 807 dMY_POOL;
f4cc38af 808 CODE:
514612b7 809 if ((items >= 2) && SvROK(ST(1)) && SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
fea7688c 810 if (--items < 2) {
514612b7 811 Perl_croak(aTHX_ "Usage: threads->create(\\%specs, function, ...)");
fea7688c 812 }
514612b7 813 specs = (HV*)SvRV(ST(1));
814 idx = 1;
815 } else {
fea7688c 816 if (items < 2) {
514612b7 817 Perl_croak(aTHX_ "Usage: threads->create(function, ...)");
fea7688c 818 }
514612b7 819 specs = NULL;
820 idx = 0;
821 }
f4cc38af 822
514612b7 823 if (sv_isobject(ST(0))) {
824 /* $thr->create() */
825 classname = HvNAME(SvSTASH(SvRV(ST(0))));
826 thread = INT2PTR(ithread *, SvIV(SvRV(ST(0))));
827 stack_size = thread->stack_size;
69a9b4b8 828 exit_opt = thread->state & PERL_ITHR_THREAD_EXIT_ONLY;
514612b7 829 } else {
830 /* threads->create() */
831 classname = (char *)SvPV_nolen(ST(0));
5c6ff896 832 stack_size = MY_POOL.default_stack_size;
69a9b4b8 833 thread_exit_only = get_sv("threads::thread_exit_only", TRUE);
834 exit_opt = (SvTRUE(thread_exit_only))
835 ? PERL_ITHR_THREAD_EXIT_ONLY : 0;
514612b7 836 }
837
838 function_to_call = ST(idx+1);
839
9d9ff5b1 840 context = -1;
514612b7 841 if (specs) {
842 /* stack_size */
843 if (hv_exists(specs, "stack", 5)) {
844 stack_size = SvIV(*hv_fetch(specs, "stack", 5, 0));
845 } else if (hv_exists(specs, "stacksize", 9)) {
846 stack_size = SvIV(*hv_fetch(specs, "stacksize", 9, 0));
847 } else if (hv_exists(specs, "stack_size", 10)) {
848 stack_size = SvIV(*hv_fetch(specs, "stack_size", 10, 0));
849 }
9d9ff5b1 850
851 /* context */
852 if (hv_exists(specs, "context", 7)) {
853 str = (char *)SvPV_nolen(*hv_fetch(specs, "context", 7, 0));
854 switch (*str) {
855 case 'a':
856 case 'A':
857 context = G_ARRAY;
858 break;
859 case 's':
860 case 'S':
861 context = G_SCALAR;
862 break;
863 case 'v':
864 case 'V':
865 context = G_VOID;
866 break;
867 default:
868 Perl_croak(aTHX_ "Invalid context: %s", str);
869 }
870 } else if (hv_exists(specs, "array", 5)) {
871 if (SvTRUE(*hv_fetch(specs, "array", 5, 0))) {
872 context = G_ARRAY;
873 }
874 } else if (hv_exists(specs, "scalar", 6)) {
875 if (SvTRUE(*hv_fetch(specs, "scalar", 6, 0))) {
876 context = G_SCALAR;
877 }
878 } else if (hv_exists(specs, "void", 4)) {
879 if (SvTRUE(*hv_fetch(specs, "void", 4, 0))) {
880 context = G_VOID;
881 }
882 }
69a9b4b8 883
884 /* exit => thread_only */
885 if (hv_exists(specs, "exit", 4)) {
886 str = (char *)SvPV_nolen(*hv_fetch(specs, "exit", 4, 0));
887 exit_opt = (*str == 't' || *str == 'T')
888 ? PERL_ITHR_THREAD_EXIT_ONLY : 0;
889 }
9d9ff5b1 890 }
891 if (context == -1) {
892 context = GIMME_V; /* Implicit context */
893 } else {
894 context |= (GIMME_V & (~(G_ARRAY|G_SCALAR|G_VOID)));
514612b7 895 }
f4cc38af 896
897 /* Function args */
898 params = newAV();
899 if (items > 2) {
514612b7 900 for (ii=2; ii < items ; ii++) {
901 av_push(params, SvREFCNT_inc(ST(idx+ii)));
f4cc38af 902 }
903 }
904
905 /* Create thread */
5c6ff896 906 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
9ca4d7fd 907 thread = S_ithread_create(aTHX_ function_to_call,
908 stack_size,
909 context,
910 exit_opt,
911 newRV_noinc((SV*)params));
912 if (! thread) {
913 XSRETURN_UNDEF; /* Mutex already unlocked */
914 }
861d5cbe 915 ST(0) = sv_2mortal(S_ithread_to_SV(aTHX_ Nullsv, thread, classname, FALSE));
9ca4d7fd 916
917 /* Let thread run */
918 MUTEX_UNLOCK(&thread->mutex);
5c6ff896 919 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
9ca4d7fd 920
f4cc38af 921 /* XSRETURN(1); - implied */
922
8222d950 923
68795e93 924void
f4cc38af 925ithread_list(...)
926 PREINIT:
927 char *classname;
fc04eb16 928 ithread *thread;
f4cc38af 929 int list_context;
930 IV count = 0;
ead32952 931 int want_running;
5c6ff896 932 dMY_POOL;
f4cc38af 933 PPCODE:
934 /* Class method only */
fea7688c 935 if (SvROK(ST(0))) {
ead32952 936 Perl_croak(aTHX_ "Usage: threads->list(...)");
fea7688c 937 }
f4cc38af 938 classname = (char *)SvPV_nolen(ST(0));
939
940 /* Calling context */
941 list_context = (GIMME_V == G_ARRAY);
942
ead32952 943 /* Running or joinable parameter */
944 if (items > 1) {
945 want_running = SvTRUE(ST(1));
946 }
947
f4cc38af 948 /* Walk through threads list */
5c6ff896 949 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
950 for (thread = MY_POOL.main_thread.next;
951 thread != &MY_POOL.main_thread;
fc04eb16 952 thread = thread->next)
f4cc38af 953 {
954 /* Ignore detached or joined threads */
fc04eb16 955 if (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED)) {
f4cc38af 956 continue;
957 }
ead32952 958
959 /* Filter per parameter */
960 if (items > 1) {
961 if (want_running) {
962 if (thread->state & PERL_ITHR_FINISHED) {
963 continue; /* Not running */
964 }
965 } else {
966 if (! (thread->state & PERL_ITHR_FINISHED)) {
967 continue; /* Still running - not joinable yet */
968 }
969 }
970 }
971
f4cc38af 972 /* Push object on stack if list context */
973 if (list_context) {
861d5cbe 974 XPUSHs(sv_2mortal(S_ithread_to_SV(aTHX_ Nullsv, thread, classname, TRUE)));
f4cc38af 975 }
976 count++;
977 }
5c6ff896 978 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
f4cc38af 979 /* If scalar context, send back count */
980 if (! list_context) {
981 XSRETURN_IV(count);
982 }
678a9b6c 983
984
985void
f4cc38af 986ithread_self(...)
987 PREINIT:
988 char *classname;
fcea4b7c 989 ithread *thread;
f4cc38af 990 CODE:
991 /* Class method only */
fea7688c 992 if (SvROK(ST(0))) {
f4cc38af 993 Perl_croak(aTHX_ "Usage: threads->self()");
fea7688c 994 }
f4cc38af 995 classname = (char *)SvPV_nolen(ST(0));
996
fcea4b7c 997 thread = S_ithread_get(aTHX);
998
861d5cbe 999 ST(0) = sv_2mortal(S_ithread_to_SV(aTHX_ Nullsv, thread, classname, TRUE));
f4cc38af 1000 /* XSRETURN(1); - implied */
47ba8780 1001
47ba8780 1002
1003void
f4cc38af 1004ithread_tid(...)
1005 PREINIT:
1006 ithread *thread;
1007 CODE:
861d5cbe 1008 thread = S_SV_to_ithread(aTHX_ ST(0));
f4cc38af 1009 XST_mUV(0, thread->tid);
1010 /* XSRETURN(1); - implied */
1011
e1c44605 1012
f9dff5f5 1013void
f4cc38af 1014ithread_join(...)
1015 PREINIT:
fcea4b7c 1016 ithread *thread;
1017 int join_err;
f4cc38af 1018 AV *params;
1019 int len;
1020 int ii;
fcea4b7c 1021#ifdef WIN32
1022 DWORD waitcode;
1023#else
1024 void *retval;
1025#endif
5c6ff896 1026 dMY_POOL;
f4cc38af 1027 PPCODE:
1028 /* Object method only */
fea7688c 1029 if (! sv_isobject(ST(0))) {
f4cc38af 1030 Perl_croak(aTHX_ "Usage: $thr->join()");
fea7688c 1031 }
f4cc38af 1032
fcea4b7c 1033 /* Check if the thread is joinable */
861d5cbe 1034 thread = S_SV_to_ithread(aTHX_ ST(0));
fcea4b7c 1035 join_err = (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED));
fcea4b7c 1036 if (join_err) {
1037 if (join_err & PERL_ITHR_DETACHED) {
1038 Perl_croak(aTHX_ "Cannot join a detached thread");
1039 } else {
1040 Perl_croak(aTHX_ "Thread already joined");
1041 }
1042 }
1043
1044 /* Join the thread */
1045#ifdef WIN32
1046 waitcode = WaitForSingleObject(thread->handle, INFINITE);
1047#else
1048 pthread_join(thread->thr, &retval);
1049#endif
1050
1051 MUTEX_LOCK(&thread->mutex);
1052 /* Mark as joined */
1053 thread->state |= PERL_ITHR_JOINED;
1054
1055 /* Get the return value from the call_sv */
1056 {
1057 AV *params_copy;
1058 PerlInterpreter *other_perl;
1059 CLONE_PARAMS clone_params;
1060 ithread *current_thread;
1061
1062 params_copy = (AV *)SvRV(thread->params);
1063 other_perl = thread->interp;
1064 clone_params.stashes = newAV();
1065 clone_params.flags = CLONEf_JOIN_IN;
1066 PL_ptr_table = ptr_table_new();
1067 current_thread = S_ithread_get(aTHX);
1068 S_ithread_set(aTHX_ thread);
1069 /* Ensure 'meaningful' addresses retain their meaning */
1070 ptr_table_store(PL_ptr_table, &other_perl->Isv_undef, &PL_sv_undef);
1071 ptr_table_store(PL_ptr_table, &other_perl->Isv_no, &PL_sv_no);
1072 ptr_table_store(PL_ptr_table, &other_perl->Isv_yes, &PL_sv_yes);
1073 params = (AV *)sv_dup((SV*)params_copy, &clone_params);
1074 S_ithread_set(aTHX_ current_thread);
1075 SvREFCNT_dec(clone_params.stashes);
d4315dd6 1076 SvREFCNT_inc_void(params);
fcea4b7c 1077 ptr_table_free(PL_ptr_table);
1078 PL_ptr_table = NULL;
1079 }
1080
1081 /* We are finished with the thread */
1082 S_ithread_clear(aTHX_ thread);
1083 MUTEX_UNLOCK(&thread->mutex);
1084
5c6ff896 1085 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
9ca4d7fd 1086 if (! (thread->state & PERL_ITHR_DETACHED)) {
5c6ff896 1087 MY_POOL.joinable_threads--;
9ca4d7fd 1088 }
5c6ff896 1089 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
4dcb9e53 1090
fcea4b7c 1091 /* If no return values, then just return */
f4cc38af 1092 if (! params) {
1093 XSRETURN_UNDEF;
1094 }
1095
1096 /* Put return values on stack */
1097 len = (int)AvFILL(params);
1098 for (ii=0; ii <= len; ii++) {
1099 SV* param = av_shift(params);
1100 XPUSHs(sv_2mortal(param));
1101 }
1102
1103 /* Free return value array */
1104 SvREFCNT_dec(params);
1105
1106
1107void
1108ithread_yield(...)
1109 CODE:
1110 YIELD;
1111
1112
1113void
1114ithread_detach(...)
1115 PREINIT:
1116 ithread *thread;
fcea4b7c 1117 int detach_err;
1118 int cleanup;
5c6ff896 1119 dMY_POOL;
f4cc38af 1120 CODE:
fcea4b7c 1121 /* Check if the thread is detachable */
861d5cbe 1122 thread = S_SV_to_ithread(aTHX_ ST(0));
fcea4b7c 1123 if ((detach_err = (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED)))) {
fcea4b7c 1124 if (detach_err & PERL_ITHR_DETACHED) {
1125 Perl_croak(aTHX_ "Thread already detached");
1126 } else {
1127 Perl_croak(aTHX_ "Cannot detach a joined thread");
1128 }
1129 }
1130
1131 /* Detach the thread */
5c6ff896 1132 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
9ca4d7fd 1133 MUTEX_LOCK(&thread->mutex);
fcea4b7c 1134 thread->state |= PERL_ITHR_DETACHED;
1135#ifdef WIN32
1136 /* Windows has no 'detach thread' function */
1137#else
1138 PERL_THREAD_DETACH(thread->thr);
1139#endif
1140 /* Cleanup if finished */
1141 cleanup = (thread->state & PERL_ITHR_FINISHED);
1142 MUTEX_UNLOCK(&thread->mutex);
1143
4dcb9e53 1144 if (cleanup) {
5c6ff896 1145 MY_POOL.joinable_threads--;
4dcb9e53 1146 } else {
5c6ff896 1147 MY_POOL.running_threads--;
1148 MY_POOL.detached_threads++;
4dcb9e53 1149 }
5c6ff896 1150 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
4dcb9e53 1151
1152 if (cleanup) {
fcea4b7c 1153 S_ithread_destruct(aTHX_ thread);
4dcb9e53 1154 }
f4cc38af 1155
47ba8780 1156
1157void
c0003851 1158ithread_kill(...)
1159 PREINIT:
1160 ithread *thread;
1161 char *sig_name;
1162 IV signal;
1163 CODE:
1164 /* Must have safe signals */
fea7688c 1165 if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG) {
4dcb9e53 1166 Perl_croak(aTHX_ "Cannot signal threads without safe signals");
fea7688c 1167 }
c0003851 1168
1169 /* Object method only */
fea7688c 1170 if (! sv_isobject(ST(0))) {
c0003851 1171 Perl_croak(aTHX_ "Usage: $thr->kill('SIG...')");
fea7688c 1172 }
c0003851 1173
c0003851 1174 /* Get signal */
1175 sig_name = SvPV_nolen(ST(1));
1176 if (isALPHA(*sig_name)) {
fea7688c 1177 if (*sig_name == 'S' && sig_name[1] == 'I' && sig_name[2] == 'G') {
c0003851 1178 sig_name += 3;
fea7688c 1179 }
1180 if ((signal = whichsig(sig_name)) < 0) {
c0003851 1181 Perl_croak(aTHX_ "Unrecognized signal name: %s", sig_name);
fea7688c 1182 }
1183 } else {
c0003851 1184 signal = SvIV(ST(1));
fea7688c 1185 }
c0003851 1186
1187 /* Set the signal for the thread */
861d5cbe 1188 thread = S_SV_to_ithread(aTHX_ ST(0));
4dcb9e53 1189 MUTEX_LOCK(&thread->mutex);
3ceb02cd 1190 if (thread->interp) {
c0003851 1191 dTHXa(thread->interp);
1192 PL_psig_pend[signal]++;
1193 PL_sig_pending = 1;
1194 }
4dcb9e53 1195 MUTEX_UNLOCK(&thread->mutex);
c0003851 1196
1197 /* Return the thread to allow for method chaining */
1198 ST(0) = ST(0);
1199 /* XSRETURN(1); - implied */
1200
1201
1202void
f4cc38af 1203ithread_DESTROY(...)
1204 CODE:
fcea4b7c 1205 sv_unmagic(SvRV(ST(0)), PERL_MAGIC_shared_scalar);
f4cc38af 1206
1207
1208void
1209ithread_equal(...)
fc04eb16 1210 PREINIT:
1211 int are_equal = 0;
f4cc38af 1212 CODE:
fc04eb16 1213 /* Compares TIDs to determine thread equality */
f4cc38af 1214 if (sv_isobject(ST(0)) && sv_isobject(ST(1))) {
1215 ithread *thr1 = INT2PTR(ithread *, SvIV(SvRV(ST(0))));
1216 ithread *thr2 = INT2PTR(ithread *, SvIV(SvRV(ST(1))));
fc04eb16 1217 are_equal = (thr1->tid == thr2->tid);
1218 }
1219 if (are_equal) {
1220 XST_mYES(0);
f4cc38af 1221 } else {
fc04eb16 1222 /* Return 0 on false for backward compatibility */
f4cc38af 1223 XST_mIV(0, 0);
1224 }
1225 /* XSRETURN(1); - implied */
1226
47ba8780 1227
47ba8780 1228void
f4cc38af 1229ithread_object(...)
1230 PREINIT:
1231 char *classname;
1232 UV tid;
fc04eb16 1233 ithread *thread;
9ca4d7fd 1234 int have_obj = 0;
5c6ff896 1235 dMY_POOL;
f4cc38af 1236 CODE:
1237 /* Class method only */
fea7688c 1238 if (SvROK(ST(0))) {
f4cc38af 1239 Perl_croak(aTHX_ "Usage: threads->object($tid)");
fea7688c 1240 }
f4cc38af 1241 classname = (char *)SvPV_nolen(ST(0));
1242
1243 if ((items < 2) || ! SvOK(ST(1))) {
1244 XSRETURN_UNDEF;
1245 }
1246
fc04eb16 1247 /* threads->object($tid) */
f4cc38af 1248 tid = SvUV(ST(1));
1249
1250 /* Walk through threads list */
5c6ff896 1251 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
1252 for (thread = MY_POOL.main_thread.next;
1253 thread != &MY_POOL.main_thread;
fc04eb16 1254 thread = thread->next)
f4cc38af 1255 {
9ca4d7fd 1256 /* Look for TID */
1257 if (thread->tid == tid) {
1258 /* Ignore if detached or joined */
1259 if (! (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED))) {
1260 /* Put object on stack */
861d5cbe 1261 ST(0) = sv_2mortal(S_ithread_to_SV(aTHX_ Nullsv, thread, classname, TRUE));
9ca4d7fd 1262 have_obj = 1;
1263 }
1264 break;
f4cc38af 1265 }
f4cc38af 1266 }
5c6ff896 1267 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
9ca4d7fd 1268
1269 if (! have_obj) {
f4cc38af 1270 XSRETURN_UNDEF;
1271 }
1272 /* XSRETURN(1); - implied */
1273
1274
1275void
1276ithread__handle(...);
1277 PREINIT:
1278 ithread *thread;
1279 CODE:
861d5cbe 1280 thread = S_SV_to_ithread(aTHX_ ST(0));
f4cc38af 1281#ifdef WIN32
fcea4b7c 1282 XST_mUV(0, PTR2UV(&thread->handle));
f4cc38af 1283#else
75ba4ae2 1284 XST_mUV(0, PTR2UV(&thread->thr));
f4cc38af 1285#endif
1286 /* XSRETURN(1); - implied */
68795e93 1287
514612b7 1288
1289void
1290ithread_get_stack_size(...)
1291 PREINIT:
1292 IV stack_size;
5c6ff896 1293 dMY_POOL;
514612b7 1294 CODE:
1295 if (sv_isobject(ST(0))) {
1296 /* $thr->get_stack_size() */
1297 ithread *thread = INT2PTR(ithread *, SvIV(SvRV(ST(0))));
1298 stack_size = thread->stack_size;
1299 } else {
1300 /* threads->get_stack_size() */
5c6ff896 1301 stack_size = MY_POOL.default_stack_size;
514612b7 1302 }
1303 XST_mIV(0, stack_size);
1304 /* XSRETURN(1); - implied */
1305
1306
1307void
1308ithread_set_stack_size(...)
1309 PREINIT:
1310 IV old_size;
5c6ff896 1311 dMY_POOL;
514612b7 1312 CODE:
fea7688c 1313 if (items != 2) {
514612b7 1314 Perl_croak(aTHX_ "Usage: threads->set_stack_size($size)");
fea7688c 1315 }
1316 if (sv_isobject(ST(0))) {
514612b7 1317 Perl_croak(aTHX_ "Cannot change stack size of an existing thread");
fea7688c 1318 }
514612b7 1319
5c6ff896 1320 old_size = MY_POOL.default_stack_size;
1321 MY_POOL.default_stack_size = S_good_stack_size(aTHX_ SvIV(ST(1)));
514612b7 1322 XST_mIV(0, old_size);
1323 /* XSRETURN(1); - implied */
1324
ead32952 1325
1326void
1327ithread_is_running(...)
1328 PREINIT:
1329 ithread *thread;
1330 CODE:
1331 /* Object method only */
fea7688c 1332 if (! sv_isobject(ST(0))) {
ead32952 1333 Perl_croak(aTHX_ "Usage: $thr->is_running()");
fea7688c 1334 }
ead32952 1335
1336 thread = INT2PTR(ithread *, SvIV(SvRV(ST(0))));
ead32952 1337 ST(0) = (thread->state & PERL_ITHR_FINISHED) ? &PL_sv_no : &PL_sv_yes;
ead32952 1338 /* XSRETURN(1); - implied */
1339
1340
1341void
1342ithread_is_detached(...)
1343 PREINIT:
1344 ithread *thread;
1345 CODE:
861d5cbe 1346 thread = S_SV_to_ithread(aTHX_ ST(0));
ead32952 1347 ST(0) = (thread->state & PERL_ITHR_DETACHED) ? &PL_sv_yes : &PL_sv_no;
ead32952 1348 /* XSRETURN(1); - implied */
1349
1350
1351void
1352ithread_is_joinable(...)
1353 PREINIT:
1354 ithread *thread;
1355 CODE:
1356 /* Object method only */
fea7688c 1357 if (! sv_isobject(ST(0))) {
ead32952 1358 Perl_croak(aTHX_ "Usage: $thr->is_joinable()");
fea7688c 1359 }
ead32952 1360
1361 thread = INT2PTR(ithread *, SvIV(SvRV(ST(0))));
1362 MUTEX_LOCK(&thread->mutex);
1363 ST(0) = ((thread->state & PERL_ITHR_FINISHED) &&
1364 ! (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED)))
1365 ? &PL_sv_yes : &PL_sv_no;
1366 MUTEX_UNLOCK(&thread->mutex);
1367 /* XSRETURN(1); - implied */
1368
1369
1370void
1371ithread_wantarray(...)
1372 PREINIT:
1373 ithread *thread;
1374 CODE:
861d5cbe 1375 thread = S_SV_to_ithread(aTHX_ ST(0));
ead32952 1376 ST(0) = (thread->gimme & G_ARRAY) ? &PL_sv_yes :
1377 (thread->gimme & G_VOID) ? &PL_sv_undef
1378 /* G_SCALAR */ : &PL_sv_no;
ead32952 1379 /* XSRETURN(1); - implied */
1380
69a9b4b8 1381
1382void
1383ithread_set_thread_exit_only(...)
1384 PREINIT:
1385 ithread *thread;
1386 CODE:
fea7688c 1387 if (items != 2) {
69a9b4b8 1388 Perl_croak(aTHX_ "Usage: ->set_thread_exit_only(boolean)");
fea7688c 1389 }
861d5cbe 1390 thread = S_SV_to_ithread(aTHX_ ST(0));
69a9b4b8 1391 MUTEX_LOCK(&thread->mutex);
1392 if (SvTRUE(ST(1))) {
1393 thread->state |= PERL_ITHR_THREAD_EXIT_ONLY;
1394 } else {
1395 thread->state &= ~PERL_ITHR_THREAD_EXIT_ONLY;
1396 }
1397 MUTEX_UNLOCK(&thread->mutex);
1398
73e09c8f 1399#endif /* USE_ITHREADS */
1400
fc04eb16 1401
68795e93 1402BOOT:
1403{
73e09c8f 1404#ifdef USE_ITHREADS
5c6ff896 1405 SV *my_pool_sv = *hv_fetch(PL_modglobal, MY_POOL_KEY,
1406 sizeof(MY_POOL_KEY)-1, TRUE);
1407 my_pool_t *my_poolp = (my_pool_t*)SvPVX(newSV(sizeof(my_pool_t)-1));
1408
fc04eb16 1409 MY_CXT_INIT;
1410
5c6ff896 1411 Zero(my_poolp, 1, my_pool_t);
1412 sv_setuv(my_pool_sv, PTR2UV(my_poolp));
1413
fc04eb16 1414 PL_perl_destruct_level = 2;
5c6ff896 1415 MUTEX_INIT(&MY_POOL.create_destruct_mutex);
1416 MUTEX_LOCK(&MY_POOL.create_destruct_mutex);
fc04eb16 1417
1418 PL_threadhook = &Perl_ithread_hook;
1419
5c6ff896 1420 MY_POOL.tid_counter = 1;
1421# ifdef THREAD_CREATE_NEEDS_STACK
1422 MY_POOL.default_stack_size = THREAD_CREATE_NEEDS_STACK;
1423# endif
1424
c372d929 1425 /* The 'main' thread is thread 0.
1426 * It is detached (unjoinable) and immortal.
1427 */
fc04eb16 1428
5c6ff896 1429 MUTEX_INIT(&MY_POOL.main_thread.mutex);
fc04eb16 1430
1431 /* Head of the threads list */
5c6ff896 1432 MY_POOL.main_thread.next = &MY_POOL.main_thread;
1433 MY_POOL.main_thread.prev = &MY_POOL.main_thread;
fc04eb16 1434
5c6ff896 1435 MY_POOL.main_thread.count = 1; /* Immortal */
fc04eb16 1436
5c6ff896 1437 MY_POOL.main_thread.interp = aTHX;
1438 MY_POOL.main_thread.state = PERL_ITHR_DETACHED; /* Detached */
1439 MY_POOL.main_thread.stack_size = MY_POOL.default_stack_size;
fc04eb16 1440# ifdef WIN32
5c6ff896 1441 MY_POOL.main_thread.thr = GetCurrentThreadId();
fc04eb16 1442# else
5c6ff896 1443 MY_POOL.main_thread.thr = pthread_self();
fc04eb16 1444# endif
1445
5c6ff896 1446 S_ithread_set(aTHX_ &MY_POOL.main_thread);
1447 MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
73e09c8f 1448#endif /* USE_ITHREADS */
68795e93 1449}