Merged silc_1_0_branch to trunk.
[silc.git] / lib / silcutil / unix / silcunixschedule.c
index 2bdff338251bc68f921f797b9f1973e0b5938a62..d27ceacdb527beb3de1eef7ac02dc6305d02e7e7 100644 (file)
@@ -4,13 +4,12 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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;
 
@@ -117,10 +118,10 @@ void *silc_schedule_internal_init(SilcSchedule schedule)
     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"));
@@ -131,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)
@@ -176,7 +182,9 @@ void silc_schedule_internal_signal_register(void *context,
   if (!internal)
     return;
 
-  sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
+  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) {
@@ -188,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);
 }
 
@@ -203,7 +211,9 @@ void silc_schedule_internal_signal_unregister(void *context,
   if (!internal)
     return;
 
-  sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
+  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 &&
@@ -216,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);
 }
 
@@ -230,16 +240,19 @@ void silc_schedule_internal_signal_call(void *context, SilcUInt32 signal)
   if (!internal)
     return;
 
-  sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
+  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,
@@ -248,22 +261,27 @@ void silc_schedule_internal_signals_call(void *context,
   SilcUnixScheduler internal = (SilcUnixScheduler)context;
   int i;
 
+  SILC_LOG_DEBUG(("Start"));
+
   if (!internal)
     return;
 
-  sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
+  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. */