+ sigset_t oldmask;
+ int cs, i, r;
+ struct sigaction sa = { .sa_flags = SA_RESTART | SA_ONSTACK, .sa_handler = handler };
+ pthread_t self = __pthread_self(), td;
+ int count = 0;
+
+ /* Blocking signals in two steps, first only app-level signals
+ * before taking the lock, then all signals after taking the lock,
+ * is necessary to achieve AS-safety. Blocking them all first would
+ * deadlock if multiple threads called __synccall. Waiting to block
+ * any until after the lock would allow re-entry in the same thread
+ * with the lock already held. */
+ __block_app_sigs(&oldmask);
+ __tl_lock();
+ __block_all_sigs(0);
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+
+ sem_init(&target_sem, 0, 0);
+ sem_init(&caller_sem, 0, 0);
+
+ if (!libc.threads_minus_1 || __syscall(SYS_gettid) != self->tid)
+ goto single_threaded;