Added SilcStack suppor to SILC Scheduler API.
authorPekka Riikonen <priikone@silcnet.org>
Wed, 4 Jul 2007 13:30:26 +0000 (13:30 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 4 Jul 2007 13:30:26 +0000 (13:30 +0000)
20 files changed:
CHANGES.RUNTIME
TODO
lib/Makefile.ad
lib/silcclient/client.c
lib/silchttp/tests/test_silchttpserver.c
lib/silcsftp/tests/sftp_client.c
lib/silcsftp/tests/sftp_server.c
lib/silcskr/tests/test_silcskr.c
lib/silcutil/silcfsm.c
lib/silcutil/silcfsm.h
lib/silcutil/silcschedule.c
lib/silcutil/silcschedule.h
lib/silcutil/silcschedule_i.h
lib/silcutil/tests/test_silcasync.c
lib/silcutil/tests/test_silcfdstream.c
lib/silcutil/tests/test_silcfsm.c
lib/silcutil/tests/test_silcnet.c
lib/silcutil/tests/test_silcschedule.c
lib/silcutil/tests/test_silcthread.c
lib/silcutil/unix/silcunixschedule.c

index 1983a05f62175b4c1d0dd35a6820250b56a40f86..761361cb6b4f6df59426b8fbb1903c619c179dfe 100644 (file)
@@ -1,3 +1,14 @@
+Wed Jul  4 16:31:05 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added SilcStack support to SILC Scheduler API.  The scheduler
+         now creates stack always.  It can be retrieved by
+         silc_schedule_get_stack.  Affected files are
+         lib/silcutil/silcschedule.[ch], silcschedule_i.h.
+
+       * Added SilcStack child creation and use multi-thread support.
+         Added OOM handler, silc_stack_set_oom_handler.  Affected
+         files are lib/silcutil/silcstack.[ch].
+
 Tue Jul  3 22:45:56 EEST 2007  Pekka Riikonen <priikone@silcnet.org>
 
        * Added concept of child stacks to SilcStack, allowing to create
diff --git a/TODO b/TODO
index ac0175a6e883f6b400f734999754c159f8fa4bf8..7ab7b9ad6f8e1fec44dcb2edf030841781e29f31 100644 (file)
--- a/TODO
+++ b/TODO
@@ -289,7 +289,19 @@ SKR Library, lib/silcskr/
 Crypto Library, lib/silccrypt/
 ==============================
 
- o SilcStack to APIs.
+ o Add silc_crypto_init and silc_crypto_uninit.  The _init should take
+   SilcStack that will act as global memory pool for all of crypto 
+   library.  It should not be necessary anymore to separately register
+   default ciphers, HMACs, etc, the _init would do that.  However, if
+   user after _init calls silc_pkcs_register, for example, it would take
+   preference over the default once, ie. user can always dictate the
+   order of algorithms.
+
+   The global SilcStack should be used by all routines in lib/silccrypt, 
+   lib/silcacc (and lib/silcmath).  lib/silcskr and lib/silcasn1 has support 
+   in the API for providing SilcStack, however, if not provided, they 
+   should look for global SilcStack, if SILC_DIST_CRYPTO is defined.
+   Same SILC_DIST_CRYPTO ifdef for other libs.
 
  o Add fingerprint to SilcSILCPublicKey and retrieval to silcpk.h, and
    possibly to silcpkcs.h.
index 3d1cfacecf9afb82e7b207895c316f7661ec0e37..7cb3241c7c62e28b021bd836ee64f88105a72fa6 100644 (file)
@@ -48,6 +48,9 @@ SILCLIB_DIRS =                \
 #ifdef SILC_DIST_VCARD
        silcvcard       \
 #endif SILC_DIST_VCARD
+#ifdef SILC_DIST_ACC
+       silcacc         \
+#endif SILC_DIST_ACC
 
 if SILC_ENABLE_SHARED
 LIBTOOL_OPTS= -release $(LIB_BASE_VERSION) -rpath $(DESTDIR)$(libdir)
index d7942f5f0525d9a336f2933081ab7ba7e36bf560..9fef6df8b6ed453bd9a1353bbc31d529be815925 100644 (file)
@@ -1041,7 +1041,7 @@ SilcBool silc_client_init(SilcClient client, const char *username,
   silc_rng_global_init(client->rng);
 
   /* Initialize the scheduler */
-  client->schedule = silc_schedule_init(0, client);
+  client->schedule = silc_schedule_init(0, client, NULL);
   if (!client->schedule)
     return FALSE;
 
index 197e5debb668e5b2a63592ec989a042562ac03fc..e8b3f0a2d095f0285558bfec72df7bbae18cf5a2 100644 (file)
@@ -121,7 +121,7 @@ int main(int argc, char **argv)
   signal(SIGPIPE, SIG_IGN);
 
   SILC_LOG_DEBUG(("Allocating scheduler"));
-  schedule = silc_schedule_init(0, NULL);
+  schedule = silc_schedule_init(0, NULL, NULL);
   if (!schedule)
     goto err;
 
index 71ec8982979eaf6def1425d3858a438db8a8f53e..403e50715d1ffd721d1d4f161dc461fe18ee8235 100644 (file)
@@ -296,7 +296,7 @@ int main(int argc, char **argv)
     silc_log_set_debug_string("*");
   }
 
-  client->schedule = silc_schedule_init(0, NULL);
+  client->schedule = silc_schedule_init(0, NULL, NULL);
   if (!client->schedule)
     return -1;
 
index 294c293340770e76dbb719e84eb0897cd433cc10..ced35250e7c1d623a4380494f8d22cbaf8e8e3b2 100644 (file)
@@ -71,7 +71,7 @@ int main()
   silc_log_debug_hexdump(TRUE);
   silc_log_set_debug_string("*sftp*");
 
-  server->schedule = silc_schedule_init(0, NULL);
+  server->schedule = silc_schedule_init(0, NULL, NULL);
   if (!server->schedule)
     return -1;
 
index 00936a827ffa39a0edbfdb63d608e65f9f7eaa3d..f1416aa4e0b3f7bc443e12fb6847bd9f0e4d05df 100644 (file)
@@ -38,7 +38,7 @@ int main(int argc, char **argv)
   }
 
   SILC_LOG_DEBUG(("Allocating scheduler"));
