X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Funix%2Fsilcunixschedule.c;h=d27ceacdb527beb3de1eef7ac02dc6305d02e7e7;hb=c257b555225193e54d85daf541d29578b3c93882;hp=de64bd58b64e693203637ff0e3f9931ee310c9d5;hpb=a99a10531dd74835b7265e752307a80577e596b2;p=silc.git diff --git a/lib/silcutil/unix/silcunixschedule.c b/lib/silcutil/unix/silcunixschedule.c index de64bd58..d27ceacd 100644 --- a/lib/silcutil/unix/silcunixschedule.c +++ b/lib/silcutil/unix/silcunixschedule.c @@ -4,13 +4,12 @@ Author: Pekka Riikonen - Copyright (C) 1998 - 2001 Pekka Riikonen + Copyright (C) 1998 - 2004 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - + the Free Software Foundation; version 2 of the License. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -24,7 +23,7 @@ /* Calls normal select() system call. */ -int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, +int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, struct timeval *timeout) { fd_set in, out; @@ -76,6 +75,7 @@ typedef struct { /* Internal context. */ typedef struct { + void *app_context; int wakeup_pipe[2]; SilcTask wakeup_task; sigset_t signals; @@ -100,7 +100,8 @@ SILC_TASK_CALLBACK(silc_schedule_wakeup_cb) the scheduler needs to be wakenup when tasks are added or removed from the task queues. Returns context to the platform specific scheduler. */ -void *silc_schedule_internal_init(SilcSchedule schedule) +void *silc_schedule_internal_init(SilcSchedule schedule, + void *app_context) { SilcUnixScheduler internal; @@ -112,16 +113,18 @@ 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; } - internal->wakeup_task = + internal->wakeup_task = silc_schedule_task_add(schedule, internal->wakeup_pipe[0], silc_schedule_wakeup_cb, internal, - 0, 0, SILC_TASK_FD, + 0, 0, SILC_TASK_FD, SILC_TASK_PRI_NORMAL); if (!internal->wakeup_task) { + SILC_LOG_ERROR(("Could not add a wakeup task, threads won't work")); close(internal->wakeup_pipe[0]); close(internal->wakeup_pipe[1]); silc_free(internal); @@ -129,9 +132,14 @@ void *silc_schedule_internal_init(SilcSchedule schedule) } #endif + internal->app_context = app_context; + return (void *)internal; } +void silc_schedule_internal_signals_block(void *context); +void silc_schedule_internal_signals_unblock(void *context); + /* Uninitializes the platform specific scheduler context. */ void silc_schedule_internal_uninit(void *context) @@ -171,7 +179,12 @@ void silc_schedule_internal_signal_register(void *context, SilcUnixScheduler internal = (SilcUnixScheduler)context; int i; - sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked); + if (!internal) + return; + + SILC_LOG_DEBUG(("Registering signal %d", signal)); + + silc_schedule_internal_signals_block(context); for (i = 0; i < SIGNAL_COUNT; i++) { if (!internal->signal_call[i].signal) { @@ -183,7 +196,7 @@ void silc_schedule_internal_signal_register(void *context, } } - sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL); + silc_schedule_internal_signals_unblock(context); sigaddset(&internal->signals, signal); } @@ -195,7 +208,12 @@ void silc_schedule_internal_signal_unregister(void *context, SilcUnixScheduler internal = (SilcUnixScheduler)context; int i; - sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked); + if (!internal) + return; + + SILC_LOG_DEBUG(("Unregistering signal %d", signal)); + + silc_schedule_internal_signals_block(context); for (i = 0; i < SIGNAL_COUNT; i++) { if (internal->signal_call[i].signal == signal && @@ -208,7 +226,7 @@ void silc_schedule_internal_signal_unregister(void *context, } } - sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL); + silc_schedule_internal_signals_unblock(context); sigdelset(&internal->signals, signal); } @@ -219,16 +237,22 @@ void silc_schedule_internal_signal_call(void *context, SilcUInt32 signal) SilcUnixScheduler internal = (SilcUnixScheduler)context; int i; - sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked); + if (!internal) + return; + + silc_schedule_internal_signals_block(context); for (i = 0; i < SIGNAL_COUNT; i++) { - if (internal->signal_call[i].signal == signal) + if (internal->signal_call[i].signal == signal) { internal->signal_call[i].call = TRUE; + SILC_LOG_DEBUG(("Scheduling signal %d to be called", + internal->signal_call[i].signal)); + } } - sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL); + silc_schedule_internal_signals_unblock(context); } - + /* Call all signals */ void silc_schedule_internal_signals_call(void *context, @@ -237,19 +261,27 @@ void silc_schedule_internal_signals_call(void *context, SilcUnixScheduler internal = (SilcUnixScheduler)context; int i; - sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked); + SILC_LOG_DEBUG(("Start")); + + if (!internal) + return; + + silc_schedule_internal_signals_block(context); for (i = 0; i < SIGNAL_COUNT; i++) { if (internal->signal_call[i].call && internal->signal_call[i].callback) { - internal->signal_call[i].callback(schedule, SILC_TASK_INTERRUPT, + SILC_LOG_DEBUG(("Calling signal %d callback", + internal->signal_call[i].signal)); + internal->signal_call[i].callback(schedule, internal->app_context, + SILC_TASK_INTERRUPT, internal->signal_call[i].signal, internal->signal_call[i].context); internal->signal_call[i].call = FALSE; } } - sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL); + silc_schedule_internal_signals_unblock(context); } /* Block registered signals in scheduler. */ @@ -257,6 +289,10 @@ void silc_schedule_internal_signals_call(void *context, void silc_schedule_internal_signals_block(void *context) { SilcUnixScheduler internal = (SilcUnixScheduler)context; + + if (!internal) + return; + sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked); } @@ -265,5 +301,9 @@ void silc_schedule_internal_signals_block(void *context) void silc_schedule_internal_signals_unblock(void *context) { SilcUnixScheduler internal = (SilcUnixScheduler)context; + + if (!internal) + return; + sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL); }