}
/* Execute the task if the timeout has expired */
- if (!silc_compare_timeval(&task->timeout, &curtime) && !dispatch_all)
+ if (silc_compare_timeval(&task->timeout, &curtime) > 0 && !dispatch_all)
break;
t->valid = FALSE;
/* If the timeout is in past, we will run the task and all other
timeout tasks from the past. */
- if (silc_compare_timeval(&task->timeout, &curtime) && dispatch) {
+ if (silc_compare_timeval(&task->timeout, &curtime) <= 0 && dispatch) {
silc_schedule_dispatch_timeout(schedule, FALSE);
if (silc_unlikely(!schedule->valid))
return;
/* Delete from fd queue */
silc_hash_table_list(schedule->fd_queue, &htl);
- while (silc_hash_table_get(&htl, (void **)&fd, (void **)&task))
+ while (silc_hash_table_get(&htl, (void *)&fd, (void *)&task))
silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(fd));
silc_hash_table_list_reset(&htl);
schedule->fd_queue =
silc_hash_table_alloc(0, silc_hash_uint, NULL, NULL, NULL,
silc_schedule_fd_destructor, NULL, TRUE);
- if (!schedule->fd_queue)
+ if (!schedule->fd_queue) {
+ silc_free(schedule);
return NULL;
+ }
silc_list_init(schedule->timeout_queue, struct SilcTaskStruct, next);
silc_list_init(schedule->free_tasks, struct SilcTaskStruct, next);
/* Initialize the platform specific scheduler. */
schedule->internal = schedule_ops.init(schedule, app_context);
+ if (!schedule->internal) {
+ silc_hash_table_free(schedule->fd_queue);
+ silc_mutex_free(schedule->lock);
+ silc_free(schedule);
+ return NULL;
+ }
/* Timeout freelist garbage collection */
silc_schedule_task_add_timeout(schedule, silc_schedule_timeout_gc,
continue;
} else {
- /* Error */
- if (silc_likely(errno == EINTR))
+ /* Error or special case handling */
+ if (errno == EINTR)
continue;
+ if (ret == -2)
+ break;
+
SILC_LOG_ERROR(("Error in select()/poll(): %s", strerror(errno)));
continue;
}
/* Runs the scheduler and blocks here. When this returns the scheduler
has ended. */
+#ifndef SILC_SYMBIAN
void silc_schedule(SilcSchedule schedule)
{
SILC_LOG_DEBUG(("Running scheduler"));
silc_schedule_iterate(schedule, -1);
SILC_SCHEDULE_UNLOCK(schedule);
}
+#endif /* !SILC_SYMBIAN */
/* Wakes up the scheduler. This is used only in multi-threaded
environments where threads may add new tasks or remove old tasks
ttask = silc_calloc(1, sizeof(*ttask));
if (silc_unlikely(!ttask))
goto out;
- }
- silc_list_del(schedule->free_tasks, ttask);
+ } else
+ silc_list_del(schedule->free_tasks, ttask);
ttask->header.type = 1;
ttask->header.callback = callback;
prev = NULL;
while ((tmp = silc_list_get(list)) != SILC_LIST_END) {
/* If we have shorter timeout, we have found our spot */
- if (silc_compare_timeval(&ttask->timeout, &tmp->timeout)) {
+ if (silc_compare_timeval(&ttask->timeout, &tmp->timeout) < 0) {
silc_list_insert(schedule->timeout_queue, prev, ttask);
break;
}
/* Check if fd is already added */
if (silc_unlikely(silc_hash_table_find(schedule->fd_queue,
SILC_32_TO_PTR(fd),
- NULL, (void **)&task))) {
+ NULL, (void *)&task))) {
if (task->valid)
goto out;
out:
SILC_SCHEDULE_UNLOCK(schedule);
+
+#ifdef SILC_SYMBIAN
+ /* On symbian we wakeup scheduler immediately after adding timeout task
+ in case the task is added outside the scheduler loop (in some active
+ object). */
+ if (task && task->type == 1)
+ silc_schedule_wakeup(schedule);
+#endif /* SILC_SYMBIAN */
+
return task;
}
/* Delete from fd queue */
silc_hash_table_list(schedule->fd_queue, &htl);
- while (silc_hash_table_get(&htl, NULL, (void **)&task))
+ while (silc_hash_table_get(&htl, NULL, (void *)&task))
task->valid = FALSE;
silc_hash_table_list_reset(&htl);
/* fd is unique, so there is only one task with this fd in the table */
if (silc_likely(silc_hash_table_find(schedule->fd_queue,
SILC_32_TO_PTR(fd), NULL,
- (void **)&task))) {
+ (void *)&task))) {
SILC_LOG_DEBUG(("Deleting task %p", task));
task->valid = FALSE;
ret = TRUE;
/* Delete from fd queue */
silc_hash_table_list(schedule->fd_queue, &htl);
- while (silc_hash_table_get(&htl, NULL, (void **)&task)) {
+ while (silc_hash_table_get(&htl, NULL, (void *)&task)) {
if (task->callback == callback) {
task->valid = FALSE;
ret = TRUE;
/* Delete from fd queue */
silc_hash_table_list(schedule->fd_queue, &htl);
- while (silc_hash_table_get(&htl, NULL, (void **)&task)) {
+ while (silc_hash_table_get(&htl, NULL, (void *)&task)) {
if (task->context == context) {
task->valid = FALSE;
ret = TRUE;
SILC_SCHEDULE_LOCK(schedule);
if (silc_hash_table_find(schedule->fd_queue, SILC_32_TO_PTR(fd),
- NULL, (void **)&task)) {
+ NULL, (void *)&task)) {
if (!schedule_ops.schedule_fd(schedule, schedule->internal, task, mask)) {
SILC_SCHEDULE_UNLOCK(schedule);
return FALSE;
SILC_SCHEDULE_LOCK(schedule);
if (silc_hash_table_find(schedule->fd_queue, SILC_32_TO_PTR(fd),
- NULL, (void **)&task))
+ NULL, (void *)&task))
event = task->events;
SILC_SCHEDULE_UNLOCK(schedule);