+/* Finish FSM */
+
+void silc_fsm_finish(void *fsm)
+{
+ SilcFSM f = fsm;
+
+ SILC_VERIFY(!f->finished);
+
+ f->started = FALSE;
+ f->finished = TRUE;
+
+ silc_schedule_task_del_by_all(f->schedule, 0, silc_fsm_run, f);
+ f->next_later = FALSE;
+
+ /* If we are thread and using real threads, the FSM thread will finish
+ after the real thread has finished, in the main thread. */
+ if (f->thread && f->real_thread) {
+ /* Stop the real thread's scheduler to finish the thread */
+ silc_schedule_stop(f->schedule);
+ silc_schedule_wakeup(f->schedule);
+ return;
+ }
+
+ /* Normal FSM operation */
+ if (!f->synchronous)
+ if (silc_schedule_task_add_timeout(f->schedule, silc_fsm_finish_fsm,
+ f, 0, 0))
+ return;
+
+ silc_fsm_finish_fsm(f->schedule, silc_schedule_get_context(f->schedule),
+ 0, 0, fsm);
+}
+