/* Register signal */
void silc_schedule_internal_signal_register(void *context,
- SilcUInt32 signal);
+ SilcUInt32 signal,
+ SilcTaskCallback callback,
+ void *callback_context);
/* Unregister signal */
void silc_schedule_internal_signal_unregister(void *context,
- SilcUInt32 signal);
+ SilcUInt32 signal,
+ SilcTaskCallback callback,
+ void *callback_context);
+
+/* Mark signal to be called later. */
+void silc_schedule_internal_signal_call(void *context, SilcUInt32 signal);
+
+/* Call all signals */
+void silc_schedule_internal_signals_call(void *context,
+ SilcSchedule schedule);
/* Block registered signals in scheduler. */
void silc_schedule_internal_signals_block(void *context);
/* SILC Task object. Represents one task in the scheduler. */
struct SilcTaskStruct {
SilcUInt32 fd;
- struct timeval timeout;
- SilcTaskCallback callback;
- void *context;
- bool valid;
- SilcTaskPriority priority;
- SilcTaskType type;
+ SilcTaskCallback callback; /* Task callback */
+ void *context; /* Task callback context */
+ struct timeval timeout; /* Set for timeout tasks */
+ unsigned int valid : 1; /* Set when task is valid */
+ unsigned int priority : 2; /* Priority of the task */
+ unsigned int type : 5; /* Type of the task */
/* Pointers forming doubly linked circular list */
struct SilcTaskStruct *next;
Scheduler lock.
+ bool signal_tasks
+
+ TRUE when tasks has been registered from signals. Next round in
+ scheduler will call the callbacks when this is TRUE.
+
*/
struct SilcScheduleStruct {
SilcTaskQueue fd_queue;
void *internal;
SILC_MUTEX_DEFINE(lock);
bool is_locked;
+ bool signal_tasks;
};
/* Initializes the scheduler. This returns the scheduler context that
/* Initialize the platform specific scheduler. */
schedule->internal = silc_schedule_internal_init(schedule);
- silc_schedule_signal_register(schedule, SIGALRM);
return schedule;
}
if (!schedule->is_locked)
SILC_SCHEDULE_LOCK(schedule);
+ /* Deliver signals if any has been set to be called */
+ if (schedule->signal_tasks) {
+ SILC_SCHEDULE_UNLOCK(schedule);
+ silc_schedule_internal_signals_call(schedule->internal, schedule);
+ schedule->signal_tasks = FALSE;
+ SILC_SCHEDULE_LOCK(schedule);
+ }
+
/* If the task queues aren't initialized or we aren't valid anymore
we will return */
if ((!schedule->fd_queue && !schedule->timeout_queue
/* Register a new signal */
-void silc_schedule_signal_register(SilcSchedule schedule, SilcUInt32 signal)
+void silc_schedule_signal_register(SilcSchedule schedule, SilcUInt32 signal,
+ SilcTaskCallback callback, void *context)
{
- silc_schedule_internal_signal_register(schedule->internal, signal);
+ silc_schedule_internal_signal_register(schedule->internal, signal,
+ callback, context);
}
/* Unregister a new signal */
-void silc_schedule_signal_unregister(SilcSchedule schedule, SilcUInt32 signal)
+void silc_schedule_signal_unregister(SilcSchedule schedule, SilcUInt32 signal,
+ SilcTaskCallback callback, void *context)
+{
+ silc_schedule_internal_signal_unregister(schedule->internal, signal,
+ callback, context);
+}
+
+/* Call signal indicated by `signal'. */
+
+void silc_schedule_signal_call(SilcSchedule schedule, SilcUInt32 signal)
{
- silc_schedule_internal_signal_unregister(schedule->internal, signal);
+ /* Mark that signals needs to be delivered later. */
+ silc_schedule_internal_signal_call(schedule->internal, signal);
+ schedule->signal_tasks = TRUE;
}
/* Allocates a newtask task queue into the scheduler */