-  schedule = silc_schedule_init(0, NULL);
+  schedule = silc_schedule_init(0, NULL, NULL);
 
   SILC_LOG_DEBUG(("Allocating SKR"));
   skr = silc_skr_alloc();
index 3382713ed50276c90c1c84975727f901dc113a31..d87e0406cd5d83b14f4c34c8d0e8104899dfa04e 100644 (file)
@@ -765,14 +765,19 @@ 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));
+  if (silc_unlikely(!fsm->schedule)) {
+    fsm->schedule = old;
     return NULL;
+  }
 
   /* 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);
index d9c4be0f07054a0420a53fca75bec04975fc0624..c80a19b706984cc6470674b45de23660182f7f8c 100644 (file)
@@ -905,7 +905,7 @@ typedef struct SilcFSMEventObject SilcFSMEventStruct;
  *    some event happens, some thread moves to a specific state or similar.
  *    The FSM Events may also be used in FSM threads that are executed in
  *    real system threads.  It is safe to wait and signal the event from
- *    threads.
+ *    threads.  The `fsm' must be the machine, not a thread.
  *
  *    Use the macros SILC_FSM_EVENT_WAIT and SILC_FSM_EVENT_TIMEDWAIT to wait
  *    for the event.  Use the SILC_FSM_EVENT_SIGNAL macro to signal all the
@@ -924,7 +924,8 @@ SilcFSMEvent silc_fsm_event_alloc(SilcFSM fsm);
  *
  *    Initializes a pre-allocates FSM event context.  This call is
  *    equivalent to silc_fsm_event_alloc except this use the pre-allocated
- *    context.  This fuction does not allocate any memory.
+ *    context.  This fuction does not allocate any memory.  The `fsm'
+ *    must be the machine, not a thread.
  *
  ***/
 void silc_fsm_event_init(SilcFSMEvent event, SilcFSM fsm);
