thread->params = Nullsv;
perl_destruct(interp);
+ perl_free(interp);
thread->interp = NULL;
}
- if (interp)
- perl_free(interp);
PERL_SET_CONTEXT(aTHX);
}
#ifdef WIN32
HANDLE handle;
#endif
-
- MUTEX_LOCK(&thread->mutex);
-
/* Thread is still in use */
if (thread->count != 0) {
- MUTEX_UNLOCK(&thread->mutex);
return;
}
MUTEX_UNLOCK(&create_destruct_mutex);
/* Thread is now disowned */
+ MUTEX_LOCK(&thread->mutex);
S_ithread_clear(aTHX_ thread);
#ifdef WIN32
dJMPENV;
dTHXa(thread->interp);
- PERL_SET_CONTEXT(thread->interp);
- S_ithread_set(aTHX_ thread);
-#if 0
- /* Far from clear messing with ->thr child-side is a good idea */
+ /* Blocked until ->create() call finishes */
MUTEX_LOCK(&thread->mutex);
-#ifdef WIN32
- thread->thr = GetCurrentThreadId();
-#else
- thread->thr = pthread_self();
-#endif
MUTEX_UNLOCK(&thread->mutex);
-#endif
+
+ PERL_SET_CONTEXT(thread->interp);
+ S_ithread_set(aTHX_ thread);
PL_perl_destruct_level = 2;
PerlIO_flush((PerlIO *)NULL);
+ MUTEX_LOCK(&create_destruct_mutex);
MUTEX_LOCK(&thread->mutex);
/* Mark as finished */
thread->state |= PERL_ITHR_FINISHED;
MUTEX_UNLOCK(&thread->mutex);
/* Adjust thread status counts */
- MUTEX_LOCK(&create_destruct_mutex);
if (cleanup) {
detached_threads--;
} else {
SV *sv;
MAGIC *mg;
+ /* If incrementing thread ref count, then call within mutex lock */
if (inc) {
MUTEX_LOCK(&thread->mutex);
thread->count++;
/* threads->create()
* Called in context of parent thread.
+ * Called with create_destruct_mutex locked. (Unlocked on error.)
*/
-static SV *
+static ithread *
S_ithread_create(
- pTHX_ SV *obj,
- char *classname,
- SV *init_function,
+ pTHX_ SV *init_function,
IV stack_size,
int gimme,
int exit_opt,
int rc_thread_create = 0;
#endif
- MUTEX_LOCK(&create_destruct_mutex);
-
/* Allocate thread structure */
thread = (ithread *)PerlMemShared_malloc(sizeof(ithread));
if (!thread) {
*/
thread->count = 1;
+ /* Block new thread until ->create() call finishes */
MUTEX_INIT(&thread->mutex);
+ MUTEX_LOCK(&thread->mutex);
+
thread->tid = tid_counter++;
thread->stack_size = good_stack_size(aTHX_ stack_size);
thread->gimme = gimme;
#else
if (rc_stack_size || rc_thread_create) {
#endif
+ /* Must unlock mutex for destruct call */
MUTEX_UNLOCK(&create_destruct_mutex);
sv_2mortal(params);
S_ithread_destruct(aTHX_ thread);
Perl_warn(aTHX_ "Thread creation failed: pthread_create returned %d", rc_thread_create);
}
#endif
- return (&PL_sv_undef);
+ return (NULL);
}
running_threads++;
- MUTEX_UNLOCK(&create_destruct_mutex);
-
sv_2mortal(params);
-
- return (ithread_to_SV(aTHX_ obj, thread, classname, FALSE));
+ return (thread);
}
#endif /* USE_ITHREADS */
}
/* Create thread */
- ST(0) = sv_2mortal(S_ithread_create(aTHX_ Nullsv,
- classname,
- function_to_call,
- stack_size,
- context,
- exit_opt,
- newRV_noinc((SV*)params)));
+ MUTEX_LOCK(&create_destruct_mutex);
+ thread = S_ithread_create(aTHX_ function_to_call,
+ stack_size,
+ context,
+ exit_opt,
+ newRV_noinc((SV*)params));
+ if (! thread) {
+ XSRETURN_UNDEF; /* Mutex already unlocked */
+ }
+ ST(0) = sv_2mortal(ithread_to_SV(aTHX_ Nullsv, thread, classname, FALSE));
+
+ /* Let thread run */
+ MUTEX_UNLOCK(&thread->mutex);
+ MUTEX_UNLOCK(&create_destruct_mutex);
+
/* XSRETURN(1); - implied */
/* Check if the thread is joinable */
thread = SV_to_ithread(aTHX_ ST(0));
- MUTEX_LOCK(&thread->mutex);
join_err = (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED));
- MUTEX_UNLOCK(&thread->mutex);
if (join_err) {
if (join_err & PERL_ITHR_DETACHED) {
Perl_croak(aTHX_ "Cannot join a detached thread");
MUTEX_UNLOCK(&thread->mutex);
MUTEX_LOCK(&create_destruct_mutex);
- joinable_threads--;
+ if (! (thread->state & PERL_ITHR_DETACHED)) {
+ joinable_threads--;
+ }
MUTEX_UNLOCK(&create_destruct_mutex);
/* If no return values, then just return */
int detach_err;
int cleanup;
CODE:
- thread = SV_to_ithread(aTHX_ ST(0));
- MUTEX_LOCK(&thread->mutex);
-
/* Check if the thread is detachable */
+ thread = SV_to_ithread(aTHX_ ST(0));
if ((detach_err = (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED)))) {
- MUTEX_UNLOCK(&thread->mutex);
if (detach_err & PERL_ITHR_DETACHED) {
Perl_croak(aTHX_ "Thread already detached");
} else {
}
/* Detach the thread */
+ MUTEX_LOCK(&create_destruct_mutex);
+ MUTEX_LOCK(&thread->mutex);
thread->state |= PERL_ITHR_DETACHED;
#ifdef WIN32
/* Windows has no 'detach thread' function */
cleanup = (thread->state & PERL_ITHR_FINISHED);
MUTEX_UNLOCK(&thread->mutex);
- MUTEX_LOCK(&create_destruct_mutex);
if (cleanup) {
joinable_threads--;
} else {
char *classname;
UV tid;
ithread *thread;
- int found = 0;
+ int have_obj = 0;
CODE:
/* Class method only */
if (SvROK(ST(0)))
thread != threads;
thread = thread->next)
{
- /* Look for TID, but ignore detached or joined threads */
- if ((thread->tid != tid) ||
- (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED)))
- {
- continue;
+ /* Look for TID */
+ if (thread->tid == tid) {
+ /* Ignore if detached or joined */
+ if (! (thread->state & (PERL_ITHR_DETACHED|PERL_ITHR_JOINED))) {
+ /* Put object on stack */
+ ST(0) = sv_2mortal(ithread_to_SV(aTHX_ Nullsv, thread, classname, TRUE));
+ have_obj = 1;
+ }
+ break;
}
- /* Put object on stack */
- ST(0) = sv_2mortal(ithread_to_SV(aTHX_ Nullsv, thread, classname, TRUE));
- found = 1;
- break;
}
MUTEX_UNLOCK(&create_destruct_mutex);
- if (! found) {
+
+ if (! have_obj) {
XSRETURN_UNDEF;
}
/* XSRETURN(1); - implied */
Perl_croak(aTHX_ "Usage: $thr->is_running()");
thread = INT2PTR(ithread *, SvIV(SvRV(ST(0))));
- MUTEX_LOCK(&thread->mutex);
ST(0) = (thread->state & PERL_ITHR_FINISHED) ? &PL_sv_no : &PL_sv_yes;
- MUTEX_UNLOCK(&thread->mutex);
/* XSRETURN(1); - implied */
ithread *thread;
CODE:
thread = SV_to_ithread(aTHX_ ST(0));
- MUTEX_LOCK(&thread->mutex);
ST(0) = (thread->state & PERL_ITHR_DETACHED) ? &PL_sv_yes : &PL_sv_no;
- MUTEX_UNLOCK(&thread->mutex);
/* XSRETURN(1); - implied */
ithread *thread;
CODE:
thread = SV_to_ithread(aTHX_ ST(0));
- MUTEX_LOCK(&thread->mutex);
ST(0) = (thread->gimme & G_ARRAY) ? &PL_sv_yes :
(thread->gimme & G_VOID) ? &PL_sv_undef
/* G_SCALAR */ : &PL_sv_no;
- MUTEX_UNLOCK(&thread->mutex);
/* XSRETURN(1); - implied */