+ /* A thread may also become dead after this test. */
+ if ((th->state != STATE_DEAD)) {
+ /* In clone_threads, if A and B both interrupt C at
+ * approximately the same time, it does not matter: the
+ * second signal will be masked until the handler has
+ * returned from the first one. In pthreads though, we
+ * can't put the knowledge of what function to call into
+ * the siginfo, so we have to store it in the destination
+ * thread, and do it in such a way that A won't clobber
+ * B's interrupt. Hence this stupid linked list.
+ *
+ * This does depend on SIG_INTERRUPT_THREAD being queued
+ * (as POSIX RT signals are): we need to keep
+ * interrupt_fun data for exactly as many signals as are
+ * going to be received by the destination thread.
+ */
+ struct cons *c=alloc_cons(function,NIL);
+ int kill_status;
+ /* interrupt_thread_handler locks this spinlock with
+ * interrupts blocked and it does so for the sake of
+ * arrange_return_to_lisp_function, so we must also block
+ * them. */
+ sigset_t newset,oldset;
+ sigemptyset(&newset);
+ sigaddset_blockable(&newset);
+ thread_sigmask(SIG_BLOCK, &newset, &oldset);
+ get_spinlock(&th->interrupt_fun_lock,
+ (long)arch_os_get_current_thread());
+ kill_status=thread_kill(th->os_thread,SIG_INTERRUPT_THREAD);
+ if(kill_status==0) {
+ ((struct cons *)native_pointer(c))->cdr=th->interrupt_fun;
+ th->interrupt_fun=c;
+ }
+ release_spinlock(&th->interrupt_fun_lock);
+ thread_sigmask(SIG_SETMASK,&oldset,0);
+ return (kill_status ? -1 : 0);
+ }
+ errno=EPERM; return -1;