fix coredump on 'local $shared[N]' introduced by change #24942
[p5sagit/p5-mst-13.2.git] / ext / threads / shared / shared.xs
1 /*    shared.xs
2  *
3  *    Copyright (c) 2001-2002, 2006 Larry Wall
4  *
5  *    You may distribute under the terms of either the GNU General Public
6  *    License or the Artistic License, as specified in the README file.
7  *
8  * "Hand any two wizards a piece of rope and they would instinctively pull in
9  * opposite directions."
10  *                         --Sourcery
11  *
12  * Contributed by Arthur Bergman arthur@contiller.se
13  * pulled in the (an)other direction by Nick Ing-Simmons nick@ing-simmons.net
14  */
15
16 /*
17  * Shared variables are implemented by a scheme similar to tieing.
18  * Each thread has a proxy SV with attached magic -- "private SVs" --
19  * which all point to a single SV in a separate shared interpreter
20  * (PL_sharedsv_space) -- "shared SVs".
21  *
22  * The shared SV holds the variable's true values, and its state is
23  * copied between the shared and private SVs with the usual
24  * mg_get()/mg_set() arrangement.
25  *
26  * Aggregates (AVs and HVs) are implemented using tie magic, except that
27  * the vtable used is one defined in this file rather than the standard one.
28  * This means that where a tie function like is FETCH is normally invoked by
29  * the tie magic's mg_get() function, we completely bypass the calling of a
30  * perl-level function, and directly call C-level code to handle it. On
31  * the other hand. calls to functions like PUSH are done directly by code
32  * in av.c etc, which we can't bypass. So the best we can do is to provide
33  * XS versions of these functions. We also have to attach a tie object,
34  * blessed into the class threads::shared::tie, to keep the method-calling
35  * code happy.
36  *
37  * Access to aggregate elements is done the usual tied way by returning a
38  * proxy PVLV element with attached element magic.
39  *
40  * Pointers to the shared SV are squirrelled away in the mg->mg_ptr field
41  * of magic (with mg_len == 0), and in the IV2PTR(SvIV(sv)) field of tied
42  * object SVs. These pointers have to be hidden like this because they
43  * cross interpreter boundaries, and we don't want sv_clear() and friends
44  * following them.
45  *
46  * The three basic shared types look like the following:
47  *
48  * -----------------
49  *
50  * Shared scalar (my $s : shared):
51  *
52  *  SV = PVMG(0x7ba238) at 0x7387a8
53  *   FLAGS = (PADMY,GMG,SMG)
54  *   MAGIC = 0x824d88
55  *     MG_TYPE = PERL_MAGIC_shared_scalar(n)
56  *     MG_PTR = 0x810358                <<<< pointer to the shared SV
57  *
58  * -----------------
59  *
60  * Shared aggregate (my @a : shared;  my %h : shared):
61  *
62  * SV = PVAV(0x7175d0) at 0x738708
63  *   FLAGS = (PADMY,RMG)
64  *   MAGIC = 0x824e48
65  *     MG_TYPE = PERL_MAGIC_tied(P)
66  *     MG_OBJ = 0x7136e0                <<<< ref to the tied object
67  *     SV = RV(0x7136f0) at 0x7136e0
68  *       RV = 0x738640
69  *       SV = PVMG(0x7ba238) at 0x738640 <<<< the tied object
70  *         FLAGS = (OBJECT,IOK,pIOK)
71  *         IV = 8455000                 <<<< pointer to the shared AV
72  *         STASH = 0x80abf0 "threads::shared::tie"
73  *     MG_PTR = 0x810358 ""             <<<< another pointer to the shared AV
74  *   ARRAY = 0x0
75  *
76  * -----------------
77  *
78  * Aggregate element (my @a : shared; $a[0])
79  *
80  * SV = PVLV(0x77f628) at 0x713550
81  *   FLAGS = (GMG,SMG,RMG,pIOK)
82  *   MAGIC = 0x72bd58
83  *     MG_TYPE = PERL_MAGIC_shared_scalar(n)
84  *     MG_PTR = 0x8103c0 ""             <<<< pointer to the shared element
85  *   MAGIC = 0x72bd18
86  *     MG_TYPE = PERL_MAGIC_tiedelem(p)
87  *     MG_OBJ = 0x7136e0                <<<< ref to the tied object
88  *     SV = RV(0x7136f0) at 0x7136e0
89  *       RV = 0x738660
90  *       SV = PVMG(0x7ba278) at 0x738660 <<<< the tied object
91  *         FLAGS = (OBJECT,IOK,pIOK)
92  *         IV = 8455064                 <<<< pointer to the shared AV
93  *         STASH = 0x80ac30 "threads::shared::tie"
94  *   TYPE = t
95  *
96  * Note that PERL_MAGIC_tiedelem(p) magic doesn't have a pointer to a
97  * shared SV in mg_ptr; instead this is used to store the hash key,
98  * if any, like normal tied elements. Note also that element SVs may have
99  * pointers to both the shared aggregate and the shared element
100  *
101  *
102  * Userland locks:
103  *
104  * if a shared variable is used as a perl-level lock or condition
105  * variable, then PERL_MAGIC_ext magic is attached to the associated
106  * *shared* SV, whose mg_ptr field points to a malloced structure
107  * containing the necessary mutexes and condition variables.
108  *
109  * Nomenclature:
110  *
111  * In this file, any variable name prefixed with 's', eg ssv, stmp or sobj,
112  * usually represents a shared SV which correspondis to a private SV named
113  * without the prefix, eg sv, tmp or obj.
114  */
115
116 #define PERL_NO_GET_CONTEXT
117 #include "EXTERN.h"
118 #include "perl.h"
119 #include "XSUB.h"
120
121 #ifdef USE_ITHREADS
122
123 /*
124  * The shared things need an intepreter to live in ...
125  */
126 PerlInterpreter *PL_sharedsv_space;             /* The shared sv space */
127 /* To access shared space we fake aTHX in this scope and thread's context */
128
129 /* bug #24255: we include ENTER+SAVETMPS/FREETMPS+LEAVE with
130  * SHARED_CONTEXT/CALLER_CONTEXT macros, so that any mortals etc created
131  * while in the shared interpreter context don't languish */
132
133 #define SHARED_CONTEXT \
134     STMT_START {                                        \
135         PERL_SET_CONTEXT((aTHX = PL_sharedsv_space));   \
136         ENTER;                                          \
137         SAVETMPS;                                       \
138     } STMT_END
139
140 /* So we need a way to switch back to the caller's context... */
141 /* So we declare _another_ copy of the aTHX variable ... */
142 #define dTHXc PerlInterpreter *caller_perl = aTHX
143
144 /* and use it to switch back */
145 #define CALLER_CONTEXT                                  \
146     STMT_START {                                        \
147         FREETMPS;                                       \
148         LEAVE;                                          \
149         PERL_SET_CONTEXT((aTHX = caller_perl));         \
150     } STMT_END
151
152 /*
153  * Only one thread at a time is allowed to mess with shared space.
154  */
155
156 typedef struct
157 {
158  perl_mutex              mutex;
159  PerlInterpreter        *owner;
160  I32                     locks;
161  perl_cond               cond;
162 #ifdef DEBUG_LOCKS
163  char *                  file;
164  int                     line;
165 #endif
166 } recursive_lock_t;
167
168 recursive_lock_t PL_sharedsv_lock;       /* Mutex protecting the shared sv space */
169
170 void
171 recursive_lock_init(pTHX_ recursive_lock_t *lock)
172 {
173     Zero(lock,1,recursive_lock_t);
174     MUTEX_INIT(&lock->mutex);
175     COND_INIT(&lock->cond);
176 }
177
178 void
179 recursive_lock_destroy(pTHX_ recursive_lock_t *lock)
180 {
181     MUTEX_DESTROY(&lock->mutex);
182     COND_DESTROY(&lock->cond);
183 }
184
185 void
186 recursive_lock_release(pTHX_ recursive_lock_t *lock)
187 {
188     MUTEX_LOCK(&lock->mutex);
189     if (lock->owner != aTHX) {
190         MUTEX_UNLOCK(&lock->mutex);
191     }
192     else {
193         if (--lock->locks == 0) {
194             lock->owner = NULL;
195             COND_SIGNAL(&lock->cond);
196         }
197     }
198     MUTEX_UNLOCK(&lock->mutex);
199 }
200
201 void
202 recursive_lock_acquire(pTHX_ recursive_lock_t *lock,char *file,int line)
203 {
204     assert(aTHX);
205     MUTEX_LOCK(&lock->mutex);
206     if (lock->owner == aTHX) {
207         lock->locks++;
208     }
209     else {
210         while (lock->owner) {
211 #ifdef DEBUG_LOCKS
212             Perl_warn(aTHX_ " %p waiting - owned by %p %s:%d\n",
213                       aTHX, lock->owner, lock->file, lock->line);
214 #endif
215             COND_WAIT(&lock->cond,&lock->mutex);
216         }
217         lock->locks = 1;
218         lock->owner = aTHX;
219 #ifdef DEBUG_LOCKS
220         lock->file  = file;
221         lock->line  = line;
222 #endif
223     }
224     MUTEX_UNLOCK(&lock->mutex);
225     SAVEDESTRUCTOR_X(recursive_lock_release,lock);
226 }
227
228 #define ENTER_LOCK         STMT_START { \
229                               ENTER; \
230                               recursive_lock_acquire(aTHX_ &PL_sharedsv_lock, __FILE__, __LINE__);   \
231                             } STMT_END
232
233 /* the unlocking is done automatically at scope exit */
234 #define LEAVE_LOCK       LEAVE
235
236
237 /* A common idiom is to acquire access and switch in ... */
238 #define SHARED_EDIT         STMT_START {        \
239                                 ENTER_LOCK;     \
240                                 SHARED_CONTEXT; \
241                             } STMT_END
242
243 /* then switch out and release access. */
244 #define SHARED_RELEASE     STMT_START { \
245                                 CALLER_CONTEXT; \
246                                 LEAVE_LOCK;     \
247                             } STMT_END
248
249
250 /* user-level locks:
251    This structure is attached (using ext magic) to any shared SV that
252    is used by user-level locking or condition code
253 */
254
255 typedef struct {
256     recursive_lock_t    lock;           /* for user-levl locks */
257     perl_cond           user_cond;      /* For user-level conditions */
258 } user_lock;
259
260 /* magic used for attaching user_lock structs to shared SVs
261
262    The vtable used has just one entry - when the SV goes away
263    we free the memory for the above.
264  */
265
266 int
267 sharedsv_userlock_free(pTHX_ SV *sv, MAGIC *mg)
268 {
269     user_lock *ul = (user_lock *) mg->mg_ptr;
270     assert(aTHX == PL_sharedsv_space);
271     if (ul) {
272         recursive_lock_destroy(aTHX_ &ul->lock);
273         COND_DESTROY(&ul->user_cond);
274         PerlMemShared_free(ul);
275         mg->mg_ptr = NULL;
276     }
277     return 0;
278 }
279
280 MGVTBL sharedsv_uesrlock_vtbl = {
281  0,                             /* get */
282  0,                             /* set */
283  0,                             /* len */
284  0,                             /* clear */
285  sharedsv_userlock_free,        /* free */
286  0,                             /* copy */
287  0,                             /* dup */
288  0                              /* local */
289 };
290
291 /* Access to shared things is heavily based on MAGIC - in mg.h/mg.c/sv.c sense */
292
293 /* In any thread that has access to a shared thing there is a "proxy"
294    for it in its own space which has 'MAGIC' associated which accesses
295    the shared thing.
296  */
297
298 MGVTBL sharedsv_scalar_vtbl;    /* scalars have this vtable */
299 MGVTBL sharedsv_array_vtbl;     /* hashes and arrays have this - like 'tie' */
300 MGVTBL sharedsv_elem_vtbl;      /* elements of hashes and arrays have this
301                                    _AS WELL AS_ the scalar magic:
302    The sharedsv_elem_vtbl associates the element with the array/hash and
303    the sharedsv_scalar_vtbl associates it with the value
304  */
305
306
307 /* get shared aggregate SV pointed to by threads::shared::tie magic object */
308
309 STATIC SV *
310 S_sharedsv_from_obj(pTHX_ SV *sv)
311 {
312      return SvROK(sv) ? INT2PTR(SV *, SvIV(SvRV(sv))) : NULL;
313 }
314
315
316 /* Return the user_lock structure (if any) associated with a shared SV.
317  * If create is true, create one if it doesn't exist */
318
319 STATIC user_lock *
320 S_get_userlock(pTHX_ SV* ssv, bool create)
321 {
322     MAGIC *mg;
323     user_lock *ul = NULL;
324
325     assert(ssv);
326     /* XXX redsign the storage of user locks so we dont need a global
327      * lock to access them ???? DAPM */
328     ENTER_LOCK;
329     mg = mg_find(ssv, PERL_MAGIC_ext);
330     if (mg)
331         ul = (user_lock*)(mg->mg_ptr);
332     else if (create) {
333         dTHXc;
334         SHARED_CONTEXT;
335         ul = (user_lock *) PerlMemShared_malloc(sizeof(user_lock));
336         Zero(ul, 1, user_lock);
337         /* attach to shared SV using ext magic */
338         sv_magicext(ssv, NULL, PERL_MAGIC_ext, &sharedsv_uesrlock_vtbl,
339                (char *)ul, 0);
340         recursive_lock_init(aTHX_ &ul->lock);
341         COND_INIT(&ul->user_cond);
342         CALLER_CONTEXT;
343     }
344     LEAVE_LOCK;
345     return ul;
346 }
347
348
349 =for apidoc sharedsv_find
350
351 Given a private side SV tries to find if the SV has a shared backend,
352 by looking for the magic.
353
354 =cut
355
356 SV *
357 Perl_sharedsv_find(pTHX_ SV *sv)
358 {
359     MAGIC *mg;
360     if (SvTYPE(sv) >= SVt_PVMG) {
361         switch(SvTYPE(sv)) {
362         case SVt_PVAV:
363         case SVt_PVHV:
364             if ((mg = mg_find(sv, PERL_MAGIC_tied))
365                 && mg->mg_virtual == &sharedsv_array_vtbl) {
366                 return (SV *) mg->mg_ptr;
367             }
368             break;
369         default:
370             /* This should work for elements as well as they
371              * have scalar magic as well as their element magic
372              */
373             if ((mg = mg_find(sv, PERL_MAGIC_shared_scalar))
374                 && mg->mg_virtual == &sharedsv_scalar_vtbl) {
375                 return (SV *) mg->mg_ptr;
376             }
377             break;
378         }
379     }
380     /* Just for tidyness of API also handle tie objects */
381     if (SvROK(sv) && sv_derived_from(sv, "threads::shared::tie")) {
382         return S_sharedsv_from_obj(aTHX_ sv);
383     }
384     return NULL;
385 }
386
387
388 /* associate a private SV  with a shared SV by pointing the appropriate
389  * magics at it.  Assumes lock is held */
390
391 void
392 Perl_sharedsv_associate(pTHX_ SV *sv, SV *ssv)
393 {
394     dTHXc;
395     MAGIC *mg = 0;
396
397     /* If we are asked for any private ops we need a thread */
398     assert ( aTHX !=  PL_sharedsv_space );
399
400     /* To avoid need for recursive locks require caller to hold lock */
401     assert ( PL_sharedsv_lock.owner == aTHX );
402
403     switch(SvTYPE(sv)) {
404     case SVt_PVAV:
405     case SVt_PVHV:
406         if (!(mg = mg_find(sv, PERL_MAGIC_tied))
407             || mg->mg_virtual != &sharedsv_array_vtbl
408             || (SV*) mg->mg_ptr != ssv)
409         {
410             SV *obj = newSV(0);
411             sv_setref_iv(obj, "threads::shared::tie",PTR2IV(ssv));
412             if (mg) {
413                 sv_unmagic(sv, PERL_MAGIC_tied);
414             }
415             mg = sv_magicext(sv, obj, PERL_MAGIC_tied, &sharedsv_array_vtbl,
416                             (char *) ssv, 0);
417             mg->mg_flags |= (MGf_COPY|MGf_DUP);
418             SvREFCNT_inc(ssv);
419             SvREFCNT_dec(obj);
420             if (SvOBJECT(ssv)) {
421                 STRLEN len;
422                 char* stash_ptr = SvPV((SV*) SvSTASH(ssv), len);
423                 HV* stash = gv_stashpvn(stash_ptr, len, TRUE);
424                 SvOBJECT_on(sv);
425                 SvSTASH_set(sv, (HV*)SvREFCNT_inc(stash));
426             }
427         }
428         break;
429
430     default:
431         if ((SvTYPE(sv) < SVt_PVMG)
432             || !(mg = mg_find(sv, PERL_MAGIC_shared_scalar))
433             || mg->mg_virtual != &sharedsv_scalar_vtbl
434             || (SV*) mg->mg_ptr != ssv)
435         {
436             if (mg) {
437                 sv_unmagic(sv, PERL_MAGIC_shared_scalar);
438             }
439             mg = sv_magicext(sv, Nullsv, PERL_MAGIC_shared_scalar,
440                             &sharedsv_scalar_vtbl, (char *)ssv, 0);
441             mg->mg_flags |= (MGf_DUP|MGf_LOCAL);
442             SvREFCNT_inc(ssv);
443             if(SvOBJECT(ssv)) {
444               STRLEN len;
445               char* stash_ptr = SvPV((SV*) SvSTASH(ssv), len);
446               HV* stash = gv_stashpvn(stash_ptr, len, TRUE);
447               SvOBJECT_on(sv);
448               SvSTASH_set(sv, (HV*)SvREFCNT_inc(stash));
449             }
450         }
451         break;
452     }
453     assert ( Perl_sharedsv_find(aTHX_ sv) == ssv );
454 }
455
456
457 /* Given a private SV, create and return an associated shared SV.
458  * Assumes lock is held */
459
460 STATIC SV *
461 S_sharedsv_new_shared(pTHX_ SV *sv)
462 {
463     dTHXc;
464     SV *ssv;
465
466     assert(PL_sharedsv_lock.owner == aTHX);
467     assert(aTHX !=  PL_sharedsv_space);
468
469     SHARED_CONTEXT;
470     ssv = newSV(0);
471     SvREFCNT(ssv) = 0; /* will be upped to 1 by Perl_sharedsv_associate */
472     sv_upgrade(ssv, SvTYPE(sv));
473     CALLER_CONTEXT;
474     Perl_sharedsv_associate(aTHX_ sv, ssv);
475     return ssv;
476 }
477
478
479 /* Given a shared SV, create and return an associated private SV.
480  * Assumes lock is held */
481
482 STATIC SV *
483 S_sharedsv_new_private(pTHX_ SV *ssv)
484 {
485     SV *sv;
486
487     assert(PL_sharedsv_lock.owner == aTHX);
488     assert(aTHX !=  PL_sharedsv_space);
489
490     sv = newSV(0);
491     sv_upgrade(sv, SvTYPE(ssv));
492     Perl_sharedsv_associate(aTHX_ sv, ssv);
493     return sv;
494 }
495
496
497 /* a threadsafe version of SvREFCNT_dec(ssv) */
498
499 STATIC void
500 S_sharedsv_dec(pTHX_ SV* ssv)
501 {
502     if (!ssv)
503         return;
504     ENTER_LOCK;
505     if (SvREFCNT(ssv) > 1) {
506         /* no side effects, so can do it lightweight */
507         SvREFCNT_dec(ssv);
508     }
509     else {
510         dTHXc;
511         SHARED_CONTEXT;
512         SvREFCNT_dec(ssv);
513         CALLER_CONTEXT;
514     }
515     LEAVE_LOCK;
516 }
517
518 /* implements Perl-level share() and :shared */
519
520 void
521 Perl_sharedsv_share(pTHX_ SV *sv)
522 {
523     switch(SvTYPE(sv)) {
524     case SVt_PVGV:
525         Perl_croak(aTHX_ "Cannot share globs yet");
526         break;
527
528     case SVt_PVCV:
529         Perl_croak(aTHX_ "Cannot share subs yet");
530         break;
531
532     default:
533         ENTER_LOCK;
534         (void) S_sharedsv_new_shared(aTHX_ sv);
535         LEAVE_LOCK;
536         SvSETMAGIC(sv);
537         break;
538     }
539 }
540
541 #if defined(WIN32) || defined(OS2)
542 #  define ABS2RELMILLI(abs)        \
543     do {                                \
544         abs -= (double)time(NULL);      \
545         if (abs > 0) { abs *= 1000; }   \
546         else         { abs  = 0;    }   \
547     } while (0)
548 #endif /* WIN32 || OS2 */
549
550 /* do OS-specific condition timed wait */
551
552 bool
553 Perl_sharedsv_cond_timedwait(perl_cond *cond, perl_mutex *mut, double abs)
554 {
555 #if defined(NETWARE) || defined(FAKE_THREADS) || defined(I_MACH_CTHREADS)
556     Perl_croak_nocontext("cond_timedwait not supported on this platform");
557 #else
558 #  ifdef WIN32
559     int got_it = 0;
560
561     ABS2RELMILLI(abs);
562
563     cond->waiters++;
564     MUTEX_UNLOCK(mut);
565     /* See comments in win32/win32thread.h COND_WAIT vis-a-vis race */
566     switch (WaitForSingleObject(cond->sem, (DWORD)abs)) {
567         case WAIT_OBJECT_0:   got_it = 1; break;
568         case WAIT_TIMEOUT:                break;
569         default:
570             /* WAIT_FAILED? WAIT_ABANDONED? others? */
571             Perl_croak_nocontext("panic: cond_timedwait (%ld)",GetLastError());
572             break;
573     }
574     MUTEX_LOCK(mut);
575     cond->waiters--;
576     return got_it;
577 #  else
578 #    ifdef OS2
579     int rc, got_it = 0;
580     STRLEN n_a;
581
582     ABS2RELMILLI(abs);
583
584     if ((rc = DosResetEventSem(*cond,&n_a)) && (rc != ERROR_ALREADY_RESET))
585         Perl_rc = rc, croak_with_os2error("panic: cond_timedwait-reset");
586     MUTEX_UNLOCK(mut);
587     if (CheckOSError(DosWaitEventSem(*cond,abs))
588         && (rc != ERROR_INTERRUPT))
589         croak_with_os2error("panic: cond_timedwait");
590     if (rc == ERROR_INTERRUPT) errno = EINTR;
591     MUTEX_LOCK(mut);
592     return got_it;
593 #    else         /* hope you're I_PTHREAD! */
594     struct timespec ts;
595     int got_it = 0;
596
597     ts.tv_sec = (long)abs;
598     abs -= (NV)ts.tv_sec;
599     ts.tv_nsec = (long)(abs * 1000000000.0);
600
601     switch (pthread_cond_timedwait(cond, mut, &ts)) {
602         case 0:         got_it = 1; break;
603         case ETIMEDOUT:             break;
604         default:
605             Perl_croak_nocontext("panic: cond_timedwait");
606             break;
607     }
608     return got_it;
609 #    endif /* OS2 */
610 #  endif /* WIN32 */
611 #endif /* NETWARE || FAKE_THREADS || I_MACH_CTHREADS */
612 }
613
614 /* ------------ PERL_MAGIC_shared_scalar(n) functions -------------- */
615
616 /* get magic for PERL_MAGIC_shared_scalar(n) */
617
618 int
619 sharedsv_scalar_mg_get(pTHX_ SV *sv, MAGIC *mg)
620 {
621     SV *ssv = (SV *) mg->mg_ptr;
622     assert(ssv);
623
624     ENTER_LOCK;
625     if (SvROK(ssv)) {
626         SV *obj = S_sharedsv_new_private(aTHX_ SvRV(ssv));
627         sv_setsv_nomg(sv, &PL_sv_undef);
628         SvRV_set(sv, obj);
629         SvROK_on(sv);
630     }
631     else {
632         sv_setsv_nomg(sv, ssv);
633     }
634     LEAVE_LOCK;
635     return 0;
636 }
637
638 /* copy the contents of a private SV to a shared SV:
639  * used by various mg_set()-type functions.
640  * Assumes lock is held */
641
642 void
643 sharedsv_scalar_store(pTHX_ SV *sv, SV *ssv)
644 {
645     dTHXc;
646     bool allowed = TRUE;
647
648     assert(PL_sharedsv_lock.owner == aTHX);
649     if (SvROK(sv)) {
650         SV *obj = SvRV(sv);
651         SV *sobj = Perl_sharedsv_find(aTHX_ obj);
652         if (sobj) {
653             SHARED_CONTEXT;
654             SvUPGRADE(ssv, SVt_RV);
655             sv_setsv_nomg(ssv, &PL_sv_undef);
656             
657             SvRV_set(ssv, SvREFCNT_inc(sobj));
658             SvROK_on(ssv);
659             if(SvOBJECT(obj)) {
660               SV* fake_stash = newSVpv(HvNAME_get(SvSTASH(obj)),0);
661               SvOBJECT_on(sobj);
662               SvSTASH_set(sobj, (HV*)fake_stash);
663             }
664             CALLER_CONTEXT;
665         }
666         else {
667             allowed = FALSE;
668         }
669     }
670     else {
671         SvTEMP_off(sv);
672         SHARED_CONTEXT;
673         sv_setsv_nomg(ssv, sv);
674         if(SvOBJECT(sv)) {
675           SV* fake_stash = newSVpv(HvNAME_get(SvSTASH(sv)),0);
676           SvOBJECT_on(ssv);
677           SvSTASH_set(ssv, (HV*)fake_stash);
678         }
679         CALLER_CONTEXT;
680     }
681     if (!allowed) {
682         Perl_croak(aTHX_ "Invalid value for shared scalar");
683     }
684 }
685
686 /* set magic for PERL_MAGIC_shared_scalar(n) */
687
688 int
689 sharedsv_scalar_mg_set(pTHX_ SV *sv, MAGIC *mg)
690 {
691     SV *ssv = (SV*)(mg->mg_ptr);
692     assert(ssv);
693     ENTER_LOCK;
694     if (SvTYPE(ssv) < SvTYPE(sv)) {
695         dTHXc;
696         SHARED_CONTEXT;
697         sv_upgrade(ssv, SvTYPE(sv));
698         CALLER_CONTEXT;
699     }
700     sharedsv_scalar_store(aTHX_ sv, ssv);
701     LEAVE_LOCK;
702     return 0;
703 }
704
705 /* free magic for PERL_MAGIC_shared_scalar(n) */
706
707 int
708 sharedsv_scalar_mg_free(pTHX_ SV *sv, MAGIC *mg)
709 {
710     S_sharedsv_dec(aTHX_ (SV*)mg->mg_ptr);
711     return 0;
712 }
713
714 /*
715  * Called during cloning of PERL_MAGIC_shared_scalar(n) magic in new thread
716  */
717 int
718 sharedsv_scalar_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
719 {
720     SvREFCNT_inc(mg->mg_ptr);
721     return 0;
722 }
723
724 /*
725  * Called during local $shared
726  */
727 int
728 sharedsv_scalar_mg_local(pTHX_ SV* nsv, MAGIC *mg)
729 {
730     MAGIC *nmg;
731     SV *ssv = (SV *) mg->mg_ptr;
732     if (ssv) {
733         ENTER_LOCK;
734         SvREFCNT_inc(ssv);
735         LEAVE_LOCK;
736     }
737     nmg = sv_magicext(nsv, mg->mg_obj, mg->mg_type, mg->mg_virtual,
738                             mg->mg_ptr, mg->mg_len);
739     nmg->mg_flags   = mg->mg_flags;
740     nmg->mg_private = mg->mg_private;
741
742     return 0;
743 }
744
745 MGVTBL sharedsv_scalar_vtbl = {
746  sharedsv_scalar_mg_get,        /* get */
747  sharedsv_scalar_mg_set,        /* set */
748  0,                             /* len */
749  0,                             /* clear */
750  sharedsv_scalar_mg_free,       /* free */
751  0,                             /* copy */
752  sharedsv_scalar_mg_dup,        /* dup */
753  sharedsv_scalar_mg_local       /* local */
754 };
755
756 /* ------------ PERL_MAGIC_tiedelem(p) functions -------------- */
757
758 /* get magic for PERL_MAGIC_tiedelem(p) */
759
760 int
761 sharedsv_elem_mg_FETCH(pTHX_ SV *sv, MAGIC *mg)
762 {
763     dTHXc;
764     SV *saggregate = S_sharedsv_from_obj(aTHX_ mg->mg_obj);
765     SV** svp;
766
767     ENTER_LOCK;
768     if (SvTYPE(saggregate) == SVt_PVAV) {
769         assert ( mg->mg_ptr == 0 );
770         SHARED_CONTEXT;
771         svp = av_fetch((AV*) saggregate, mg->mg_len, 0);
772     }
773     else {
774         char *key = mg->mg_ptr;
775         STRLEN len = mg->mg_len;
776         assert ( mg->mg_ptr != 0 );
777         if (mg->mg_len == HEf_SVKEY) {
778            key = SvPV((SV *) mg->mg_ptr, len);
779         }
780         SHARED_CONTEXT;
781         svp = hv_fetch((HV*) saggregate, key, len, 0);
782     }
783     CALLER_CONTEXT;
784     if (svp) {
785         /* Exists in the array */
786         if (SvROK(*svp)) {
787             SV *obj = S_sharedsv_new_private(aTHX_ SvRV(*svp));
788             sv_setsv_nomg(sv, &PL_sv_undef);
789             SvRV_set(sv, obj);
790             SvROK_on(sv);
791             SvSETMAGIC(sv);
792         }
793         else {
794             /* XXX can this branch ever happen? DAPM */
795             /* XXX assert("no such branch"); */
796             Perl_sharedsv_associate(aTHX_ sv, *svp);
797             sv_setsv(sv, *svp);
798         }
799     }
800     else {
801         /* Not in the array */
802         sv_setsv(sv, &PL_sv_undef);
803     }
804     LEAVE_LOCK;
805     return 0;
806 }
807
808 /* set magic for PERL_MAGIC_tiedelem(p) */
809
810 int
811 sharedsv_elem_mg_STORE(pTHX_ SV *sv, MAGIC *mg)
812 {
813     dTHXc;
814     SV *saggregate = S_sharedsv_from_obj(aTHX_ mg->mg_obj);
815     SV **svp;
816     /* Theory - SV itself is magically shared - and we have ordered the
817        magic such that by the time we get here it has been stored
818        to its shared counterpart
819      */
820     ENTER_LOCK;
821     assert(saggregate);
822     if (SvTYPE(saggregate) == SVt_PVAV) {
823         assert ( mg->mg_ptr == 0 );
824         SHARED_CONTEXT;
825         svp = av_fetch((AV*) saggregate, mg->mg_len, 1);
826     }
827     else {
828         char *key = mg->mg_ptr;
829         STRLEN len = mg->mg_len;
830         assert ( mg->mg_ptr != 0 );
831         if (mg->mg_len == HEf_SVKEY)
832            key = SvPV((SV *) mg->mg_ptr, len);
833         SHARED_CONTEXT;
834         svp = hv_fetch((HV*) saggregate, key, len, 1);
835     }
836     CALLER_CONTEXT;
837     Perl_sharedsv_associate(aTHX_ sv, *svp);
838     sharedsv_scalar_store(aTHX_ sv, *svp);
839     LEAVE_LOCK;
840     return 0;
841 }
842
843 /* clear magic for PERL_MAGIC_tiedelem(p) */
844
845 int
846 sharedsv_elem_mg_DELETE(pTHX_ SV *sv, MAGIC *mg)
847 {
848     dTHXc;
849     MAGIC *shmg;
850     SV *saggregate = S_sharedsv_from_obj(aTHX_ mg->mg_obj);
851     ENTER_LOCK;
852     sharedsv_elem_mg_FETCH(aTHX_ sv, mg);
853     if ((shmg = mg_find(sv, PERL_MAGIC_shared_scalar)))
854         sharedsv_scalar_mg_get(aTHX_ sv, shmg);
855     if (SvTYPE(saggregate) == SVt_PVAV) {
856         SHARED_CONTEXT;
857         av_delete((AV*) saggregate, mg->mg_len, G_DISCARD);
858     }
859     else {
860         char *key = mg->mg_ptr;
861         STRLEN len = mg->mg_len;
862         assert ( mg->mg_ptr != 0 );
863         if (mg->mg_len == HEf_SVKEY)
864            key = SvPV((SV *) mg->mg_ptr, len);
865         SHARED_CONTEXT;
866         hv_delete((HV*) saggregate, key, len, G_DISCARD);
867     }
868     CALLER_CONTEXT;
869     LEAVE_LOCK;
870     return 0;
871 }
872
873 /* Called during cloning of PERL_MAGIC_tiedelem(p) magic in new
874  * thread */
875
876 int
877 sharedsv_elem_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
878 {
879     SvREFCNT_inc(S_sharedsv_from_obj(aTHX_ mg->mg_obj));
880     assert(mg->mg_flags & MGf_DUP);
881     return 0;
882 }
883
884 MGVTBL sharedsv_elem_vtbl = {
885  sharedsv_elem_mg_FETCH,        /* get */
886  sharedsv_elem_mg_STORE,        /* set */
887  0,                             /* len */
888  sharedsv_elem_mg_DELETE,       /* clear */
889  0,                             /* free */
890  0,                             /* copy */
891  sharedsv_elem_mg_dup,          /* dup */
892  0                              /* local */
893 };
894
895 /* ------------ PERL_MAGIC_tied(P) functions -------------- */
896
897 /* len magic for PERL_MAGIC_tied(P) */
898
899 U32
900 sharedsv_array_mg_FETCHSIZE(pTHX_ SV *sv, MAGIC *mg)
901 {
902     dTHXc;
903     SV *ssv = (SV *) mg->mg_ptr;
904     U32 val;
905     SHARED_EDIT;
906     if (SvTYPE(ssv) == SVt_PVAV) {
907         val = av_len((AV*) ssv);
908     }
909     else {
910         /* not actually defined by tie API but ... */
911         val = HvKEYS((HV*) ssv);
912     }
913     SHARED_RELEASE;
914     return val;
915 }
916
917 /* clear magic for PERL_MAGIC_tied(P) */
918
919 int
920 sharedsv_array_mg_CLEAR(pTHX_ SV *sv, MAGIC *mg)
921 {
922     dTHXc;
923     SV *ssv = (SV *) mg->mg_ptr;
924     SHARED_EDIT;
925     if (SvTYPE(ssv) == SVt_PVAV) {
926         av_clear((AV*) ssv);
927     }
928     else {
929         hv_clear((HV*) ssv);
930     }
931     SHARED_RELEASE;
932     return 0;
933 }
934
935 /* free magic for PERL_MAGIC_tied(P) */
936
937 int
938 sharedsv_array_mg_free(pTHX_ SV *sv, MAGIC *mg)
939 {
940     S_sharedsv_dec(aTHX_ (SV*)mg->mg_ptr);
941     return 0;
942 }
943
944 /*
945  * copy magic for PERL_MAGIC_tied(P)
946  * This is called when perl is about to access an element of
947  * the array -
948  */
949 int
950 sharedsv_array_mg_copy(pTHX_ SV *sv, MAGIC* mg,
951                        SV *nsv, const char *name, int namlen)
952 {
953     MAGIC *nmg = sv_magicext(nsv,mg->mg_obj,
954                             toLOWER(mg->mg_type),&sharedsv_elem_vtbl,
955                             name, namlen);
956     nmg->mg_flags |= MGf_DUP;
957     return 1;
958 }
959
960 /* Called during cloning of PERL_MAGIC_tied(P) magic in new thread */
961
962 int
963 sharedsv_array_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
964 {
965     SvREFCNT_inc((SV*)mg->mg_ptr);
966     assert(mg->mg_flags & MGf_DUP);
967     return 0;
968 }
969
970 MGVTBL sharedsv_array_vtbl = {
971  0,                             /* get */
972  0,                             /* set */
973  sharedsv_array_mg_FETCHSIZE,   /* len */
974  sharedsv_array_mg_CLEAR,       /* clear */
975  sharedsv_array_mg_free,        /* free */
976  sharedsv_array_mg_copy,        /* copy */
977  sharedsv_array_mg_dup,         /* dup */
978  0                              /* local */
979 };
980
981 =for apidoc sharedsv_unlock
982
983 Recursively unlocks a shared sv.
984
985 =cut
986
987 void
988 Perl_sharedsv_unlock(pTHX_ SV *ssv)
989 {
990     user_lock *ul = S_get_userlock(aTHX_ ssv, 0);
991     assert(ul);
992     recursive_lock_release(aTHX_ &ul->lock);
993 }
994
995 =for apidoc sharedsv_lock
996
997 Recursive locks on a sharedsv.
998 Locks are dynamically scoped at the level of the first lock.
999
1000 =cut
1001
1002 void
1003 Perl_sharedsv_lock(pTHX_ SV *ssv)
1004 {
1005     user_lock *ul;
1006     if (!ssv)
1007         return;
1008     ul = S_get_userlock(aTHX_ ssv, 1);
1009     recursive_lock_acquire(aTHX_ &ul->lock, __FILE__, __LINE__);
1010 }
1011
1012 /* handles calls from lock() builtin via PL_lockhook */
1013
1014 void
1015 Perl_sharedsv_locksv(pTHX_ SV *sv)
1016 {
1017     SV *ssv;
1018
1019     if(SvROK(sv))
1020         sv = SvRV(sv);
1021     ssv = Perl_sharedsv_find(aTHX_ sv);
1022     if(!ssv)
1023        croak("lock can only be used on shared values");
1024     Perl_sharedsv_lock(aTHX_ ssv);
1025 }
1026
1027 =head1 Shared SV Functions
1028
1029 =for apidoc sharedsv_init
1030
1031 Saves a space for keeping SVs wider than an interpreter,
1032
1033 =cut
1034
1035 void
1036 Perl_sharedsv_init(pTHX)
1037 {
1038   dTHXc;
1039   /* This pair leaves us in shared context ... */
1040   PL_sharedsv_space = perl_alloc();
1041   perl_construct(PL_sharedsv_space);
1042   CALLER_CONTEXT;
1043   recursive_lock_init(aTHX_ &PL_sharedsv_lock);
1044   PL_lockhook = &Perl_sharedsv_locksv;
1045   PL_sharehook = &Perl_sharedsv_share;
1046 }
1047
1048 #endif /* USE_ITHREADS */
1049
1050 MODULE = threads::shared        PACKAGE = threads::shared::tie
1051
1052 PROTOTYPES: DISABLE
1053
1054 #ifdef USE_ITHREADS
1055
1056 void
1057 PUSH(SV *obj, ...)
1058 CODE:
1059         dTHXc;
1060         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1061         int i;
1062         for(i = 1; i < items; i++) {
1063             SV* tmp = newSVsv(ST(i));
1064             SV *stmp;
1065             ENTER_LOCK;
1066             stmp = S_sharedsv_new_shared(aTHX_ tmp);
1067             sharedsv_scalar_store(aTHX_ tmp, stmp);
1068             SHARED_CONTEXT;
1069             av_push((AV*) sobj, stmp);
1070             SvREFCNT_inc(stmp);
1071             SHARED_RELEASE;
1072             SvREFCNT_dec(tmp);
1073         }
1074
1075 void
1076 UNSHIFT(SV *obj, ...)
1077 CODE:
1078         dTHXc;
1079         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1080         int i;
1081         ENTER_LOCK;
1082         SHARED_CONTEXT;
1083         av_unshift((AV*)sobj, items - 1);
1084         CALLER_CONTEXT;
1085         for(i = 1; i < items; i++) {
1086             SV *tmp = newSVsv(ST(i));
1087             SV *stmp = S_sharedsv_new_shared(aTHX_ tmp);
1088             sharedsv_scalar_store(aTHX_ tmp, stmp);
1089             SHARED_CONTEXT;
1090             av_store((AV*) sobj, i - 1, stmp);
1091             SvREFCNT_inc(stmp);
1092             CALLER_CONTEXT;
1093             SvREFCNT_dec(tmp);
1094         }
1095         LEAVE_LOCK;
1096
1097 void
1098 POP(SV *obj)
1099 CODE:
1100         dTHXc;
1101         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1102         SV* ssv;
1103         ENTER_LOCK;
1104         SHARED_CONTEXT;
1105         ssv = av_pop((AV*)sobj);
1106         CALLER_CONTEXT;
1107         ST(0) = sv_newmortal();
1108         Perl_sharedsv_associate(aTHX_ ST(0), ssv);
1109         SvREFCNT_dec(ssv);
1110         LEAVE_LOCK;
1111         XSRETURN(1);
1112
1113 void
1114 SHIFT(SV *obj)
1115 CODE:
1116         dTHXc;
1117         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1118         SV* ssv;
1119         ENTER_LOCK;
1120         SHARED_CONTEXT;
1121         ssv = av_shift((AV*)sobj);
1122         CALLER_CONTEXT;
1123         ST(0) = sv_newmortal();
1124         Perl_sharedsv_associate(aTHX_ ST(0), ssv);
1125         SvREFCNT_dec(ssv);
1126         LEAVE_LOCK;
1127         XSRETURN(1);
1128
1129 void
1130 EXTEND(SV *obj, IV count)
1131 CODE:
1132         dTHXc;
1133         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1134         SHARED_EDIT;
1135         av_extend((AV*)sobj, count);
1136         SHARED_RELEASE;
1137
1138 void
1139 STORESIZE(SV *obj,IV count)
1140 CODE:
1141         dTHXc;
1142         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1143         SHARED_EDIT;
1144         av_fill((AV*) sobj, count);
1145         SHARED_RELEASE;
1146
1147
1148
1149
1150 void
1151 EXISTS(SV *obj, SV *index)
1152 CODE:
1153         dTHXc;
1154         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1155         bool exists;
1156         if (SvTYPE(sobj) == SVt_PVAV) {
1157             SHARED_EDIT;
1158             exists = av_exists((AV*) sobj, SvIV(index));
1159         }
1160         else {
1161             STRLEN len;
1162             char *key = SvPV(index,len);
1163             SHARED_EDIT;
1164             exists = hv_exists((HV*) sobj, key, len);
1165         }
1166         SHARED_RELEASE;
1167         ST(0) = (exists) ? &PL_sv_yes : &PL_sv_no;
1168         XSRETURN(1);
1169
1170
1171 void
1172 FIRSTKEY(SV *obj)
1173 CODE:
1174         dTHXc;
1175         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1176         char* key = NULL;
1177         I32 len = 0;
1178         HE* entry;
1179         ENTER_LOCK;
1180         SHARED_CONTEXT;
1181         hv_iterinit((HV*) sobj);
1182         entry = hv_iternext((HV*) sobj);
1183         if (entry) {
1184                 key = hv_iterkey(entry,&len);
1185                 CALLER_CONTEXT;
1186                 ST(0) = sv_2mortal(newSVpv(key, len));
1187         } else {
1188              CALLER_CONTEXT;
1189              ST(0) = &PL_sv_undef;
1190         }
1191         LEAVE_LOCK;
1192         XSRETURN(1);
1193
1194 void
1195 NEXTKEY(SV *obj, SV *oldkey)
1196 CODE:
1197         dTHXc;
1198         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1199         char* key = NULL;
1200         I32 len = 0;
1201         HE* entry;
1202         ENTER_LOCK;
1203         SHARED_CONTEXT;
1204         entry = hv_iternext((HV*) sobj);
1205         if (entry) {
1206                 key = hv_iterkey(entry,&len);
1207                 CALLER_CONTEXT;
1208                 ST(0) = sv_2mortal(newSVpv(key, len));
1209         } else {
1210              CALLER_CONTEXT;
1211              ST(0) = &PL_sv_undef;
1212         }
1213         LEAVE_LOCK;
1214         XSRETURN(1);
1215
1216 MODULE = threads::shared                PACKAGE = threads::shared
1217
1218 PROTOTYPES: ENABLE
1219
1220 void
1221 _id(SV *ref)
1222         PROTOTYPE: \[$@%]
1223 CODE:
1224         SV *ssv;
1225         ref = SvRV(ref);
1226         if(SvROK(ref))
1227             ref = SvRV(ref);
1228         if( (ssv = Perl_sharedsv_find(aTHX_ ref)) ){
1229             ST(0) = sv_2mortal(newSViv(PTR2IV(ssv)));
1230             XSRETURN(1);
1231         }
1232         XSRETURN_UNDEF;
1233
1234
1235 void
1236 _refcnt(SV *ref)
1237         PROTOTYPE: \[$@%]
1238 CODE:
1239         SV *ssv;
1240         ref = SvRV(ref);
1241         if(SvROK(ref))
1242             ref = SvRV(ref);
1243         if( (ssv = Perl_sharedsv_find(aTHX_ ref)) ) {
1244             ST(0) = sv_2mortal(newSViv(SvREFCNT(ssv)));
1245             XSRETURN(1);
1246         }
1247         else {
1248              Perl_warn(aTHX_ "%" SVf " is not shared",ST(0));
1249         }
1250         XSRETURN_UNDEF;
1251
1252 SV*
1253 share(SV *ref)
1254         PROTOTYPE: \[$@%]
1255         CODE:
1256         if(!SvROK(ref))
1257             Perl_croak(aTHX_ "Argument to share needs to be passed as ref");
1258         ref = SvRV(ref);
1259         if(SvROK(ref))
1260             ref = SvRV(ref);
1261         Perl_sharedsv_share(aTHX_ ref);
1262         RETVAL = newRV(ref);
1263         OUTPUT:
1264         RETVAL
1265
1266 void
1267 lock_enabled(SV *ref)
1268         PROTOTYPE: \[$@%]
1269         CODE:
1270         SV *ssv;
1271         if(!SvROK(ref))
1272             Perl_croak(aTHX_ "Argument to lock needs to be passed as ref");
1273         ref = SvRV(ref);
1274         if(SvROK(ref))
1275             ref = SvRV(ref);
1276         ssv = Perl_sharedsv_find(aTHX_ ref);
1277         if(!ssv)
1278            croak("lock can only be used on shared values");
1279         Perl_sharedsv_lock(aTHX_ ssv);
1280
1281 void
1282 cond_wait_enabled(SV *ref_cond, SV *ref_lock = 0)
1283         PROTOTYPE: \[$@%];\[$@%]
1284         PREINIT:
1285         SV *ssv;
1286         perl_cond* user_condition;
1287         int locks;
1288         int same = 0;
1289         user_lock *ul;
1290
1291         CODE:
1292         if (!ref_lock || ref_lock == ref_cond) same = 1;
1293
1294         if(!SvROK(ref_cond))
1295             Perl_croak(aTHX_ "Argument to cond_wait needs to be passed as ref");
1296         ref_cond = SvRV(ref_cond);
1297         if(SvROK(ref_cond))
1298             ref_cond = SvRV(ref_cond);
1299         ssv = Perl_sharedsv_find(aTHX_ ref_cond);
1300         if(!ssv)
1301             croak("cond_wait can only be used on shared values");
1302         ul = S_get_userlock(aTHX_ ssv, 1);
1303
1304         user_condition = &ul->user_cond;
1305         if (! same) {
1306             if (!SvROK(ref_lock))
1307                 Perl_croak(aTHX_ "cond_wait lock needs to be passed as ref");
1308             ref_lock = SvRV(ref_lock);
1309             if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
1310             ssv = Perl_sharedsv_find(aTHX_ ref_lock);
1311             if (!ssv)
1312                 croak("cond_wait lock must be a shared value");
1313             ul = S_get_userlock(aTHX_ ssv, 1);
1314         }
1315         if(ul->lock.owner != aTHX)
1316             croak("You need a lock before you can cond_wait");
1317         /* Stealing the members of the lock object worries me - NI-S */
1318         MUTEX_LOCK(&ul->lock.mutex);
1319         ul->lock.owner = NULL;
1320         locks = ul->lock.locks;
1321         ul->lock.locks = 0;
1322
1323         /* since we are releasing the lock here we need to tell other
1324         people that is ok to go ahead and use it */
1325         COND_SIGNAL(&ul->lock.cond);
1326         COND_WAIT(user_condition, &ul->lock.mutex);
1327         while(ul->lock.owner != NULL) {
1328             /* OK -- must reacquire the lock */
1329             COND_WAIT(&ul->lock.cond, &ul->lock.mutex);
1330         }
1331         ul->lock.owner = aTHX;
1332         ul->lock.locks = locks;
1333         MUTEX_UNLOCK(&ul->lock.mutex);
1334
1335 int
1336 cond_timedwait_enabled(SV *ref_cond, double abs, SV *ref_lock = 0)
1337         PROTOTYPE: \[$@%]$;\[$@%]
1338         PREINIT:
1339         SV *ssv;
1340         perl_cond* user_condition;
1341         int locks;
1342         int same = 0;
1343         user_lock *ul;
1344
1345         CODE:
1346         if (!ref_lock || ref_cond == ref_lock) same = 1;
1347
1348         if(!SvROK(ref_cond))
1349             Perl_croak(aTHX_ "Argument to cond_timedwait needs to be passed as ref");
1350         ref_cond = SvRV(ref_cond);
1351         if(SvROK(ref_cond))
1352             ref_cond = SvRV(ref_cond);
1353         ssv = Perl_sharedsv_find(aTHX_ ref_cond);
1354         if(!ssv)
1355             croak("cond_timedwait can only be used on shared values");
1356         ul = S_get_userlock(aTHX_ ssv, 1);
1357     
1358         user_condition = &ul->user_cond;
1359         if (! same) {
1360             if (!SvROK(ref_lock))
1361                 Perl_croak(aTHX_ "cond_timedwait lock needs to be passed as ref");
1362             ref_lock = SvRV(ref_lock);
1363             if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
1364             ssv = Perl_sharedsv_find(aTHX_ ref_lock);
1365             if (!ssv)
1366                 croak("cond_timedwait lock must be a shared value");
1367             ul = S_get_userlock(aTHX_ ssv, 1);
1368         }
1369         if(ul->lock.owner != aTHX)
1370             croak("You need a lock before you can cond_wait");
1371
1372         MUTEX_LOCK(&ul->lock.mutex);
1373         ul->lock.owner = NULL;
1374         locks = ul->lock.locks;
1375         ul->lock.locks = 0;
1376         /* since we are releasing the lock here we need to tell other
1377         people that is ok to go ahead and use it */
1378         COND_SIGNAL(&ul->lock.cond);
1379         RETVAL = Perl_sharedsv_cond_timedwait(user_condition, &ul->lock.mutex, abs);
1380         while (ul->lock.owner != NULL) {
1381             /* OK -- must reacquire the lock... */
1382             COND_WAIT(&ul->lock.cond, &ul->lock.mutex);
1383         }
1384         ul->lock.owner = aTHX;
1385         ul->lock.locks = locks;
1386         MUTEX_UNLOCK(&ul->lock.mutex);
1387
1388         if (RETVAL == 0)
1389             XSRETURN_UNDEF;
1390         OUTPUT:
1391         RETVAL
1392
1393 void
1394 cond_signal_enabled(SV *ref)
1395         PROTOTYPE: \[$@%]
1396         CODE:
1397         SV *ssv;
1398         user_lock *ul;
1399
1400         if(!SvROK(ref))
1401             Perl_croak(aTHX_ "Argument to cond_signal needs to be passed as ref");
1402         ref = SvRV(ref);
1403         if(SvROK(ref))
1404             ref = SvRV(ref);
1405         ssv = Perl_sharedsv_find(aTHX_ ref);
1406         if(!ssv)
1407             croak("cond_signal can only be used on shared values");
1408         ul = S_get_userlock(aTHX_ ssv, 1);
1409         if (ckWARN(WARN_THREADS) && ul->lock.owner != aTHX)
1410             Perl_warner(aTHX_ packWARN(WARN_THREADS),
1411                             "cond_signal() called on unlocked variable");
1412         COND_SIGNAL(&ul->user_cond);
1413
1414 void
1415 cond_broadcast_enabled(SV *ref)
1416         PROTOTYPE: \[$@%]
1417         CODE:
1418         SV *ssv;
1419         user_lock *ul;
1420
1421         if(!SvROK(ref))
1422             Perl_croak(aTHX_ "Argument to cond_broadcast needs to be passed as ref");
1423         ref = SvRV(ref);
1424         if(SvROK(ref))
1425             ref = SvRV(ref);
1426         ssv = Perl_sharedsv_find(aTHX_ ref);
1427         if(!ssv)
1428             croak("cond_broadcast can only be used on shared values");
1429         ul = S_get_userlock(aTHX_ ssv, 1);
1430         if (ckWARN(WARN_THREADS) && ul->lock.owner != aTHX)
1431             Perl_warner(aTHX_ packWARN(WARN_THREADS),
1432                             "cond_broadcast() called on unlocked variable");
1433         COND_BROADCAST(&ul->user_cond);
1434
1435
1436 SV*
1437 bless(SV* ref, ...);
1438         PROTOTYPE: $;$
1439         CODE:
1440         {
1441           HV* stash;
1442           SV *ssv;
1443           if (items == 1)
1444             stash = CopSTASH(PL_curcop);
1445           else {
1446             SV* classname = ST(1);
1447             STRLEN len;
1448             char *ptr;
1449             
1450             if (classname && !SvGMAGICAL(classname) &&
1451                         !SvAMAGIC(classname) && SvROK(classname))
1452               Perl_croak(aTHX_ "Attempt to bless into a reference");
1453             ptr = SvPV(classname,len);
1454             if (ckWARN(WARN_MISC) && len == 0)
1455               Perl_warner(aTHX_ packWARN(WARN_MISC),
1456                           "Explicit blessing to '' (assuming package main)");
1457             stash = gv_stashpvn(ptr, len, TRUE);
1458           }
1459           SvREFCNT_inc(ref);
1460           (void)sv_bless(ref, stash);
1461           RETVAL = ref;
1462           ssv = Perl_sharedsv_find(aTHX_ ref);
1463           if(ssv) {
1464             dTHXc;
1465             ENTER_LOCK;
1466             SHARED_CONTEXT;
1467             {
1468               SV* fake_stash = newSVpv(HvNAME_get(stash),0);
1469               (void)sv_bless(ssv,(HV*)fake_stash);
1470             }
1471             CALLER_CONTEXT;
1472             LEAVE_LOCK;
1473           }
1474         }
1475         OUTPUT:
1476         RETVAL          
1477
1478 #endif /* USE_ITHREADS */
1479
1480 BOOT:
1481 {
1482 #ifdef USE_ITHREADS
1483      Perl_sharedsv_init(aTHX);
1484 #endif /* USE_ITHREADS */
1485 }