+
+ p = silc_calloc(1, sizeof(*p));
+ if (!p)
+ continue;
+ p->sema = sema;
+ p->fsm = fsm;
+ silc_fsm_sema_ref(sema);
+
+ /* Signal through scheduler. Wake up destination scheduler in case
+ caller is a real thread. */
+ silc_schedule_task_add_timeout(fsm->schedule, silc_fsm_signal, p, 0, 1);
+ silc_schedule_wakeup(fsm->schedule);
+ }
+
+ silc_mutex_unlock(lock);
+}
+
+/* Post thread termination semaphore. Special function used only to
+ signal thread termination when SILC_FSM_THREAD_WAIT was used. */
+
+static void silc_fsm_thread_termination_post(SilcFSMSema sema)
+{
+ SilcFSM fsm;
+ SilcMutex lock = sema->fsm->u.m.lock;
+
+ SILC_LOG_DEBUG(("Post thread termination semaphore %p", sema));
+
+ silc_mutex_lock(lock);
+
+ silc_list_start(sema->waiters);
+ while ((fsm = silc_list_get(sema->waiters)) != SILC_LIST_END) {
+ /* Signal on thread termination. Wake up destination scheduler in case
+ caller is a real thread. */
+ silc_list_del(sema->waiters, fsm);
+ silc_fsm_continue(fsm);
+ silc_schedule_wakeup(fsm->schedule);