index bdda281e280e36e9444e586cf987fde08b34e37e..1737e3be597c82dda0f2ac525689a98ed5d38c0e 100644 (file)
@@ -312,27 +312,35 @@ void silc_schedule_stats(SilcSchedule schedule)
    scheduler can handle. The `app_context' is application specific
    context that is delivered to task callbacks. */
 
-SilcSchedule silc_schedule_init(int max_tasks, void *app_context)
+SilcSchedule silc_schedule_init(int max_tasks, void *app_context,
+                               SilcStack stack)
 {
   SilcSchedule schedule;
 
-  SILC_LOG_DEBUG(("Initializing scheduler"));
+  stack = silc_stack_alloc(0, stack);
+  if (!stack)
+    return NULL;
 
-  schedule = silc_calloc(1, sizeof(*schedule));
+  /* Allocate scheduler from the stack */
+  schedule = silc_scalloc(stack, 1, sizeof(*schedule));
   if (!schedule)
     return NULL;
 
+  SILC_LOG_DEBUG(("Initializing scheduler %p", schedule));
+
+  /* Allocate Fd task hash table dynamically */
   schedule->fd_queue =
     silc_hash_table_alloc(NULL, 0, silc_hash_uint, NULL, NULL, NULL,
                          silc_schedule_fd_destructor, NULL, TRUE);
   if (!schedule->fd_queue) {
-    silc_free(schedule);
+    silc_stack_free(stack);
     return NULL;
   }
 
   silc_list_init(schedule->timeout_queue, struct SilcTaskStruct, next);
   silc_list_init(schedule->free_tasks, struct SilcTaskStruct, next);
 
+  schedule->stack = stack;
   schedule->app_context = app_context;
   schedule->valid = TRUE;
   schedule->max_tasks = max_tasks;
@@ -345,7 +353,7 @@ SilcSchedule silc_schedule_init(int max_tasks, void *app_context)
   if (!schedule->internal) {
     silc_hash_table_free(schedule->fd_queue);
     silc_mutex_free(schedule->lock);
-    silc_free(schedule);
+    silc_stack_free(stack);
     return NULL;
   }
 
@@ -365,7 +373,7 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule)
 {
   SilcTask task;
 
-  SILC_LOG_DEBUG(("Uninitializing scheduler"));
+  SILC_LOG_DEBUG(("Uninitializing scheduler %p", schedule));
 
   if (schedule->valid == TRUE)
     return FALSE;
@@ -397,7 +405,7 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule)
   schedule_ops.uninit(schedule, schedule->internal);
 
   silc_mutex_free(schedule->lock);
-  silc_free(schedule);
+  silc_stack_free(schedule->stack);
 
   return TRUE;
 }
@@ -548,6 +556,13 @@ void *silc_schedule_get_context(SilcSchedule schedule)
   return schedule->app_context;
 }
 
+/* Return the stack of the scheduler */
+
+SilcStack silc_schedule_get_stack(SilcSchedule schedule)
+{
+  return schedule->stack;
+}
+
 /* Set notify callback */
 
 void silc_schedule_set_notify(SilcSchedule schedule,
index 8c2154a5619e405f63df48f7dc8152307922124e..a7914aec3039be88a19bbddb6f7d648443ad6e25 100644 (file)
@@ -245,7 +245,8 @@ void func(SilcSchedule schedule, void *app_context, SilcTaskEvent type,     \
  *
  * SYNOPSIS
  *
- *    SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
+ *    SilcSchedule silc_schedule_init(int max_tasks, void *app_context,
+ *                                    SilcStack stack);
  *
  * DESCRIPTION
  *
@@ -261,8 +262,17 @@ void func(SilcSchedule schedule, void *app_context, SilcTaskEvent type,    \
  *    limit can be significantly increased when this function is called in
  *    priviliged mode (as super user).
  *
+ *    If `stack' is non-NULL all memory allocation for the scheduler is done
+ *    from the `stack'.  Scheduler's stack may be retrieved by calling
+ *    silc_schedule_get_stack.  A stack is created for scheduler always even
+ *    if `stack' is NULL.  If it is non-NULL the created stack is a child
+ *    stack using `stack' as its parent.  This means that memory allocated
+ *    by the scheduler will be returned to the `stack' when scheduler is
+ *    destroyed.
+ *
  ***/
-SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
+SilcSchedule silc_schedule_init(int max_tasks, void *app_context,
+                               SilcStack stack);
 
 /****f* silcutil/SilcScheduleAPI/silc_schedule_uninit
  *
@@ -277,6 +287,10 @@ SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
  *    scheduler could not be uninitialized. This happens when the scheduler
  *    is still valid and silc_schedule_stop has not been called.
  *
+ *    If SilcStack was given to silc_schedule_init all memory allocated
+ *    during the life time of the scheduler will be returned back to the
+ *    given stack.
+ *
  ***/
 SilcBool silc_schedule_uninit(SilcSchedule schedule);
 
@@ -378,6 +392,22 @@ void silc_schedule_wakeup(SilcSchedule schedule);
  ***/
 void *silc_schedule_get_context(SilcSchedule schedule);
 
+/****f* silcutil/SilcScheduleAPI/silc_schedule_get_stack
+ *
+ * SYNOPSIS
+ *
+ *    SilcStack silc_schedule_get_stack(SilcSchedule schedule);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the stack of the `schedule'.  If it is used to make memory
+ *    allocations outside the scheduler, it is recommended that a new
+ *    child stack is created by using the returned stack as a parent and
+ *    using the child stack to make the memory allocations.
+ *
+ ***/
+SilcStack silc_schedule_get_stack(SilcSchedule schedule);
+
 /****f* silcutil/SilcScheduleAPI/silc_schedule_set_notify
  *
  * SYNOPSIS
index 61ea48125a0d96d374db7f2730fd8d95cd6a2adc..6c8d462d56eaf2948a51250f8fb0801e73f35a56 100644 (file)
@@ -76,6 +76,7 @@ struct SilcScheduleStruct {
   void *app_context;              /* Application specific context */
   SilcTaskNotifyCb notify;        /* Notify callback */
   void *notify_context;                   /* Notify context */
+  SilcStack stack;                /* Stack */
   SilcHashTable fd_queue;         /* FD task queue */
   SilcList fd_dispatch;                   /* Dispatched FDs */
   SilcList timeout_queue;         /* Timeout queue */
index ca68c7d01f6703a272f1742f68f264e9762d19d1..4e60ba4220d48bedb67f9ae5b41ec1cdc7b2ec28 100644 (file)
@@ -126,7 +126,7 @@ int main(int argc, char **argv)
   }
 
   SILC_LOG_DEBUG(("Allocating scheduler"));
-  schedule = silc_schedule_init(0, NULL);
+  schedule = silc_schedule_init(0, NULL, NULL);
 
   f = silc_calloc(1, sizeof(*f));
   if (!f)
index e4d53a59e7316d327107c6c8a8875ded929b7f14..cd95c6ce338a24f6934af80a5b2f4f2c99d38090 100644 (file)
@@ -203,7 +203,7 @@ int main(int argc, char **argv)
   }
 
   SILC_LOG_DEBUG(("Allocating scheduler"));
