X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcfsm.c;h=2ded983253aa77906cd439210b69306afe92116c;hb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;hp=5139c0cd7f7be2f2c0f7b45f1e76dd1d7752da8d;hpb=7719f8448a57a24545fc73615492528a23735ad7;p=silc.git diff --git a/lib/silcutil/silcfsm.c b/lib/silcutil/silcfsm.c index 5139c0cd..2ded9832 100644 --- a/lib/silcutil/silcfsm.c +++ b/lib/silcutil/silcfsm.c @@ -58,8 +58,13 @@ SilcBool silc_fsm_init(SilcFSM fsm, void *destructor_context, SilcSchedule schedule) { - if (!schedule) - return FALSE; + if (!schedule) { + schedule = silc_schedule_get_global(); + if (!schedule) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return FALSE; + } + } fsm->fsm_context = fsm_context; fsm->state_context = NULL; @@ -106,7 +111,7 @@ void silc_fsm_thread_init(SilcFSMThread thread, SILC_LOG_DEBUG(("Initializing new thread %p (%s)", thread, real_thread ? "real" : "FSM")); - SILC_ASSERT(!fsm->thread); + SILC_VERIFY(!fsm->thread); thread->fsm_context = thread_context; thread->state_context = NULL; @@ -151,6 +156,9 @@ SILC_TASK_CALLBACK(silc_fsm_free_final) if (f->thread && f->u.t.event) silc_fsm_event_free(f->u.t.event); + if (!f->thread) + silc_atomic_uninit32(&f->u.m.threads); + silc_free(f); } @@ -312,11 +320,7 @@ void silc_fsm_finish(void *fsm) { SilcFSM f = fsm; - SILC_ASSERT(!f->finished); - - /* Machine must not have active threads */ - if (!f->thread && silc_atomic_get_int32(&f->u.m.threads)) - assert(silc_atomic_get_int32(&f->u.m.threads) == 0); + SILC_VERIFY(!f->finished); f->started = FALSE; f->finished = TRUE; @@ -355,7 +359,7 @@ SilcSchedule silc_fsm_get_schedule(void *fsm) SilcFSM silc_fsm_get_machine(SilcFSMThread thread) { - SILC_ASSERT(thread->thread); + SILC_VERIFY(thread->thread); return (SilcFSM)thread->u.t.fsm; } @@ -405,7 +409,7 @@ SilcBool silc_fsm_thread_wait(void *fsm, void *thread) { SilcFSM t = thread; - SILC_ASSERT(t->thread); + SILC_VERIFY(t->thread); t->u.t.event = silc_fsm_event_alloc(t->u.t.fsm); if (!t->u.t.event) @@ -481,11 +485,13 @@ SILC_TASK_CALLBACK(silc_fsm_finish_fsm) fsm->destructor(fsm, fsm->fsm_context, fsm->destructor_context); } else { + /* Machine must not have active threads */ + SILC_VERIFY(silc_atomic_get_int32(&fsm->u.m.threads) == 0); + if (fsm->u.m.lock) { silc_mutex_free(fsm->u.m.lock); fsm->u.m.lock = NULL; } - silc_atomic_uninit32(&fsm->u.m.threads); /* Call the destructor callback. */ if (fsm->destructor) @@ -514,7 +520,7 @@ SilcFSMEvent silc_fsm_event_alloc(SilcFSM fsm) void silc_fsm_event_init(SilcFSMEvent event, SilcFSM fsm) { SILC_LOG_DEBUG(("Initializing event %p", event)); - SILC_ASSERT(!fsm->thread); + SILC_VERIFY(!fsm->thread); memset(event, 0, sizeof(*event)); event->fsm = fsm; event->refcnt = 0; @@ -764,18 +770,29 @@ void *silc_fsm_thread(void *context) /* We allocate new SilcSchedule for the FSM, as the old SilcSchedule cannot be used in this thread. Application may still use it if it wants but we use our own. */ - fsm->schedule = silc_schedule_init(0, old); - if (silc_unlikely(!fsm->schedule)) + fsm->schedule = silc_schedule_init(0, old, silc_schedule_get_stack(old), old); + if (silc_unlikely(!fsm->schedule)) { + fsm->schedule = old; return NULL; + } + + /* The new scheduler is a global scheduler in this thread */ + silc_schedule_set_global(fsm->schedule); /* Start the FSM thread */ if (silc_unlikely(!silc_schedule_task_add_timeout(fsm->schedule, - silc_fsm_run, fsm, 0, 0))) + silc_fsm_run, fsm, 0, 0))) { + silc_schedule_uninit(fsm->schedule); + fsm->schedule = old; return NULL; + } /* Run the scheduler */ silc_schedule(fsm->schedule); + /* Reset global scheduler */ + silc_schedule_set_global(NULL); + /* Free resources */ silc_schedule_uninit(fsm->schedule);