+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
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.
#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)
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;
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;
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;
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;
}
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();
/* 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);
* 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
*
* 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);
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;
if (!schedule->internal) {
silc_hash_table_free(schedule->fd_queue);
silc_mutex_free(schedule->lock);
- silc_free(schedule);
+ silc_stack_free(stack);
return NULL;
}
{
SilcTask task;
- SILC_LOG_DEBUG(("Uninitializing scheduler"));
+ SILC_LOG_DEBUG(("Uninitializing scheduler %p", schedule));
if (schedule->valid == TRUE)
return FALSE;
schedule_ops.uninit(schedule, schedule->internal);
silc_mutex_free(schedule->lock);
- silc_free(schedule);
+ silc_stack_free(schedule->stack);
return TRUE;
}
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,
*
* SYNOPSIS
*
- * SilcSchedule silc_schedule_init(int max_tasks, void *app_context);
+ * SilcSchedule silc_schedule_init(int max_tasks, void *app_context,
+ * SilcStack stack);
*
* DESCRIPTION
*
* 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
*
* 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);
***/
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
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 */
}
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)
}
SILC_LOG_DEBUG(("Allocating scheduler"));
- schedule = silc_schedule_init(0, NULL);
+ schedule = silc_schedule_init(0, NULL, NULL);
if (!schedule)
goto err;
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;;
}
}
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)
}
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)
}
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);
silc_log_set_debug_string("*thread*");
}
- schedule = silc_schedule_init(0, NULL);
+ schedule = silc_schedule_init(0, NULL, NULL);
if (!schedule)
goto err;
SilcUnixScheduler internal;
int i;
- internal = silc_calloc(1, sizeof(*internal));
+ internal = silc_scalloc(schedule->stack, 1, sizeof(*internal));
if (!internal)
return NULL;
#ifdef SILC_THREADS
if (pipe(internal->wakeup_pipe)) {
SILC_LOG_ERROR(("pipe() fails: %s", strerror(errno)));
- silc_free(internal);
return NULL;
}
#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 */