-  schedule = silc_schedule_init(0, NULL);
+  schedule = silc_schedule_init(0, NULL, NULL);
   if (!schedule)
     goto err;
 
index f041630f1cfe16426ef353723e9fb800f0a07481..030deb56ac35a7dc49331b3fbccc9afcd7ad79cf 100644 (file)
@@ -212,7 +212,7 @@ SILC_FSM_STATE(test_st_signal1)
 
   SILC_LOG_DEBUG(("Signaller 1"));
   SILC_FSM_EVENT_SIGNAL(&f->wait2);
-  silc_fsm_next_later(fsm, test_st_signal1_check, 0, 500000); 
+  silc_fsm_next_later(fsm, test_st_signal1_check, 0, 500000);
   return SILC_FSM_WAIT;;
 }
 
@@ -454,7 +454,7 @@ int main(int argc, char **argv)
   }
 
   SILC_LOG_DEBUG(("Allocating scheduler"));
-  schedule = silc_schedule_init(0, NULL);
+  schedule = silc_schedule_init(0, NULL, NULL);
 
   f = silc_calloc(1, sizeof(*f));
   if (!f)
index 2931bd7475ea13d51c59078602dfea91a33f89ec..1c7a985157e41213f00b630ff63511364615f121 100644 (file)
@@ -172,7 +172,7 @@ int main(int argc, char **argv)
   }
 
   SILC_LOG_DEBUG(("Allocating scheduler"));
-  schedule = silc_schedule_init(0, NULL);
+  schedule = silc_schedule_init(0, NULL, NULL);
 
   f = silc_calloc(1, sizeof(*f));
   if (!f)
index 204f632fede304c8f21b84d09621f418399ff2fc..0b87ca443e76ab259aefc64c1c1a69b249bd57a1 100644 (file)
@@ -98,7 +98,7 @@ int main(int argc, char **argv)
   }
 
   SILC_LOG_DEBUG(("Allocating scheduler"));
-  schedule = silc_schedule_init(NUM_FTASK, NULL);
+  schedule = silc_schedule_init(NUM_FTASK, NULL, NULL);
   if (!schedule)
     goto err;
   silc_schedule_set_notify(schedule, notify_cb, NULL);
index 1b0245f82bef104dd4a4e45f03197cb59794f0fd..b2ec10d17cafc9244f45cad283e6908da294004f 100644 (file)
@@ -30,7 +30,7 @@ int main(int argc, char **argv)
     silc_log_set_debug_string("*thread*");
   }
 
-  schedule = silc_schedule_init(0, NULL);
+  schedule = silc_schedule_init(0, NULL, NULL);
   if (!schedule)
     goto err;
 
index 137d52def8d784e8ddd55dc69f2fd6a661fe81b2..524e4b86f19eaf05d2dfd1ae3111020d5cb101bd 100644 (file)
@@ -349,7 +349,7 @@ void *silc_schedule_internal_init(SilcSchedule schedule,
   SilcUnixScheduler internal;
   int i;
 
-  internal = silc_calloc(1, sizeof(*internal));
+  internal = silc_scalloc(schedule->stack, 1, sizeof(*internal));
   if (!internal)
     return NULL;
 
@@ -389,7 +389,6 @@ void *silc_schedule_internal_init(SilcSchedule schedule,
 #ifdef SILC_THREADS
   if (pipe(internal->wakeup_pipe)) {
     SILC_LOG_ERROR(("pipe() fails: %s", strerror(errno)));
-    silc_free(internal);
     return NULL;
   }
 
@@ -433,8 +432,6 @@ void silc_schedule_internal_uninit(SilcSchedule schedule, void *context)
 #elif defined(HAVE_POLL) && defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
   silc_free(internal->fds);
 #endif /* HAVE_POLL && HAVE_SETRLIMIT && RLIMIT_NOFILE */
-
-  silc_free(internal);
 }
 
 /* Wakes up the scheduler */