#ifndef sv_dup_inc
# define sv_dup_inc(s,t) SvREFCNT_inc(sv_dup(s,t))
#endif
+#ifndef PERL_UNUSED_RESULT
+# if defined(__GNUC__) && defined(HASATTRIBUTE_WARN_UNUSED_RESULT)
+# define PERL_UNUSED_RESULT(v) STMT_START { __typeof__(v) z = (v); (void)sizeof(z); } STMT_END
+# else
+# define PERL_UNUSED_RESULT(v) ((void)(v))
+# endif
+#endif
#ifdef USE_ITHREADS
+#ifdef __amigaos4__
+# undef YIELD
+# define YIELD sleep(0)
+#endif
#ifdef WIN32
# include <windows.h>
/* Supposed to be in Winbase.h */
#define MY_POOL (*my_poolp)
-#ifndef WIN32
+#if defined(WIN32) || (defined(__amigaos4__) && defined(__NEWLIB__))
+# undef THREAD_SIGNAL_BLOCKING
+#else
+# define THREAD_SIGNAL_BLOCKING
+#endif
+
+#ifdef THREAD_SIGNAL_BLOCKING
+
/* Block most signals for calling thread, setting the old signal mask to
* oldmask, if it is not NULL */
STATIC int
||
(thread->state & PERL_ITHR_NONVIABLE));
-#ifndef WIN32
+#ifdef THREAD_SIGNAL_BLOCKING
/* We temporarily set the interpreter context to the interpreter being
* destroyed. It's in no condition to handle signals while it's being
* taken apart.
}
PERL_SET_CONTEXT(aTHX);
-#ifndef WIN32
+#ifdef THREAD_SIGNAL_BLOCKING
S_set_sigmask(&origmask);
#endif
}
{
ithread *thread = (ithread *)arg;
int jmp_rc = 0;
- I32 oldscope;
+ volatile I32 oldscope;
volatile int exit_app = 0; /* Thread terminated using 'exit' */
volatile int exit_code = 0;
- int died = 0; /* Thread terminated abnormally */
+ volatile int died = 0; /* Thread terminated abnormally */
dJMPENV;
dMY_POOL;
- /* Blocked until ->create() call finishes */
+ /* The following mutex lock + mutex unlock pair explained.
+ *
+ * parent:
+ * - calls ithread_create (and S_ithread_create), which:
+ * - creates the new thread
+ * - does MUTEX_LOCK(&thread->mutex)
+ * - calls pthread_create(..., S_ithread_run,...)
+ * child:
+ * - starts the S_ithread_run (where we are now), which:
+ * - tries to MUTEX_LOCK(&thread->mutex)
+ * - blocks
+ * parent:
+ * - continues doing more createy stuff
+ * - does MUTEX_UNLOCK(&thread->mutex)
+ * - continues
+ * child:
+ * - finishes MUTEX_LOCK(&thread->mutex)
+ * - does MUTEX_UNLOCK(&thread->mutex)
+ * - continues
+ */
MUTEX_LOCK(&thread->mutex);
MUTEX_UNLOCK(&thread->mutex);
PERL_SET_CONTEXT(thread->interp);
S_ithread_set(aTHX_ thread);
-#ifndef WIN32
+#ifdef THREAD_SIGNAL_BLOCKING
/* Thread starts with most signals blocked - restore the signal mask from
* the ithread struct.
*/
}
JMPENV_POP;
-#ifndef WIN32
+#ifdef THREAD_SIGNAL_BLOCKING
/* The interpreter is finished, so this thread can stop receiving
* signals. This way, our signal handler doesn't get called in the
* middle of our parent thread calling perl_destruct()...
}
PERL_SET_CONTEXT(aTHX);
if (!thread) {
+ /* This lock was acquired in ithread_create()
+ * prior to calling S_ithread_create(). */
MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
{
int fd = PerlIO_fileno(Perl_error_log);
/* Block new thread until ->create() call finishes */
MUTEX_INIT(&thread->mutex);
- MUTEX_LOCK(&thread->mutex);
+ MUTEX_LOCK(&thread->mutex); /* See S_ithread_run() for more detail. */
thread->tid = MY_POOL.tid_counter++;
thread->stack_size = S_good_stack_size(aTHX_ stack_size);
PL_srand_called = FALSE; /* Set it to false so we can detect if it gets
set during the clone */
-#ifndef WIN32
+#ifdef THREAD_SIGNAL_BLOCKING
/* perl_clone() will leave us the new interpreter's context. This poses
* two problems for our signal handler. First, it sets the new context
* before the new interpreter struct is fully initialized, so our signal
# endif
}
-#ifndef WIN32
+#ifdef THREAD_SIGNAL_BLOCKING
/* Now it's safe to accept signals, since we're in our own interpreter's
* context and we have created the thread.
*/
if (rc_stack_size || rc_thread_create) {
#endif
/* Must unlock mutex for destruct call */
+ /* This lock was acquired in ithread_create()
+ * prior to calling S_ithread_create(). */
MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
thread->state |= PERL_ITHR_NONVIABLE;
S_ithread_free(aTHX_ thread); /* Releases MUTEX */
ST(0) = sv_2mortal(S_ithread_to_SV(aTHX_ Nullsv, thread, classname, FALSE));
MUTEX_UNLOCK(&MY_POOL.create_destruct_mutex);
- /* Let thread run */
+ /* Let thread run. */
+ /* See S_ithread_run() for more detail. */
MUTEX_UNLOCK(&thread->mutex);
/* XSRETURN(1); - implied */