Added silc_likely and silc_unlikely GCC branch prediction macros.
[silc.git] / lib / silcutil / silcfsm.c
index 5cd81e1969a2e59786c7532f11c17242187fcf9d..4feffdffba0f74110f3d13f929278dcf49b8336e 100644 (file)
@@ -38,11 +38,11 @@ SilcFSM silc_fsm_alloc(void *fsm_context,
   SilcFSM fsm;
 
   fsm = silc_calloc(1, sizeof(*fsm));
-  if (!fsm)
+  if (silc_unlikely(!fsm))
     return NULL;
 
-  if (!silc_fsm_init(fsm, fsm_context, destructor,
-                    destructor_context, schedule)) {
+  if (silc_unlikely(!silc_fsm_init(fsm, fsm_context, destructor,
+                                  destructor_context, schedule))) {
     silc_free(fsm);
     return NULL;
   }
@@ -86,7 +86,7 @@ SilcFSMThread silc_fsm_thread_alloc(SilcFSM fsm,
   SilcFSMThread thread;
 
   thread = silc_calloc(1, sizeof(*thread));
-  if (!thread)
+  if (silc_unlikely(!thread))
     return NULL;
 
   silc_fsm_thread_init(thread, fsm, thread_context, destructor,
@@ -160,10 +160,11 @@ void silc_fsm_free(void *fsm)
 {
   SilcFSM f = fsm;
   if (!f->thread)
-    silc_schedule_task_add_timeout(f->schedule, silc_fsm_free_final, f, 0, 0);
-  else
-    silc_fsm_free_final(f->schedule, silc_schedule_get_context(f->schedule),
-                       0, 0, f);
+    if (silc_schedule_task_add_timeout(f->schedule, silc_fsm_free_final,
+                                      f, 0, 0))
+      return;
+  silc_fsm_free_final(f->schedule, silc_schedule_get_context(f->schedule),
+                     0, 0, f);
 }
 
 /* Task to start real thread. We start threads through scheduler, not
@@ -200,13 +201,18 @@ void silc_fsm_start(void *fsm, SilcFSMStateCallback start_state)
 
   /* Start real thread through scheduler */
   if (f->thread && f->real_thread) {
-    silc_schedule_task_add_timeout(f->schedule, silc_fsm_start_real_thread,
-                                  f, 0, 0);
+    if (!silc_schedule_task_add_timeout(f->schedule,
+                                       silc_fsm_start_real_thread,
+                                       f, 0, 0))
+      silc_fsm_start_real_thread(f->schedule,
+                                silc_schedule_get_context(f->schedule),
+                                0, 0, f);
     return;
   }
 
   /* Normal FSM operation */
-  silc_schedule_task_add_timeout(f->schedule, silc_fsm_run, f, 0, 0);
+  if (!silc_schedule_task_add_timeout(f->schedule, silc_fsm_run, f, 0, 0))
+    silc_fsm_run(f->schedule, silc_schedule_get_context(f->schedule), 0, 0, f);
 }
 
 /* Start FSM in the specified state synchronously */
@@ -288,8 +294,13 @@ void silc_fsm_finish(void *fsm)
   SilcFSM f = fsm;
 
   SILC_ASSERT(!f->finished);
-  f->finished = TRUE;
+
+  /* Machine must not have active threads */
+  if (!f->thread && f->u.m.threads)
+    assert(f->u.m.threads == 0);
+
   f->started = FALSE;
+  f->finished = TRUE;
 
   silc_schedule_task_del_by_all(f->schedule, 0, silc_fsm_run, f);
   f->next_later = FALSE;
@@ -304,11 +315,13 @@ void silc_fsm_finish(void *fsm)
   }
 
   /* Normal FSM operation */
-  if (f->synchronous)
-    silc_fsm_finish_fsm(f->schedule, silc_schedule_get_context(f->schedule),
-                       0, 0, fsm);
-  else
-    silc_schedule_task_add_timeout(f->schedule, silc_fsm_finish_fsm, f, 0, 0);
+  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);
 }
 
 /* Return associated scheduler */
@@ -327,16 +340,12 @@ SilcFSM silc_fsm_get_machine(SilcFSMThread thread)
   return (SilcFSM)thread->u.t.fsm;
 }
 
-/* Returns TRUE if FSM is started and not yet finished */
+/* Returns TRUE if FSM is started */
 
 SilcBool silc_fsm_is_started(void *fsm)
 {
   SilcFSM f = fsm;
-
-  if (f->started && !f->finished)
-    return TRUE;
-
-  return FALSE;
+  return f->started;
 }
 
 /* Set context */
@@ -379,8 +388,6 @@ SilcBool silc_fsm_thread_wait(void *fsm, void *thread)
 
   SILC_ASSERT(t->thread);
 
-  if (t->finished)
-    return FALSE;
   t->u.t.sema = silc_fsm_sema_alloc(t->u.t.fsm, 0);
   if (!t->u.t.sema)
     return FALSE;
@@ -473,7 +480,7 @@ SilcFSMSema silc_fsm_sema_alloc(SilcFSM fsm, SilcUInt32 value)
   SilcFSMSema sema;
 
   sema = silc_calloc(1, sizeof(*sema));
-  if (!sema)
+  if (silc_unlikely(!sema))
     return NULL;
 
   silc_fsm_sema_init(sema, fsm, value);
@@ -666,7 +673,7 @@ void silc_fsm_sema_post(SilcFSMSema sema)
     }
 
     p = silc_calloc(1, sizeof(*p));
-    if (!p)
+    if (silc_unlikely(!p))
       continue;
     p->sema = sema;
     p->fsm = fsm;
@@ -718,11 +725,12 @@ static void *silc_fsm_thread(void *context)
      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 (!fsm->schedule)
+  if (silc_unlikely(!fsm->schedule))
     return NULL;
 
   /* Start the FSM thread */
-  if (!silc_schedule_task_add_timeout(fsm->schedule, silc_fsm_run, fsm, 0, 0))
+  if (silc_unlikely(!silc_schedule_task_add_timeout(fsm->schedule,
+                                                   silc_fsm_run, fsm, 0, 0)))
     return NULL;
 
   /* Run the scheduler */