ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/staticperl/perl/ext/Thread/Thread.xs
Revision: 1.1
Committed: Thu Jun 30 14:27:05 2005 UTC (21 years, 3 months ago) by root
Branch: MAIN
CVS Tags: PERL-5-8-7, HEAD
Branch point for: PERL
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #define PERL_NO_GET_CONTEXT
2     #include "EXTERN.h"
3     #include "perl.h"
4     #include "XSUB.h"
5    
6     /* Magic signature for Thread's mg_private is "Th" */
7     #define Thread_MAGIC_SIGNATURE 0x5468
8    
9     #ifdef __cplusplus
10     #ifdef I_UNISTD
11     #include <unistd.h>
12     #endif
13     #endif
14     #include <fcntl.h>
15    
16     static int sig_pipe[2];
17    
18     #ifndef THREAD_RET_TYPE
19     #define THREAD_RET_TYPE void *
20     #define THREAD_RET_CAST(x) ((THREAD_RET_TYPE) x)
21     #endif
22    
23     static void
24     remove_thread(pTHX_ Thread t)
25     {
26     #ifdef USE_5005THREADS
27     DEBUG_S(WITH_THR(PerlIO_printf(Perl_debug_log,
28     "%p: remove_thread %p\n", thr, t)));
29     MUTEX_LOCK(&PL_threads_mutex);
30     MUTEX_DESTROY(&t->mutex);
31     PL_nthreads--;
32     t->prev->next = t->next;
33     t->next->prev = t->prev;
34     SvREFCNT_dec(t->oursv);
35     COND_BROADCAST(&PL_nthreads_cond);
36     MUTEX_UNLOCK(&PL_threads_mutex);
37     #endif
38     }
39    
40     static THREAD_RET_TYPE
41     threadstart(void *arg)
42     {
43     #ifdef USE_5005THREADS
44     #ifdef FAKE_THREADS
45     Thread savethread = thr;
46     LOGOP myop;
47     dSP;
48     I32 oldscope = PL_scopestack_ix;
49     I32 retval;
50     AV *av;
51     int i;
52    
53     DEBUG_S(PerlIO_printf(Perl_debug_log, "new thread %p starting at %s\n",
54     thr, SvPEEK(TOPs)));
55     thr = (Thread) arg;
56     savemark = TOPMARK;
57     thr->prev = thr->prev_run = savethread;
58     thr->next = savethread->next;
59     thr->next_run = savethread->next_run;
60     savethread->next = savethread->next_run = thr;
61     thr->wait_queue = 0;
62     thr->private = 0;
63    
64     /* Now duplicate most of perl_call_sv but with a few twists */
65     PL_op = (OP*)&myop;
66     Zero(PL_op, 1, LOGOP);
67     myop.op_flags = OPf_STACKED;
68     myop.op_next = Nullop;
69     myop.op_flags |= OPf_KNOW;
70     myop.op_flags |= OPf_WANT_LIST;
71     PL_op = pp_entersub(ARGS);
72     DEBUG_S(if (!PL_op)
73     PerlIO_printf(Perl_debug_log, "thread starts at Nullop\n"));
74     /*
75     * When this thread is next scheduled, we start in the right
76     * place. When the thread runs off the end of the sub, perl.c
77     * handles things, using savemark to figure out how much of the
78     * stack is the return value for any join.
79     */
80     thr = savethread; /* back to the old thread */
81     return 0;
82     #else
83     Thread thr = (Thread) arg;
84     dSP;
85     I32 oldmark = TOPMARK;
86     I32 retval;
87     SV *sv;
88     AV *av;
89     int i;
90    
91     #if defined(MULTIPLICITY)
92     PERL_SET_INTERP(thr->interp);
93     #endif
94    
95     DEBUG_S(PerlIO_printf(Perl_debug_log, "new thread %p waiting to start\n",
96     thr));
97    
98     /*
99     * Wait until our creator releases us. If we didn't do this, then
100     * it would be potentially possible for out thread to carry on and
101     * do stuff before our creator fills in our "self" field. For example,
102     * if we went and created another thread which tried to JOIN with us,
103     * then we'd be in a mess.
104     */
105     MUTEX_LOCK(&thr->mutex);
106     MUTEX_UNLOCK(&thr->mutex);
107    
108     /*
109     * It's safe to wait until now to set the thread-specific pointer
110     * from our pthread_t structure to our struct perl_thread, since
111     * we're the only thread who can get at it anyway.
112     */
113     PERL_SET_THX(thr);
114    
115     DEBUG_S(PerlIO_printf(Perl_debug_log, "new thread %p starting at %s\n",
116     thr, SvPEEK(TOPs)));
117    
118     av = newAV();
119     sv = POPs;
120     PUTBACK;
121     ENTER;
122     SAVETMPS;
123     perl_call_sv(sv, G_ARRAY|G_EVAL);
124     SPAGAIN;
125     retval = SP - (PL_stack_base + oldmark);
126     SP = PL_stack_base + oldmark + 1;
127     if (SvCUR(thr->errsv)) {
128     MUTEX_LOCK(&thr->mutex);
129     thr->flags |= THRf_DID_DIE;
130     MUTEX_UNLOCK(&thr->mutex);
131     av_store(av, 0, &PL_sv_no);
132     av_store(av, 1, newSVsv(thr->errsv));
133     DEBUG_S(PerlIO_printf(Perl_debug_log, "%p died: %s\n",
134     thr, SvPV(thr->errsv, PL_na)));
135     }
136     else {
137     DEBUG_S(STMT_START {
138     for (i = 1; i <= retval; i++) {
139     PerlIO_printf(Perl_debug_log, "%p return[%d] = %s\n",
140     thr, i, SvPEEK(SP[i - 1]));
141     }
142     } STMT_END);
143     av_store(av, 0, &PL_sv_yes);
144     for (i = 1; i <= retval; i++, SP++)
145     sv_setsv(*av_fetch(av, i, TRUE), SvREFCNT_inc(*SP));
146     }
147     FREETMPS;
148     LEAVE;
149    
150     #if 0
151     /* removed for debug */
152     SvREFCNT_dec(PL_curstack);
153     #endif
154     SvREFCNT_dec(thr->cvcache);
155     SvREFCNT_dec(thr->threadsv);
156     SvREFCNT_dec(thr->specific);
157     SvREFCNT_dec(thr->errsv);
158    
159     /*Safefree(cxstack);*/
160     while (PL_curstackinfo->si_next)
161     PL_curstackinfo = PL_curstackinfo->si_next;
162     while (PL_curstackinfo) {
163     PERL_SI *p = PL_curstackinfo->si_prev;
164     SvREFCNT_dec(PL_curstackinfo->si_stack);
165     Safefree(PL_curstackinfo->si_cxstack);
166     Safefree(PL_curstackinfo);
167     PL_curstackinfo = p;
168     }
169     Safefree(PL_markstack);
170     Safefree(PL_scopestack);
171     Safefree(PL_savestack);
172     Safefree(PL_retstack);
173     Safefree(PL_tmps_stack);
174     SvREFCNT_dec(PL_ofs_sv);
175    
176     SvREFCNT_dec(PL_rs);
177     SvREFCNT_dec(PL_statname);
178     SvREFCNT_dec(PL_errors);
179     Safefree(PL_screamfirst);
180     Safefree(PL_screamnext);
181     Safefree(PL_reg_start_tmp);
182     SvREFCNT_dec(PL_lastscream);
183     SvREFCNT_dec(PL_defoutgv);
184     Safefree(PL_reg_poscache);
185    
186     MUTEX_LOCK(&thr->mutex);
187     thr->thr_done = 1;
188     DEBUG_S(PerlIO_printf(Perl_debug_log,
189     "%p: threadstart finishing: state is %u\n",
190     thr, ThrSTATE(thr)));
191     switch (ThrSTATE(thr)) {
192     case THRf_R_JOINABLE:
193     ThrSETSTATE(thr, THRf_ZOMBIE);
194     MUTEX_UNLOCK(&thr->mutex);
195     DEBUG_S(PerlIO_printf(Perl_debug_log,
196     "%p: R_JOINABLE thread finished\n", thr));
197     break;
198     case THRf_R_JOINED:
199     ThrSETSTATE(thr, THRf_DEAD);
200     MUTEX_UNLOCK(&thr->mutex);
201     remove_thread(aTHX_ thr);
202     DEBUG_S(PerlIO_printf(Perl_debug_log,
203     "%p: R_JOINED thread finished\n", thr));
204     break;
205     case THRf_R_DETACHED:
206     ThrSETSTATE(thr, THRf_DEAD);
207     MUTEX_UNLOCK(&thr->mutex);
208     SvREFCNT_dec(av);
209     DEBUG_S(PerlIO_printf(Perl_debug_log,
210     "%p: DETACHED thread finished\n", thr));
211     remove_thread(aTHX_ thr); /* This might trigger main thread to finish */
212     break;
213     default:
214     MUTEX_UNLOCK(&thr->mutex);
215     croak("panic: illegal state %u at end of threadstart", ThrSTATE(thr));
216     /* NOTREACHED */
217     }
218     return THREAD_RET_CAST(av); /* Available for anyone to join with */
219     /* us unless we're detached, in which */
220     /* case noone sees the value anyway. */
221     #endif
222     #else
223     return THREAD_RET_CAST(NULL);
224     #endif
225     }
226    
227     static SV *
228     newthread (pTHX_ SV *startsv, AV *initargs, char *classname)
229     {
230     #ifdef USE_5005THREADS
231     dSP;
232     Thread savethread;
233     int i;
234     SV *sv;
235     int err;
236     #ifndef THREAD_CREATE
237     static pthread_attr_t attr;
238     static int attr_inited = 0;
239     sigset_t fullmask, oldmask;
240     static int attr_joinable = PTHREAD_CREATE_JOINABLE;
241     #endif
242    
243     if (ckWARN(WARN_DEPRECATED))
244     Perl_warner(aTHX_ packWARN(WARN_DEPRECATED),
245     "5.005 threads are deprecated");
246     savethread = thr;
247     thr = new_struct_thread(thr);
248     /* temporarily pretend to be the child thread in case the
249     * XPUSHs() below want to grow the child's stack. This is
250     * safe, since the other thread is not yet created, and we
251     * are the only ones who know about it */
252     PERL_SET_THX(thr);
253     SPAGAIN;
254     DEBUG_S(PerlIO_printf(Perl_debug_log,
255     "%p: newthread (%p), tid is %u, preparing stack\n",
256     savethread, thr, thr->tid));
257     /* The following pushes the arg list and startsv onto the *new* stack */
258     PUSHMARK(SP);
259     /* Could easily speed up the following greatly */
260     for (i = 0; i <= AvFILL(initargs); i++)
261     XPUSHs(SvREFCNT_inc(*av_fetch(initargs, i, FALSE)));
262     XPUSHs(SvREFCNT_inc(startsv));
263     PUTBACK;
264    
265     /* On your marks... */
266     PERL_SET_THX(savethread);
267     MUTEX_LOCK(&thr->mutex);
268    
269     #ifdef THREAD_CREATE
270     err = THREAD_CREATE(thr, threadstart);
271     #else
272     /* Get set... */
273     sigfillset(&fullmask);
274     if (sigprocmask(SIG_SETMASK, &fullmask, &oldmask) == -1)
275     croak("panic: sigprocmask");
276     err = 0;
277     if (!attr_inited) {
278     attr_inited = 1;
279     err = pthread_attr_init(&attr);
280     # ifdef THREAD_CREATE_NEEDS_STACK
281     if (err == 0)
282     err = pthread_attr_setstacksize(&attr, THREAD_CREATE_NEEDS_STACK);
283     if (err)
284     croak("panic: pthread_attr_setstacksize failed");
285     # endif
286     # ifdef PTHREAD_ATTR_SETDETACHSTATE
287     if (err == 0)
288     err = PTHREAD_ATTR_SETDETACHSTATE(&attr, attr_joinable);
289     if (err)
290     croak("panic: pthread_attr_setdetachstate failed");
291     # else
292     croak("panic: can't pthread_attr_setdetachstate");
293     # endif
294     }
295     if (err == 0)
296     err = PTHREAD_CREATE(&thr->self, attr, threadstart, (void*) thr);
297     #endif
298    
299     if (err) {
300     MUTEX_UNLOCK(&thr->mutex);
301     DEBUG_S(PerlIO_printf(Perl_debug_log,
302     "%p: create of %p failed %d\n",
303     savethread, thr, err));
304     /* Thread creation failed--clean up */
305     SvREFCNT_dec(thr->cvcache);
306     remove_thread(aTHX_ thr);
307     for (i = 0; i <= AvFILL(initargs); i++)
308     SvREFCNT_dec(*av_fetch(initargs, i, FALSE));
309     SvREFCNT_dec(startsv);
310     return NULL;
311     }
312    
313     #ifdef THREAD_POST_CREATE
314     THREAD_POST_CREATE(thr);
315     #else
316     if (sigprocmask(SIG_SETMASK, &oldmask, 0))
317     croak("panic: sigprocmask");
318     #endif
319    
320     sv = newSViv(thr->tid);
321     sv_magic(sv, thr->oursv, '~', 0, 0);
322     SvMAGIC(sv)->mg_private = Thread_MAGIC_SIGNATURE;
323     sv = sv_bless(newRV_noinc(sv), gv_stashpv(classname, TRUE));
324    
325     /* Go */
326     MUTEX_UNLOCK(&thr->mutex);
327    
328     return sv;
329     #else
330     # ifdef USE_ITHREADS
331     croak("This perl was built for \"ithreads\", which currently does not support Thread.pm.\n"
332     "Run \"perldoc Thread\" for more information");
333     # else
334     croak("This perl was not built with support for 5.005-style threads.\n"
335     "Run \"perldoc Thread\" for more information");
336     # endif
337     return &PL_sv_undef;
338     #endif
339     }
340    
341     static Signal_t handle_thread_signal (int sig);
342    
343     static Signal_t
344     handle_thread_signal(int sig)
345     {
346     unsigned char c = (unsigned char) sig;
347     dTHX;
348     /*
349     * We're not really allowed to call fprintf in a signal handler
350     * so don't be surprised if this isn't robust while debugging
351     * with -DL.
352     */
353     DEBUG_S(PerlIO_printf(Perl_debug_log,
354     "handle_thread_signal: got signal %d\n", sig));
355     write(sig_pipe[1], &c, 1);
356     }
357    
358     MODULE = Thread PACKAGE = Thread
359     PROTOTYPES: DISABLE
360    
361     void
362     new(classname, startsv, ...)
363     char * classname
364     SV * startsv
365     AV * av = av_make(items - 2, &ST(2));
366     PPCODE:
367     XPUSHs(sv_2mortal(newthread(aTHX_ startsv, av, classname)));
368    
369     void
370     join(t)
371     Thread t
372     PREINIT:
373     #ifdef USE_5005THREADS
374     AV * av;
375     int i;
376     #endif
377     PPCODE:
378     #ifdef USE_5005THREADS
379     if (t == thr)
380     croak("Attempt to join self");
381     DEBUG_S(PerlIO_printf(Perl_debug_log, "%p: joining %p (state %u)\n",
382     thr, t, ThrSTATE(t)));
383     MUTEX_LOCK(&t->mutex);
384     switch (ThrSTATE(t)) {
385     case THRf_R_JOINABLE:
386     case THRf_R_JOINED:
387     ThrSETSTATE(t, THRf_R_JOINED);
388     MUTEX_UNLOCK(&t->mutex);
389     break;
390     case THRf_ZOMBIE:
391     ThrSETSTATE(t, THRf_DEAD);
392     MUTEX_UNLOCK(&t->mutex);
393     remove_thread(aTHX_ t);
394     break;
395     default:
396     MUTEX_UNLOCK(&t->mutex);
397     croak("can't join with thread");
398     /* NOTREACHED */
399     }
400     JOIN(t, &av);
401    
402     sv_2mortal((SV*)av);
403    
404     if (SvTRUE(*av_fetch(av, 0, FALSE))) {
405     /* Could easily speed up the following if necessary */
406     for (i = 1; i <= AvFILL(av); i++)
407     XPUSHs(*av_fetch(av, i, FALSE));
408     }
409     else {
410     STRLEN n_a;
411     char *mess = SvPV(*av_fetch(av, 1, FALSE), n_a);
412     DEBUG_S(PerlIO_printf(Perl_debug_log,
413     "%p: join propagating die message: %s\n",
414     thr, mess));
415     croak(mess);
416     }
417     #endif
418    
419     void
420     detach(t)
421     Thread t
422     CODE:
423     #ifdef USE_5005THREADS
424     DEBUG_S(PerlIO_printf(Perl_debug_log, "%p: detaching %p (state %u)\n",
425     thr, t, ThrSTATE(t)));
426     MUTEX_LOCK(&t->mutex);
427     switch (ThrSTATE(t)) {
428     case THRf_R_JOINABLE:
429     ThrSETSTATE(t, THRf_R_DETACHED);
430     /* fall through */
431     case THRf_R_DETACHED:
432     DETACH(t);
433     MUTEX_UNLOCK(&t->mutex);
434     break;
435     case THRf_ZOMBIE:
436     ThrSETSTATE(t, THRf_DEAD);
437     DETACH(t);
438     MUTEX_UNLOCK(&t->mutex);
439     remove_thread(aTHX_ t);
440     break;
441     default:
442     MUTEX_UNLOCK(&t->mutex);
443     croak("can't detach thread");
444     /* NOTREACHED */
445     }
446     #endif
447    
448     void
449     equal(t1, t2)
450     Thread t1
451     Thread t2
452     PPCODE:
453     PUSHs((t1 == t2) ? &PL_sv_yes : &PL_sv_no);
454    
455     void
456     flags(t)
457     Thread t
458     PPCODE:
459     #ifdef USE_5005THREADS
460     PUSHs(sv_2mortal(newSViv(t->flags)));
461     #endif
462    
463     void
464     done(t)
465     Thread t
466     PPCODE:
467     #ifdef USE_5005THREADS
468     PUSHs(t->thr_done ? &PL_sv_yes : &PL_sv_no);
469     #endif
470    
471     void
472     self(classname)
473     char * classname
474     PREINIT:
475     #ifdef USE_5005THREADS
476     SV *sv;
477     #endif
478     PPCODE:
479     #ifdef USE_5005THREADS
480     sv = newSViv(thr->tid);
481     sv_magic(sv, thr->oursv, '~', 0, 0);
482     SvMAGIC(sv)->mg_private = Thread_MAGIC_SIGNATURE;
483     PUSHs(sv_2mortal(sv_bless(newRV_noinc(sv),
484     gv_stashpv(classname, TRUE))));
485     #endif
486    
487     U32
488     tid(t)
489     Thread t
490     CODE:
491     #ifdef USE_5005THREADS
492     MUTEX_LOCK(&t->mutex);
493     RETVAL = t->tid;
494     MUTEX_UNLOCK(&t->mutex);
495     #else
496     RETVAL = 0;
497     #endif
498     OUTPUT:
499     RETVAL
500    
501     void
502     DESTROY(t)
503     SV * t
504     PPCODE:
505     PUSHs(t ? &PL_sv_yes : &PL_sv_no);
506    
507     void
508     yield()
509     CODE:
510     {
511     #ifdef USE_5005THREADS
512     YIELD;
513     #endif
514     }
515    
516     void
517     cond_wait(sv)
518     SV * sv
519     PREINIT:
520     #ifdef USE_5005THREADS
521     MAGIC * mg;
522     #endif
523     CODE:
524     #ifdef USE_5005THREADS
525     if (SvROK(sv))
526     sv = SvRV(sv);
527    
528     mg = condpair_magic(sv);
529     DEBUG_S(PerlIO_printf(Perl_debug_log, "%p: cond_wait %p\n", thr, sv));
530     MUTEX_LOCK(MgMUTEXP(mg));
531     if (MgOWNER(mg) != thr) {
532     MUTEX_UNLOCK(MgMUTEXP(mg));
533     croak("cond_wait for lock that we don't own\n");
534     }
535     MgOWNER(mg) = 0;
536     COND_SIGNAL(MgOWNERCONDP(mg));
537     COND_WAIT(MgCONDP(mg), MgMUTEXP(mg));
538     while (MgOWNER(mg))
539     COND_WAIT(MgOWNERCONDP(mg), MgMUTEXP(mg));
540     MgOWNER(mg) = thr;
541     MUTEX_UNLOCK(MgMUTEXP(mg));
542     #endif
543    
544     void
545     cond_signal(sv)
546     SV * sv
547     PREINIT:
548     #ifdef USE_5005THREADS
549     MAGIC * mg;
550     #endif
551     CODE:
552     #ifdef USE_5005THREADS
553     if (SvROK(sv))
554     sv = SvRV(sv);
555    
556     mg = condpair_magic(sv);
557     DEBUG_S(PerlIO_printf(Perl_debug_log, "%p: cond_signal %p\n",thr,sv));
558     MUTEX_LOCK(MgMUTEXP(mg));
559     if (MgOWNER(mg) != thr) {
560     MUTEX_UNLOCK(MgMUTEXP(mg));
561     croak("cond_signal for lock that we don't own\n");
562     }
563     COND_SIGNAL(MgCONDP(mg));
564     MUTEX_UNLOCK(MgMUTEXP(mg));
565     #endif
566    
567     void
568     cond_broadcast(sv)
569     SV * sv
570     PREINIT:
571     #ifdef USE_5005THREADS
572     MAGIC * mg;
573     #endif
574     CODE:
575     #ifdef USE_5005THREADS
576     if (SvROK(sv))
577     sv = SvRV(sv);
578    
579     mg = condpair_magic(sv);
580     DEBUG_S(PerlIO_printf(Perl_debug_log, "%p: cond_broadcast %p\n",
581     thr, sv));
582     MUTEX_LOCK(MgMUTEXP(mg));
583     if (MgOWNER(mg) != thr) {
584     MUTEX_UNLOCK(MgMUTEXP(mg));
585     croak("cond_broadcast for lock that we don't own\n");
586     }
587     COND_BROADCAST(MgCONDP(mg));
588     MUTEX_UNLOCK(MgMUTEXP(mg));
589     #endif
590    
591     void
592     list(classname)
593     char * classname
594     PREINIT:
595     #ifdef USE_5005THREADS
596     Thread t;
597     AV * av;
598     SV ** svp;
599     int n = 0;
600     #endif
601     PPCODE:
602     #ifdef USE_5005THREADS
603     av = newAV();
604     /*
605     * Iterate until we have enough dynamic storage for all threads.
606     * We mustn't do any allocation while holding threads_mutex though.
607     */
608     MUTEX_LOCK(&PL_threads_mutex);
609     do {
610     n = PL_nthreads;
611     MUTEX_UNLOCK(&PL_threads_mutex);
612     if (AvFILL(av) < n - 1) {
613     int i = AvFILL(av);
614     for (i = AvFILL(av); i < n - 1; i++) {
615     SV *sv = newSViv(0); /* fill in tid later */
616     sv_magic(sv, 0, '~', 0, 0); /* fill in other magic later */
617     av_push(av, sv_bless(newRV_noinc(sv),
618     gv_stashpv(classname, TRUE)));
619    
620     }
621     }
622     MUTEX_LOCK(&PL_threads_mutex);
623     } while (n < PL_nthreads);
624     n = PL_nthreads; /* Get the final correct value */
625    
626     /*
627     * At this point, there's enough room to fill in av.
628     * Note that we are holding threads_mutex so the list
629     * won't change out from under us but all the remaining
630     * processing is "fast" (no blocking, malloc etc.)
631     */
632     t = thr;
633     svp = AvARRAY(av);
634     do {
635     SV *sv = (SV*)SvRV(*svp);
636     sv_setiv(sv, t->tid);
637     SvMAGIC(sv)->mg_obj = SvREFCNT_inc(t->oursv);
638     SvMAGIC(sv)->mg_flags |= MGf_REFCOUNTED;
639     SvMAGIC(sv)->mg_private = Thread_MAGIC_SIGNATURE;
640     t = t->next;
641     svp++;
642     } while (t != thr);
643     /* */
644     MUTEX_UNLOCK(&PL_threads_mutex);
645     /* Truncate any unneeded slots in av */
646     av_fill(av, n - 1);
647     /* Finally, push all the new objects onto the stack and drop av */
648     EXTEND(SP, n);
649     for (svp = AvARRAY(av); n > 0; n--, svp++)
650     PUSHs(*svp);
651     (void)sv_2mortal((SV*)av);
652     #endif
653    
654    
655     MODULE = Thread PACKAGE = Thread::Signal
656    
657     void
658     kill_sighandler_thread()
659     PPCODE:
660     write(sig_pipe[1], "\0", 1);
661     PUSHs(&PL_sv_yes);
662    
663     void
664     init_thread_signals()
665     PPCODE:
666     PL_sighandlerp = handle_thread_signal;
667     if (pipe(sig_pipe) == -1)
668     XSRETURN_UNDEF;
669     PUSHs(&PL_sv_yes);
670    
671     void
672     await_signal()
673     PREINIT:
674     unsigned char c;
675     SSize_t ret;
676     CODE:
677     do {
678     ret = read(sig_pipe[0], &c, 1);
679     } while (ret == -1 && errno == EINTR);
680     if (ret == -1)
681     croak("panic: await_signal");
682     ST(0) = sv_newmortal();
683     if (ret)
684     sv_setsv(ST(0), c ? PL_psig_ptr[c] : &PL_sv_no);
685     DEBUG_S(PerlIO_printf(Perl_debug_log,
686     "await_signal returning %s\n", SvPEEK(ST(0))));
687    
688     MODULE = Thread PACKAGE = Thread::Specific
689    
690     void
691     data(classname = "Thread::Specific")
692     char * classname
693     PPCODE:
694     #ifdef USE_5005THREADS
695     if (AvFILL(thr->specific) == -1) {
696     GV *gv = gv_fetchpv("Thread::Specific::FIELDS", TRUE, SVt_PVHV);
697     av_store(thr->specific, 0, newRV((SV*)GvHV(gv)));
698     }
699     XPUSHs(sv_bless(newRV((SV*)thr->specific),gv_stashpv(classname,TRUE)));
700     #endif