From: Pekka Riikonen Date: Fri, 1 Dec 2006 16:44:20 +0000 (+0000) Subject: Optimized function calls during scheduler. X-Git-Tag: silc.client.1.1.beta1~149 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=e96111e2f7e6119b8286fc5eb5d63a5d3ee400b9;p=silc.git Optimized function calls during scheduler. Added support for zero timeouts. --- diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index 012eca77..8e7690f2 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -123,7 +123,7 @@ static void silc_schedule_dispatch_timeout(SilcSchedule schedule, silc_schedule_task_remove(schedule, t); /* Balance when we have lots of small timeouts */ - if ((++count) > 50) + if ((++count) > 40) break; } } @@ -188,6 +188,7 @@ static void silc_schedule_select_timeout(SilcSchedule schedule) /* Save the timeout */ if (task) { schedule->timeout = curtime; + schedule->has_timeout = TRUE; SILC_LOG_DEBUG(("timeout: sec=%d, usec=%d", schedule->timeout.tv_sec, schedule->timeout.tv_usec)); } @@ -426,70 +427,76 @@ SilcBool silc_schedule_one(SilcSchedule schedule, int timeout_usecs) struct timeval timeout; int ret; - SILC_LOG_DEBUG(("In scheduler loop")); - 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); - schedule_ops.signals_call(schedule, schedule->internal); - schedule->signal_tasks = FALSE; - SILC_SCHEDULE_LOCK(schedule); - } + while (1) { + SILC_LOG_DEBUG(("In scheduler loop")); - /* Check if scheduler is valid */ - if (schedule->valid == FALSE) { - SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting")); - if (!schedule->is_locked) + /* Deliver signals if any has been set to be called */ + if (schedule->signal_tasks) { SILC_SCHEDULE_UNLOCK(schedule); - return FALSE; - } + schedule_ops.signals_call(schedule, schedule->internal); + schedule->signal_tasks = FALSE; + SILC_SCHEDULE_LOCK(schedule); + } - /* Calculate next timeout for silc_select(). This is the timeout value - when at earliest some of the timeout tasks expire. This may dispatch - already expired timeouts. */ - silc_schedule_select_timeout(schedule); + /* Check if scheduler is valid */ + if (schedule->valid == FALSE) { + SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting")); + if (!schedule->is_locked) + SILC_SCHEDULE_UNLOCK(schedule); + return FALSE; + } - /* Check if scheduler is valid */ - if (schedule->valid == FALSE) { - SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting")); - if (!schedule->is_locked) - SILC_SCHEDULE_UNLOCK(schedule); - return FALSE; - } + /* Calculate next timeout for silc_select(). This is the timeout value + when at earliest some of the timeout tasks expire. This may dispatch + already expired timeouts. */ + silc_schedule_select_timeout(schedule); + + /* Check if scheduler is valid */ + if (schedule->valid == FALSE) { + SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting")); + if (!schedule->is_locked) + SILC_SCHEDULE_UNLOCK(schedule); + return FALSE; + } - if (timeout_usecs >= 0) { - timeout.tv_sec = 0; - timeout.tv_usec = timeout_usecs; - schedule->timeout = timeout; - schedule->has_timeout = TRUE; - } + if (timeout_usecs >= 0) { + timeout.tv_sec = 0; + timeout.tv_usec = timeout_usecs; + schedule->timeout = timeout; + schedule->has_timeout = TRUE; + } - /* This is the main silc_select(). The program blocks here until some - of the selected file descriptors change status or the selected - timeout expires. */ - SILC_LOG_DEBUG(("Select")); - ret = schedule_ops.select(schedule, schedule->internal); - - switch (ret) { - case 0: - /* Timeout */ - SILC_LOG_DEBUG(("Running timeout tasks")); - silc_schedule_dispatch_timeout(schedule, FALSE); - break; - case -1: - /* Error */ - if (errno == EINTR) + /* This is the main silc_select(). The program blocks here until some + of the selected file descriptors change status or the selected + timeout expires. */ + SILC_LOG_DEBUG(("Select")); + ret = schedule_ops.select(schedule, schedule->internal); + + switch (ret) { + case 0: + /* Timeout */ + SILC_LOG_DEBUG(("Running timeout tasks")); + if (silc_list_count(schedule->timeout_queue)) + silc_schedule_dispatch_timeout(schedule, FALSE); + break; + case -1: + /* Error */ + if (errno == EINTR) + break; + SILC_LOG_ERROR(("Error in select(): %s", strerror(errno))); + break; + default: + /* There is some data available now */ + SILC_LOG_DEBUG(("Running fd tasks")); + silc_schedule_dispatch_fd(schedule); + break; + } + + if (timeout_usecs >= 0) break; - SILC_LOG_ERROR(("Error in select(): %s", strerror(errno))); - break; - default: - /* There is some data available now */ - SILC_LOG_DEBUG(("Running fd tasks")); - silc_schedule_dispatch_fd(schedule); - break; } if (!schedule->is_locked) @@ -511,13 +518,10 @@ void silc_schedule(SilcSchedule schedule) return; } + /* Start the scheduler loop */ SILC_SCHEDULE_LOCK(schedule); schedule->is_locked = TRUE; - - /* Start the scheduler loop */ - while (silc_schedule_one(schedule, -1)) - ; - + silc_schedule_one(schedule, -1); SILC_SCHEDULE_UNLOCK(schedule); } @@ -579,8 +583,8 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, ttask->header.valid = TRUE; /* Add timeout */ + silc_gettimeofday(&ttask->timeout); if ((seconds + useconds) > 0) { - silc_gettimeofday(&ttask->timeout); ttask->timeout.tv_sec += seconds + (useconds / 1000000L); ttask->timeout.tv_usec += (useconds % 1000000L); if (ttask->timeout.tv_usec >= 1000000L) { diff --git a/lib/silcutil/silcschedule.h b/lib/silcutil/silcschedule.h index 1d1e7e25..e2f4e581 100644 --- a/lib/silcutil/silcschedule.h +++ b/lib/silcutil/silcschedule.h @@ -381,7 +381,8 @@ void *silc_schedule_get_context(SilcSchedule schedule); * Add timeout task to scheduler. The `callback' will be called once * the specified timeout has elapsed. The task will be removed from the * scheduler automatically once the task expires. The event returned - * to the `callback' is SILC_TASK_EXPIRE. + * to the `callback' is SILC_TASK_EXPIRE. The task added with zero (0) + * timeout will be executed immediately next time tasks are scheduled. * ***/ #define silc_schedule_task_add_timeout(schedule, callback, context, s, u) \ diff --git a/lib/silcutil/tests/test_silcschedule.c b/lib/silcutil/tests/test_silcschedule.c index 8afbc9da..19f94b2b 100644 --- a/lib/silcutil/tests/test_silcschedule.c +++ b/lib/silcutil/tests/test_silcschedule.c @@ -48,7 +48,7 @@ SILC_TASK_CALLBACK(cont) SILC_LOG_DEBUG(("Adding %d timeout tasks", NUM_TTASK / 3)); for (i = 0; i < NUM_TTASK / 3; i++) - silc_schedule_task_add_timeout(schedule, timeout, (void *)i, 0, 1); + silc_schedule_task_add_timeout(schedule, timeout, (void *)i, 0, 0); silc_schedule_task_add_timeout(schedule, cont2, (void *)i, 0, 100); }