From f1a52c060fd203ee275b9cc6aff711bf1961ad13 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 4 Jul 2007 13:30:26 +0000 Subject: [PATCH] Added SilcStack suppor to SILC Scheduler API. --- CHANGES.RUNTIME | 11 ++++++++ TODO | 14 +++++++++- lib/Makefile.ad | 3 +++ lib/silcclient/client.c | 2 +- lib/silchttp/tests/test_silchttpserver.c | 2 +- lib/silcsftp/tests/sftp_client.c | 2 +- lib/silcsftp/tests/sftp_server.c | 2 +- lib/silcskr/tests/test_silcskr.c | 2 +- lib/silcutil/silcfsm.c | 11 +++++--- lib/silcutil/silcfsm.h | 5 ++-- lib/silcutil/silcschedule.c | 29 +++++++++++++++----- lib/silcutil/silcschedule.h | 34 ++++++++++++++++++++++-- lib/silcutil/silcschedule_i.h | 1 + lib/silcutil/tests/test_silcasync.c | 2 +- lib/silcutil/tests/test_silcfdstream.c | 2 +- lib/silcutil/tests/test_silcfsm.c | 4 +-- lib/silcutil/tests/test_silcnet.c | 2 +- lib/silcutil/tests/test_silcschedule.c | 2 +- lib/silcutil/tests/test_silcthread.c | 2 +- lib/silcutil/unix/silcunixschedule.c | 5 +--- 20 files changed, 106 insertions(+), 31 deletions(-) diff --git a/CHANGES.RUNTIME b/CHANGES.RUNTIME index 1983a05f..761361cb 100644 --- a/CHANGES.RUNTIME +++ b/CHANGES.RUNTIME @@ -1,3 +1,14 @@ +Wed Jul 4 16:31:05 EEST 2007 Pekka Riikonen + + * 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 * Added concept of child stacks to SilcStack, allowing to create diff --git a/TODO b/TODO index ac0175a6..7ab7b9ad 100644 --- 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. diff --git a/lib/Makefile.ad b/lib/Makefile.ad index 3d1cface..7cb3241c 100644 --- a/lib/Makefile.ad +++ b/lib/Makefile.ad @@ -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) diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index d7942f5f..9fef6df8 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -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; diff --git a/lib/silchttp/tests/test_silchttpserver.c b/lib/silchttp/tests/test_silchttpserver.c index 197e5deb..e8b3f0a2 100644 --- a/lib/silchttp/tests/test_silchttpserver.c +++ b/lib/silchttp/tests/test_silchttpserver.c @@ -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; diff --git a/lib/silcsftp/tests/sftp_client.c b/lib/silcsftp/tests/sftp_client.c index 71ec8982..403e5071 100644 --- a/lib/silcsftp/tests/sftp_client.c +++ b/lib/silcsftp/tests/sftp_client.c @@ -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; diff --git a/lib/silcsftp/tests/sftp_server.c b/lib/silcsftp/tests/sftp_server.c index 294c2933..ced35250 100644 --- a/lib/silcsftp/tests/sftp_server.c +++ b/lib/silcsftp/tests/sftp_server.c @@ -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; diff --git a/lib/silcskr/tests/test_silcskr.c b/lib/silcskr/tests/test_silcskr.c index 00936a82..f1416aa4 100644 --- a/lib/silcskr/tests/test_silcskr.c +++ b/lib/silcskr/tests/test_silcskr.c @@ -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(); diff --git a/lib/silcutil/silcfsm.c b/lib/silcutil/silcfsm.c index 3382713e..d87e0406 100644 --- a/lib/silcutil/silcfsm.c +++ b/lib/silcutil/silcfsm.c @@ -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); diff --git a/lib/silcutil/silcfsm.h b/lib/silcutil/silcfsm.h index d9c4be0f..c80a19b7 100644 --- a/lib/silcutil/silcfsm.h +++ b/lib/silcutil/silcfsm.h @@ -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); diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index bdda281e..1737e3be 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -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, diff --git a/lib/silcutil/silcschedule.h b/lib/silcutil/silcschedule.h index 8c2154a5..a7914aec 100644 --- a/lib/silcutil/silcschedule.h +++ b/lib/silcutil/silcschedule.h @@ -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 diff --git a/lib/silcutil/silcschedule_i.h b/lib/silcutil/silcschedule_i.h index 61ea4812..6c8d462d 100644 --- a/lib/silcutil/silcschedule_i.h +++ b/lib/silcutil/silcschedule_i.h @@ -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 */ diff --git a/lib/silcutil/tests/test_silcasync.c b/lib/silcutil/tests/test_silcasync.c index ca68c7d0..4e60ba42 100644 --- a/lib/silcutil/tests/test_silcasync.c +++ b/lib/silcutil/tests/test_silcasync.c @@ -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) diff --git a/lib/silcutil/tests/test_silcfdstream.c b/lib/silcutil/tests/test_silcfdstream.c index e4d53a59..cd95c6ce 100644 --- a/lib/silcutil/tests/test_silcfdstream.c +++ b/lib/silcutil/tests/test_silcfdstream.c @@ -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; diff --git a/lib/silcutil/tests/test_silcfsm.c b/lib/silcutil/tests/test_silcfsm.c index f041630f..030deb56 100644 --- a/lib/silcutil/tests/test_silcfsm.c +++ b/lib/silcutil/tests/test_silcfsm.c @@ -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) diff --git a/lib/silcutil/tests/test_silcnet.c b/lib/silcutil/tests/test_silcnet.c index 2931bd74..1c7a9851 100644 --- a/lib/silcutil/tests/test_silcnet.c +++ b/lib/silcutil/tests/test_silcnet.c @@ -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) diff --git a/lib/silcutil/tests/test_silcschedule.c b/lib/silcutil/tests/test_silcschedule.c index 204f632f..0b87ca44 100644 --- a/lib/silcutil/tests/test_silcschedule.c +++ b/lib/silcutil/tests/test_silcschedule.c @@ -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); diff --git a/lib/silcutil/tests/test_silcthread.c b/lib/silcutil/tests/test_silcthread.c index 1b0245f8..b2ec10d1 100644 --- a/lib/silcutil/tests/test_silcthread.c +++ b/lib/silcutil/tests/test_silcthread.c @@ -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; diff --git a/lib/silcutil/unix/silcunixschedule.c b/lib/silcutil/unix/silcunixschedule.c index 137d52de..524e4b86 100644 --- a/lib/silcutil/unix/silcunixschedule.c +++ b/lib/silcutil/unix/silcunixschedule.c @@ -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 */ -- 2.24.0