53b9e2d8c70e73fbf8ca9306bf3cc9692e3733fd
[p5sagit/p5-mst-13.2.git] / ext / threads / shared / shared.xs
1 /*    shared.xs
2  *
3  *    Copyright (c) 2001-2002, 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_COPY|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 /* free magic for PERL_MAGIC_tiedelem(p) */
874
875 int
876 sharedsv_elem_mg_free(pTHX_ SV *sv, MAGIC *mg)
877 {
878     S_sharedsv_dec(aTHX_ S_sharedsv_from_obj(aTHX_ mg->mg_obj));
879     return 0;
880 }
881
882 /* Called during cloning of PERL_MAGIC_tiedelem(p) magic in new
883  * thread */
884
885 int
886 sharedsv_elem_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
887 {
888     SvREFCNT_inc(S_sharedsv_from_obj(aTHX_ mg->mg_obj));
889     assert(mg->mg_flags & MGf_DUP);
890     return 0;
891 }
892
893 MGVTBL sharedsv_elem_vtbl = {
894  sharedsv_elem_mg_FETCH,        /* get */
895  sharedsv_elem_mg_STORE,        /* set */
896  0,                             /* len */
897  sharedsv_elem_mg_DELETE,       /* clear */
898  sharedsv_elem_mg_free,         /* free */
899  0,                             /* copy */
900  sharedsv_elem_mg_dup,          /* dup */
901  0                              /* local */
902 };
903
904 /* ------------ PERL_MAGIC_tied(P) functions -------------- */
905
906 /* len magic for PERL_MAGIC_tied(P) */
907
908 U32
909 sharedsv_array_mg_FETCHSIZE(pTHX_ SV *sv, MAGIC *mg)
910 {
911     dTHXc;
912     SV *ssv = (SV *) mg->mg_ptr;
913     U32 val;
914     SHARED_EDIT;
915     if (SvTYPE(ssv) == SVt_PVAV) {
916         val = av_len((AV*) ssv);
917     }
918     else {
919         /* not actually defined by tie API but ... */
920         val = HvKEYS((HV*) ssv);
921     }
922     SHARED_RELEASE;
923     return val;
924 }
925
926 /* clear magic for PERL_MAGIC_tied(P) */
927
928 int
929 sharedsv_array_mg_CLEAR(pTHX_ SV *sv, MAGIC *mg)
930 {
931     dTHXc;
932     SV *ssv = (SV *) mg->mg_ptr;
933     SHARED_EDIT;
934     if (SvTYPE(ssv) == SVt_PVAV) {
935         av_clear((AV*) ssv);
936     }
937     else {
938         hv_clear((HV*) ssv);
939     }
940     SHARED_RELEASE;
941     return 0;
942 }
943
944 /* free magic for PERL_MAGIC_tied(P) */
945
946 int
947 sharedsv_array_mg_free(pTHX_ SV *sv, MAGIC *mg)
948 {
949     S_sharedsv_dec(aTHX_ (SV*)mg->mg_ptr);
950     return 0;
951 }
952
953 /*
954  * copy magic for PERL_MAGIC_tied(P)
955  * This is called when perl is about to access an element of
956  * the array -
957  */
958 int
959 sharedsv_array_mg_copy(pTHX_ SV *sv, MAGIC* mg,
960                        SV *nsv, const char *name, int namlen)
961 {
962     MAGIC *nmg = sv_magicext(nsv,mg->mg_obj,
963                             toLOWER(mg->mg_type),&sharedsv_elem_vtbl,
964                             name, namlen);
965     ENTER_LOCK;
966     SvREFCNT_inc((SV*)mg->mg_ptr);
967     LEAVE_LOCK;
968     nmg->mg_flags |= MGf_DUP;
969     return 1;
970 }
971
972 /* Called during cloning of PERL_MAGIC_tied(P) magic in new thread */
973
974 int
975 sharedsv_array_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
976 {
977     SvREFCNT_inc((SV*)mg->mg_ptr);
978     assert(mg->mg_flags & MGf_DUP);
979     return 0;
980 }
981
982 MGVTBL sharedsv_array_vtbl = {
983  0,                             /* get */
984  0,                             /* set */
985  sharedsv_array_mg_FETCHSIZE,   /* len */
986  sharedsv_array_mg_CLEAR,       /* clear */
987  sharedsv_array_mg_free,        /* free */
988  sharedsv_array_mg_copy,        /* copy */
989  sharedsv_array_mg_dup,         /* dup */
990  0                              /* local */
991 };
992
993 =for apidoc sharedsv_unlock
994
995 Recursively unlocks a shared sv.
996
997 =cut
998
999 void
1000 Perl_sharedsv_unlock(pTHX_ SV *ssv)
1001 {
1002     user_lock *ul = S_get_userlock(aTHX_ ssv, 0);
1003     assert(ul);
1004     recursive_lock_release(aTHX_ &ul->lock);
1005 }
1006
1007 =for apidoc sharedsv_lock
1008
1009 Recursive locks on a sharedsv.
1010 Locks are dynamically scoped at the level of the first lock.
1011
1012 =cut
1013
1014 void
1015 Perl_sharedsv_lock(pTHX_ SV *ssv)
1016 {
1017     user_lock *ul;
1018     if (!ssv)
1019         return;
1020     ul = S_get_userlock(aTHX_ ssv, 1);
1021     recursive_lock_acquire(aTHX_ &ul->lock, __FILE__, __LINE__);
1022 }
1023
1024 /* handles calls from lock() builtin via PL_lockhook */
1025
1026 void
1027 Perl_sharedsv_locksv(pTHX_ SV *sv)
1028 {
1029     SV *ssv;
1030
1031     if(SvROK(sv))
1032         sv = SvRV(sv);
1033     ssv = Perl_sharedsv_find(aTHX_ sv);
1034     if(!ssv)
1035        croak("lock can only be used on shared values");
1036     Perl_sharedsv_lock(aTHX_ ssv);
1037 }
1038
1039 =head1 Shared SV Functions
1040
1041 =for apidoc sharedsv_init
1042
1043 Saves a space for keeping SVs wider than an interpreter,
1044
1045 =cut
1046
1047 void
1048 Perl_sharedsv_init(pTHX)
1049 {
1050   dTHXc;
1051   /* This pair leaves us in shared context ... */
1052   PL_sharedsv_space = perl_alloc();
1053   perl_construct(PL_sharedsv_space);
1054   CALLER_CONTEXT;
1055   recursive_lock_init(aTHX_ &PL_sharedsv_lock);
1056   PL_lockhook = &Perl_sharedsv_locksv;
1057   PL_sharehook = &Perl_sharedsv_share;
1058 }
1059
1060 #endif /* USE_ITHREADS */
1061
1062 MODULE = threads::shared        PACKAGE = threads::shared::tie
1063
1064 PROTOTYPES: DISABLE
1065
1066 #ifdef USE_ITHREADS
1067
1068 void
1069 PUSH(SV *obj, ...)
1070 CODE:
1071         dTHXc;
1072         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1073         int i;
1074         for(i = 1; i < items; i++) {
1075             SV* tmp = newSVsv(ST(i));
1076             SV *stmp;
1077             ENTER_LOCK;
1078             stmp = S_sharedsv_new_shared(aTHX_ tmp);
1079             sharedsv_scalar_store(aTHX_ tmp, stmp);
1080             SHARED_CONTEXT;
1081             av_push((AV*) sobj, stmp);
1082             SvREFCNT_inc(stmp);
1083             SHARED_RELEASE;
1084             SvREFCNT_dec(tmp);
1085         }
1086
1087 void
1088 UNSHIFT(SV *obj, ...)
1089 CODE:
1090         dTHXc;
1091         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1092         int i;
1093         ENTER_LOCK;
1094         SHARED_CONTEXT;
1095         av_unshift((AV*)sobj, items - 1);
1096         CALLER_CONTEXT;
1097         for(i = 1; i < items; i++) {
1098             SV *tmp = newSVsv(ST(i));
1099             SV *stmp = S_sharedsv_new_shared(aTHX_ tmp);
1100             sharedsv_scalar_store(aTHX_ tmp, stmp);
1101             SHARED_CONTEXT;
1102             av_store((AV*) sobj, i - 1, stmp);
1103             SvREFCNT_inc(stmp);
1104             CALLER_CONTEXT;
1105             SvREFCNT_dec(tmp);
1106         }
1107         LEAVE_LOCK;
1108
1109 void
1110 POP(SV *obj)
1111 CODE:
1112         dTHXc;
1113         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1114         SV* ssv;
1115         ENTER_LOCK;
1116         SHARED_CONTEXT;
1117         ssv = av_pop((AV*)sobj);
1118         CALLER_CONTEXT;
1119         ST(0) = sv_newmortal();
1120         Perl_sharedsv_associate(aTHX_ ST(0), ssv);
1121         SvREFCNT_dec(ssv);
1122         LEAVE_LOCK;
1123         XSRETURN(1);
1124
1125 void
1126 SHIFT(SV *obj)
1127 CODE:
1128         dTHXc;
1129         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1130         SV* ssv;
1131         ENTER_LOCK;
1132         SHARED_CONTEXT;
1133         ssv = av_shift((AV*)sobj);
1134         CALLER_CONTEXT;
1135         ST(0) = sv_newmortal();
1136         Perl_sharedsv_associate(aTHX_ ST(0), ssv);
1137         SvREFCNT_dec(ssv);
1138         LEAVE_LOCK;
1139         XSRETURN(1);
1140
1141 void
1142 EXTEND(SV *obj, IV count)
1143 CODE:
1144         dTHXc;
1145         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1146         SHARED_EDIT;
1147         av_extend((AV*)sobj, count);
1148         SHARED_RELEASE;
1149
1150 void
1151 STORESIZE(SV *obj,IV count)
1152 CODE:
1153         dTHXc;
1154         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1155         SHARED_EDIT;
1156         av_fill((AV*) sobj, count);
1157         SHARED_RELEASE;
1158
1159
1160
1161
1162 void
1163 EXISTS(SV *obj, SV *index)
1164 CODE:
1165         dTHXc;
1166         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1167         bool exists;
1168         if (SvTYPE(sobj) == SVt_PVAV) {
1169             SHARED_EDIT;
1170             exists = av_exists((AV*) sobj, SvIV(index));
1171         }
1172         else {
1173             STRLEN len;
1174             char *key = SvPV(index,len);
1175             SHARED_EDIT;
1176             exists = hv_exists((HV*) sobj, key, len);
1177         }
1178         SHARED_RELEASE;
1179         ST(0) = (exists) ? &PL_sv_yes : &PL_sv_no;
1180         XSRETURN(1);
1181
1182
1183 void
1184 FIRSTKEY(SV *obj)
1185 CODE:
1186         dTHXc;
1187         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1188         char* key = NULL;
1189         I32 len = 0;
1190         HE* entry;
1191         ENTER_LOCK;
1192         SHARED_CONTEXT;
1193         hv_iterinit((HV*) sobj);
1194         entry = hv_iternext((HV*) sobj);
1195         if (entry) {
1196                 key = hv_iterkey(entry,&len);
1197                 CALLER_CONTEXT;
1198                 ST(0) = sv_2mortal(newSVpv(key, len));
1199         } else {
1200              CALLER_CONTEXT;
1201              ST(0) = &PL_sv_undef;
1202         }
1203         LEAVE_LOCK;
1204         XSRETURN(1);
1205
1206 void
1207 NEXTKEY(SV *obj, SV *oldkey)
1208 CODE:
1209         dTHXc;
1210         SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1211         char* key = NULL;
1212         I32 len = 0;
1213         HE* entry;
1214         ENTER_LOCK;
1215         SHARED_CONTEXT;
1216         entry = hv_iternext((HV*) sobj);
1217         if (entry) {
1218                 key = hv_iterkey(entry,&len);
1219                 CALLER_CONTEXT;
1220                 ST(0) = sv_2mortal(newSVpv(key, len));
1221         } else {
1222              CALLER_CONTEXT;
1223              ST(0) = &PL_sv_undef;
1224         }
1225         LEAVE_LOCK;
1226         XSRETURN(1);
1227
1228 MODULE = threads::shared                PACKAGE = threads::shared
1229
1230 PROTOTYPES: ENABLE
1231
1232 void
1233 _id(SV *ref)
1234         PROTOTYPE: \[$@%]
1235 CODE:
1236         SV *ssv;
1237         ref = SvRV(ref);
1238         if(SvROK(ref))
1239             ref = SvRV(ref);
1240         if( (ssv = Perl_sharedsv_find(aTHX_ ref)) ){
1241             ST(0) = sv_2mortal(newSViv(PTR2IV(ssv)));
1242             XSRETURN(1);
1243         }
1244         XSRETURN_UNDEF;
1245
1246
1247 void
1248 _refcnt(SV *ref)
1249         PROTOTYPE: \[$@%]
1250 CODE:
1251         SV *ssv;
1252         ref = SvRV(ref);
1253         if(SvROK(ref))
1254             ref = SvRV(ref);
1255         if( (ssv = Perl_sharedsv_find(aTHX_ ref)) ) {
1256             ST(0) = sv_2mortal(newSViv(SvREFCNT(ssv)));
1257             XSRETURN(1);
1258         }
1259         else {
1260              Perl_warn(aTHX_ "%" SVf " is not shared",ST(0));
1261         }
1262         XSRETURN_UNDEF;
1263
1264 SV*
1265 share(SV *ref)
1266         PROTOTYPE: \[$@%]
1267         CODE:
1268         if(!SvROK(ref))
1269             Perl_croak(aTHX_ "Argument to share needs to be passed as ref");
1270         ref = SvRV(ref);
1271         if(SvROK(ref))
1272             ref = SvRV(ref);
1273         Perl_sharedsv_share(aTHX_ ref);
1274         RETVAL = newRV(ref);
1275         OUTPUT:
1276         RETVAL
1277
1278 void
1279 lock_enabled(SV *ref)
1280         PROTOTYPE: \[$@%]
1281         CODE:
1282         SV *ssv;
1283         if(!SvROK(ref))
1284             Perl_croak(aTHX_ "Argument to lock needs to be passed as ref");
1285         ref = SvRV(ref);
1286         if(SvROK(ref))
1287             ref = SvRV(ref);
1288         ssv = Perl_sharedsv_find(aTHX_ ref);
1289         if(!ssv)
1290            croak("lock can only be used on shared values");
1291         Perl_sharedsv_lock(aTHX_ ssv);
1292
1293 void
1294 cond_wait_enabled(SV *ref_cond, SV *ref_lock = 0)
1295         PROTOTYPE: \[$@%];\[$@%]
1296         PREINIT:
1297         SV *ssv;
1298         perl_cond* user_condition;
1299         int locks;
1300         int same = 0;
1301         user_lock *ul;
1302
1303         CODE:
1304         if (!ref_lock || ref_lock == ref_cond) same = 1;
1305
1306         if(!SvROK(ref_cond))
1307             Perl_croak(aTHX_ "Argument to cond_wait needs to be passed as ref");
1308         ref_cond = SvRV(ref_cond);
1309         if(SvROK(ref_cond))
1310             ref_cond = SvRV(ref_cond);
1311         ssv = Perl_sharedsv_find(aTHX_ ref_cond);
1312         if(!ssv)
1313             croak("cond_wait can only be used on shared values");
1314         ul = S_get_userlock(aTHX_ ssv, 1);
1315
1316         user_condition = &ul->user_cond;
1317         if (! same) {
1318             if (!SvROK(ref_lock))
1319                 Perl_croak(aTHX_ "cond_wait lock needs to be passed as ref");
1320             ref_lock = SvRV(ref_lock);
1321             if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
1322             ssv = Perl_sharedsv_find(aTHX_ ref_lock);
1323             if (!ssv)
1324                 croak("cond_wait lock must be a shared value");
1325             ul = S_get_userlock(aTHX_ ssv, 1);
1326         }
1327         if(ul->lock.owner != aTHX)
1328             croak("You need a lock before you can cond_wait");
1329         /* Stealing the members of the lock object worries me - NI-S */
1330         MUTEX_LOCK(&ul->lock.mutex);
1331         ul->lock.owner = NULL;
1332         locks = ul->lock.locks;
1333         ul->lock.locks = 0;
1334
1335         /* since we are releasing the lock here we need to tell other
1336         people that is ok to go ahead and use it */
1337         COND_SIGNAL(&ul->lock.cond);
1338         COND_WAIT(user_condition, &ul->lock.mutex);
1339         while(ul->lock.owner != NULL) {
1340             /* OK -- must reacquire the lock */
1341             COND_WAIT(&ul->lock.cond, &ul->lock.mutex);
1342         }
1343         ul->lock.owner = aTHX;
1344         ul->lock.locks = locks;
1345         MUTEX_UNLOCK(&ul->lock.mutex);
1346
1347 int
1348 cond_timedwait_enabled(SV *ref_cond, double abs, SV *ref_lock = 0)
1349         PROTOTYPE: \[$@%]$;\[$@%]
1350         PREINIT:
1351         SV *ssv;
1352         perl_cond* user_condition;
1353         int locks;
1354         int same = 0;
1355         user_lock *ul;
1356
1357         CODE:
1358         if (!ref_lock || ref_cond == ref_lock) same = 1;
1359
1360         if(!SvROK(ref_cond))
1361             Perl_croak(aTHX_ "Argument to cond_timedwait needs to be passed as ref");
1362         ref_cond = SvRV(ref_cond);
1363         if(SvROK(ref_cond))
1364             ref_cond = SvRV(ref_cond);
1365         ssv = Perl_sharedsv_find(aTHX_ ref_cond);
1366         if(!ssv)
1367             croak("cond_timedwait can only be used on shared values");
1368         ul = S_get_userlock(aTHX_ ssv, 1);
1369     
1370         user_condition = &ul->user_cond;
1371         if (! same) {
1372             if (!SvROK(ref_lock))
1373                 Perl_croak(aTHX_ "cond_timedwait lock needs to be passed as ref");
1374             ref_lock = SvRV(ref_lock);
1375             if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
1376             ssv = Perl_sharedsv_find(aTHX_ ref_lock);
1377             if (!ssv)
1378                 croak("cond_timedwait lock must be a shared value");
1379             ul = S_get_userlock(aTHX_ ssv, 1);
1380         }
1381         if(ul->lock.owner != aTHX)
1382             croak("You need a lock before you can cond_wait");
1383
1384         MUTEX_LOCK(&ul->lock.mutex);
1385         ul->lock.owner = NULL;
1386         locks = ul->lock.locks;
1387         ul->lock.locks = 0;
1388         /* since we are releasing the lock here we need to tell other
1389         people that is ok to go ahead and use it */
1390         COND_SIGNAL(&ul->lock.cond);
1391         RETVAL = Perl_sharedsv_cond_timedwait(user_condition, &ul->lock.mutex, abs);
1392         while (ul->lock.owner != NULL) {
1393             /* OK -- must reacquire the lock... */
1394             COND_WAIT(&ul->lock.cond, &ul->lock.mutex);
1395         }
1396         ul->lock.owner = aTHX;
1397         ul->lock.locks = locks;
1398         MUTEX_UNLOCK(&ul->lock.mutex);
1399
1400         if (RETVAL == 0)
1401             XSRETURN_UNDEF;
1402         OUTPUT:
1403         RETVAL
1404
1405 void
1406 cond_signal_enabled(SV *ref)
1407         PROTOTYPE: \[$@%]
1408         CODE:
1409         SV *ssv;
1410         user_lock *ul;
1411
1412         if(!SvROK(ref))
1413             Perl_croak(aTHX_ "Argument to cond_signal needs to be passed as ref");
1414         ref = SvRV(ref);
1415         if(SvROK(ref))
1416             ref = SvRV(ref);
1417         ssv = Perl_sharedsv_find(aTHX_ ref);
1418         if(!ssv)
1419             croak("cond_signal can only be used on shared values");
1420         ul = S_get_userlock(aTHX_ ssv, 1);
1421         if (ckWARN(WARN_THREADS) && ul->lock.owner != aTHX)
1422             Perl_warner(aTHX_ packWARN(WARN_THREADS),
1423                             "cond_signal() called on unlocked variable");
1424         COND_SIGNAL(&ul->user_cond);
1425
1426 void
1427 cond_broadcast_enabled(SV *ref)
1428         PROTOTYPE: \[$@%]
1429         CODE:
1430         SV *ssv;
1431         user_lock *ul;
1432
1433         if(!SvROK(ref))
1434             Perl_croak(aTHX_ "Argument to cond_broadcast needs to be passed as ref");
1435         ref = SvRV(ref);
1436         if(SvROK(ref))
1437             ref = SvRV(ref);
1438         ssv = Perl_sharedsv_find(aTHX_ ref);
1439         if(!ssv)
1440             croak("cond_broadcast can only be used on shared values");
1441         ul = S_get_userlock(aTHX_ ssv, 1);
1442         if (ckWARN(WARN_THREADS) && ul->lock.owner != aTHX)
1443             Perl_warner(aTHX_ packWARN(WARN_THREADS),
1444                             "cond_broadcast() called on unlocked variable");
1445         COND_BROADCAST(&ul->user_cond);
1446
1447
1448 SV*
1449 bless(SV* ref, ...);
1450         PROTOTYPE: $;$
1451         CODE:
1452         {
1453           HV* stash;
1454           SV *ssv;
1455           if (items == 1)
1456             stash = CopSTASH(PL_curcop);
1457           else {
1458             SV* classname = ST(1);
1459             STRLEN len;
1460             char *ptr;
1461             
1462             if (classname && !SvGMAGICAL(classname) &&
1463                         !SvAMAGIC(classname) && SvROK(classname))
1464               Perl_croak(aTHX_ "Attempt to bless into a reference");
1465             ptr = SvPV(classname,len);
1466             if (ckWARN(WARN_MISC) && len == 0)
1467               Perl_warner(aTHX_ packWARN(WARN_MISC),
1468                           "Explicit blessing to '' (assuming package main)");
1469             stash = gv_stashpvn(ptr, len, TRUE);
1470           }
1471           SvREFCNT_inc(ref);
1472           (void)sv_bless(ref, stash);
1473           RETVAL = ref;
1474           ssv = Perl_sharedsv_find(aTHX_ ref);
1475           if(ssv) {
1476             dTHXc;
1477             ENTER_LOCK;
1478             SHARED_CONTEXT;
1479             {
1480               SV* fake_stash = newSVpv(HvNAME_get(stash),0);
1481               (void)sv_bless(ssv,(HV*)fake_stash);
1482             }
1483             CALLER_CONTEXT;
1484             LEAVE_LOCK;
1485           }
1486         }
1487         OUTPUT:
1488         RETVAL          
1489
1490 #endif /* USE_ITHREADS */
1491
1492 BOOT:
1493 {
1494 #ifdef USE_ITHREADS
1495      Perl_sharedsv_init(aTHX);
1496 #endif /* USE_ITHREADS */
1497 }