X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcschedule.c;h=5ea2ebf00a743da144358d6fd9c506face1902c2;hp=5ca563035b4aa6b3008d82a48e04da47628873ac;hb=c257b555225193e54d85daf541d29578b3c93882;hpb=f658940d02cf2fd893296b6a7825b42502573668 diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index 5ca56303..5ea2ebf0 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -1,10 +1,10 @@ /* - silcschedule.c + silcschedule.c Author: Pekka Riikonen - Copyright (C) 1998 - 2002 Pekka Riikonen + Copyright (C) 1998 - 2003 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 @@ -27,7 +27,7 @@ typedef struct SilcTaskQueueStruct *SilcTaskQueue; /* System specific routines. Implemented under unix/, win32/ and such. */ /* System specific select(). Returns same values as normal select(). */ -int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, +int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, struct timeval *timeout); /* Initializes the platform specific scheduler. This for example initializes @@ -74,7 +74,7 @@ static void silc_schedule_dispatch_timeout(SilcSchedule schedule, static void silc_task_queue_alloc(SilcTaskQueue *queue); static void silc_task_queue_free(SilcTaskQueue queue); static SilcTask silc_task_find(SilcTaskQueue queue, SilcUInt32 fd); -static SilcTask silc_task_add(SilcTaskQueue queue, SilcTask newtask, +static SilcTask silc_task_add(SilcTaskQueue queue, SilcTask newtask, SilcTaskPriority priority); static SilcTask silc_task_get_first(SilcTaskQueue queue, SilcTask first); static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask, @@ -122,7 +122,7 @@ struct SilcTaskStruct { /* SILC Task Queue object. The queue holds all the tasks in the scheduler. There are always three task queues in the scheduler. One for non-timeout - tasks (fd tasks performing tasks over specified file descriptor), + tasks (fd tasks performing tasks over specified file descriptor), one for timeout tasks and one for generic tasks. */ struct SilcTaskQueueStruct { SilcTask task; /* Pointer to all tasks */ @@ -130,10 +130,10 @@ struct SilcTaskQueueStruct { SILC_MUTEX_DEFINE(lock); /* Queue's lock */ }; -/* +/* SILC Scheduler structure. - This is the actual schedule object in SILC. Both SILC client and server + This is the actual schedule object in SILC. Both SILC client and server uses this same scheduler. Actually, this scheduler could be used by any program needing scheduling. @@ -142,7 +142,7 @@ struct SilcTaskQueueStruct { SilcTaskQueue fd_queue Task queue hook for non-timeout tasks. Usually this means that these - tasks perform different kind of I/O on file descriptors. File + tasks perform different kind of I/O on file descriptors. File descriptors are usually network sockets but they actually can be any file descriptors. This hook is initialized in silc_schedule_init function. Timeout tasks should not be added to this queue because @@ -197,7 +197,7 @@ struct SilcTaskQueueStruct { System specific scheduler context. SILC_MUTEX_DEFINE(lock) - + Scheduler lock. bool signal_tasks @@ -314,15 +314,15 @@ bool silc_schedule_reinit(SilcSchedule schedule, int max_tasks) SILC_SCHEDULE_LOCK(schedule); if (schedule->max_fd <= max_tasks) return FALSE; - schedule->fd_list = silc_realloc(schedule->fd_list, + schedule->fd_list = silc_realloc(schedule->fd_list, (sizeof(*schedule->fd_list) * max_tasks)); schedule->max_fd = max_tasks; SILC_SCHEDULE_UNLOCK(schedule); return TRUE; } -/* Stops the schedule even if it is not supposed to be stopped yet. - After calling this, one should call silc_schedule_uninit (after the +/* Stops the schedule even if it is not supposed to be stopped yet. + After calling this, one should call silc_schedule_uninit (after the silc_schedule has returned). */ void silc_schedule_stop(SilcSchedule schedule) @@ -404,7 +404,7 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) execution beacuse the task might have been unregistered in the callback function, ie. it is not valid anymore. */ - /* Is the task ready for reading */ + /* Is the task ready for reading */ if (task->valid && revents & SILC_TASK_READ && fd == schedule->fd_list[i].fd) { silc_mutex_unlock(schedule->generic_queue->lock); @@ -415,7 +415,7 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) silc_mutex_lock(schedule->generic_queue->lock); } - /* Is the task ready for writing */ + /* Is the task ready for writing */ if (task->valid && revents & SILC_TASK_WRITE && fd == schedule->fd_list[i].fd) { silc_mutex_unlock(schedule->generic_queue->lock); @@ -445,7 +445,7 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) break; task = task->next; - } + } silc_mutex_unlock(schedule->generic_queue->lock); } @@ -454,8 +454,8 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule) /* Executes all tasks whose timeout has expired. The task is removed from the task queue after the callback function has returned. Also, invalid - tasks are removed here. We don't have to care about priorities because - tasks are already sorted in their priority order at the registration + tasks are removed here. We don't have to care about priorities because + tasks are already sorted in their priority order at the registration phase. */ /* This holds the schedule->lock and the schedule->timeout_queue->lock */ @@ -474,7 +474,7 @@ static void silc_schedule_dispatch_timeout(SilcSchedule schedule, if (queue && queue->task) { task = queue->task; - /* Walk thorugh all tasks in the particular task queue and run all + /* Walk thorugh all tasks in the particular task queue and run all the expired tasks. */ while(1) { /* Execute the task if the timeout has expired */ @@ -599,7 +599,7 @@ bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs) /* If the task queues aren't initialized or we aren't valid anymore we will return */ - if ((!schedule->fd_queue && !schedule->timeout_queue + if ((!schedule->fd_queue && !schedule->timeout_queue && !schedule->generic_queue) || schedule->valid == FALSE) { SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting")); if (!schedule->is_locked) @@ -625,7 +625,7 @@ bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs) of the selected file descriptors change status or the selected timeout expires. */ SILC_LOG_DEBUG(("Select")); - ret = silc_select(schedule->fd_list, schedule->last_fd + 1, + ret = silc_select(schedule->fd_list, schedule->last_fd + 1, schedule->timeout); SILC_SCHEDULE_LOCK(schedule); @@ -673,7 +673,7 @@ void silc_schedule(SilcSchedule schedule) schedule->is_locked = TRUE; /* Start the scheduler loop */ - while (silc_schedule_one(schedule, -1)) + while (silc_schedule_one(schedule, -1)) ; SILC_SCHEDULE_UNLOCK(schedule); @@ -709,9 +709,9 @@ void *silc_schedule_get_context(SilcSchedule schedule) /* Add new task to the scheduler */ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, - SilcTaskCallback callback, void *context, - long seconds, long useconds, - SilcTaskType type, + SilcTaskCallback callback, void *context, + long seconds, long useconds, + SilcTaskType type, SilcTaskPriority priority) { SilcTask newtask; @@ -722,14 +722,14 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, return NULL; queue = SILC_SCHEDULE_GET_QUEUE(type); - + /* If the task is generic task, we check whether this task has already been registered. Generic tasks are registered only once and after that the same task applies to all file descriptors to be registered. */ if (type == SILC_TASK_GENERIC) { silc_mutex_lock(queue->lock); - SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd, + SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd, type, priority)); if (queue->task) { @@ -737,7 +737,7 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, while(1) { if ((task->callback == callback) && (task->context == context)) { SILC_LOG_DEBUG(("Found matching generic task, using the match")); - + silc_mutex_unlock(queue->lock); /* Add the fd to be listened, the task found now applies to this @@ -745,10 +745,10 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ, FALSE); return task; } - + if (queue->task == task->next) break; - + task = task->next; } } @@ -827,7 +827,7 @@ void silc_schedule_task_del(SilcSchedule schedule, SilcTask task) } next = queue->task; - + while(1) { if (next->valid) next->valid = FALSE; @@ -903,6 +903,7 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd, if (schedule->fd_list[i].fd == fd) { schedule->fd_list[i].fd = fd; schedule->fd_list[i].events = mask; + schedule->fd_list[i].revents = 0; if (i > schedule->last_fd) schedule->last_fd = i; found = TRUE; @@ -918,6 +919,7 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd, if (schedule->fd_list[i].events == 0) { schedule->fd_list[i].fd = fd; schedule->fd_list[i].events = mask; + schedule->fd_list[i].revents = 0; if (i > schedule->last_fd) schedule->last_fd = i; if (send_events) { @@ -944,8 +946,9 @@ void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd) if (schedule->fd_list[i].fd == fd) { schedule->fd_list[i].fd = 0; schedule->fd_list[i].events = 0; - if (schedule->last_fd == i) - schedule->last_fd = schedule->max_fd - 1; + schedule->fd_list[i].revents = 0; + if (schedule->last_fd == i && i > 0) + schedule->last_fd = i - 1; break; } @@ -1019,10 +1022,10 @@ static SilcTask silc_task_find(SilcTaskQueue queue, SilcUInt32 fd) } /* Adds a non-timeout task into the task queue. This function is used - by silc_task_register function. Returns a pointer to the registered + by silc_task_register function. Returns a pointer to the registered task. */ -static SilcTask silc_task_add(SilcTaskQueue queue, SilcTask newtask, +static SilcTask silc_task_add(SilcTaskQueue queue, SilcTask newtask, SilcTaskPriority priority) { SilcTask task, next, prev; @@ -1102,7 +1105,7 @@ static SilcTask silc_task_get_first(SilcTaskQueue queue, SilcTask first) } /* Adds a timeout task into the task queue. This function is used by - silc_task_register function. Returns a pointer to the registered + silc_task_register function. Returns a pointer to the registered task. Timeout tasks are sorted by their timeout value in ascending order. The priority matters if there are more than one task with same timeout. */ @@ -1117,7 +1120,7 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask, /* Take last task from the list */ prev = task->prev; - + switch(priority) { case SILC_TASK_PRI_LOW: /* Lowest priority. The task is added at the end of the list. */ @@ -1141,7 +1144,7 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask, newtask->next = next; prev->next = newtask; next->prev = newtask; - + if (prev == task) { /* Check if we are going to be the first task in the queue */ if (silc_compare_timeval(&prev->timeout, &newtask->timeout)) @@ -1177,7 +1180,7 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask, newtask->next = next; prev->next = newtask; next->prev = newtask; - + if (prev == task) { /* Check if we are going to be the first task in the queue */ if (silc_compare_timeval(&prev->timeout, &newtask->timeout)) @@ -1199,7 +1202,7 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask, } /* Removes (unregisters) a task from particular task queue. This function - is used internally by scheduler. This must be called holding the + is used internally by scheduler. This must be called holding the queue->lock. */ static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task) @@ -1249,7 +1252,7 @@ static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task) queue->task = NULL; if (queue->task == old) queue->task = silc_task_get_first(queue, next); - + silc_free(old); return TRUE; }