From: Pekka Riikonen Date: Sat, 21 Oct 2006 15:41:38 +0000 (+0000) Subject: Added freelist for timeout tasks for fast task addition. X-Git-Tag: silc.client.1.1.beta1~242 X-Git-Url: http://git.silcnet.org/gitweb/?a=commitdiff_plain;h=6d18348a06478dbb7e7963aa429241b61ebe82fd;p=silc.git Added freelist for timeout tasks for fast task addition. --- diff --git a/lib/silcutil/silcschedule.c b/lib/silcutil/silcschedule.c index 50c6f5dd..495ff366 100644 --- a/lib/silcutil/silcschedule.c +++ b/lib/silcutil/silcschedule.c @@ -215,8 +215,7 @@ static void silc_schedule_task_remove(SilcSchedule schedule, SilcTask task) /* Delete from timeout queue */ silc_list_start(schedule->timeout_queue); - while ((task = (SilcTask)silc_list_get(schedule->timeout_queue)) - != SILC_LIST_END) { + while ((task = silc_list_get(schedule->timeout_queue))) { silc_list_del(schedule->timeout_queue, task); silc_free(task); } @@ -230,7 +229,11 @@ static void silc_schedule_task_remove(SilcSchedule schedule, SilcTask task) while ((ttask = silc_list_get(schedule->timeout_queue)) != SILC_LIST_END) { if (ttask == (SilcTaskTimeout)task) { silc_list_del(schedule->timeout_queue, ttask); - silc_free(ttask); + + /* Put to free list */ + silc_list_add(schedule->free_tasks, ttask); + if (silc_list_count(schedule->free_tasks) == 1) + silc_list_start(schedule->free_tasks); break; } } @@ -243,6 +246,26 @@ static void silc_schedule_task_remove(SilcSchedule schedule, SilcTask task) silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(ftask->fd)); } +#if defined(SILC_DEBUG) +/* Print schedule statistics to stdout */ + +void silc_schedule_stats(SilcSchedule schedule) +{ + SilcTaskFd ftask; + fprintf(stdout, "Schedule %p statistics:\n\n", schedule); + fprintf(stdout, "Num FD tasks: %lu (%lu bytes allocated)\n", + silc_hash_table_count(schedule->fd_queue), + sizeof(*ftask) * silc_hash_table_count(schedule->fd_queue)); + fprintf(stdout, "Num Timeout tasks: %d (%d bytes allocated)\n", + silc_list_count(schedule->timeout_queue), + sizeof(struct SilcTaskTimeoutStruct) * + silc_list_count(schedule->timeout_queue)); + fprintf(stdout, "Num Timeout freelist: %d (%d bytes allocated)\n", + silc_list_count(schedule->free_tasks), + sizeof(struct SilcTaskTimeoutStruct) * + silc_list_count(schedule->free_tasks)); +} +#endif /* SILC_DEBUG */ /****************************** Public API **********************************/ @@ -269,6 +292,7 @@ SilcSchedule silc_schedule_init(int max_tasks, void *app_context) return NULL; silc_list_init(schedule->timeout_queue, struct SilcTaskTimeoutStruct, next); + silc_list_init(schedule->free_tasks, struct SilcTaskTimeoutStruct, next); schedule->app_context = app_context; schedule->valid = TRUE; @@ -290,6 +314,8 @@ SilcSchedule silc_schedule_init(int max_tasks, void *app_context) SilcBool silc_schedule_uninit(SilcSchedule schedule) { + SilcTask task; + SILC_LOG_DEBUG(("Uninitializing scheduler")); if (schedule->valid == TRUE) @@ -307,8 +333,13 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule) } /* Unregister all tasks */ + silc_schedule_task_del(schedule, SILC_ALL_TASKS); silc_schedule_task_remove(schedule, SILC_ALL_TASKS); - silc_schedule_task_remove(schedule, SILC_ALL_TASKS); + + /* Delete timeout task freelist */ + silc_list_start(schedule->free_tasks); + while ((task = silc_list_get(schedule->free_tasks))) + silc_free(task); /* Unregister all task queues */ silc_hash_table_free(schedule->fd_queue); @@ -478,9 +509,15 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd, SILC_SCHEDULE_LOCK(schedule); if (type == SILC_TASK_TIMEOUT) { - SilcTaskTimeout tmp, prev, ttask = silc_calloc(1, sizeof(*ttask)); - if (!ttask) - goto out; + SilcTaskTimeout tmp, prev, ttask; + + ttask = silc_list_get(schedule->free_tasks); + if (!ttask) { + ttask = silc_calloc(1, sizeof(*ttask)); + if (!ttask) + goto out; + } + silc_list_del(schedule->free_tasks, ttask); ttask->header.type = 1; ttask->header.callback = callback; diff --git a/lib/silcutil/silcschedule_i.h b/lib/silcutil/silcschedule_i.h index 45441b64..4abf530d 100644 --- a/lib/silcutil/silcschedule_i.h +++ b/lib/silcutil/silcschedule_i.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2001 - 2005 Pekka Riikonen + Copyright (C) 2001 - 2006 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 @@ -45,9 +45,9 @@ typedef struct SilcTaskTimeoutStruct { /* Fd task */ typedef struct { struct SilcTaskStruct header; + unsigned int events : 15; + unsigned int revents : 15; SilcUInt32 fd; - unsigned int events : 16; - unsigned int revents : 16; } *SilcTaskFd; /* Scheduler context */ @@ -56,6 +56,7 @@ struct SilcScheduleStruct { void *app_context; /* Application specific context */ SilcHashTable fd_queue; /* FD task queue */ SilcList timeout_queue; /* Timeout queue */ + SilcList free_tasks; /* Timeout task freelist */ SilcMutex lock; /* Scheduler lock */ struct timeval timeout; /* Current timeout */ unsigned int max_tasks : 28; /* Max FD tasks */ @@ -119,4 +120,9 @@ typedef struct { void (*signals_unblock)(SilcSchedule schedule, void *context); } SilcScheduleOps; +#if defined(SILC_DEBUG) +/* Print scheduler statistics to stdout. */ +void silc_schedule_stats(SilcSchedule schedule); +#endif /* SILC_DEBUG */ + #endif /* SILCSCHEDULE_I_H */