Added freelist for timeout tasks for fast task addition.
authorPekka Riikonen <priikone@silcnet.org>
Sat, 21 Oct 2006 15:41:38 +0000 (15:41 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sat, 21 Oct 2006 15:41:38 +0000 (15:41 +0000)
lib/silcutil/silcschedule.c
lib/silcutil/silcschedule_i.h

index 50c6f5ddbcb80ba4234be43d4fea910d0e1870d5..495ff3667804ac5a3342997940fa780fc30619b1 100644 (file)
@@ -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;
index 45441b64cd2e28b5fc7560657bc7673f678e8e0e..4abf530d8ec04e9c12214332d1af01593fb1209f 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  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 */