Added SILC errno API. Added SilcResult, generic error code and
[silc.git] / lib / silcutil / silcschedule.c
index bdda281e280e36e9444e586cf987fde08b34e37e..d2ad0c924ccac83c9b124e9485bea30b5b42d470 100644 (file)
@@ -201,12 +201,12 @@ static void silc_schedule_task_remove(SilcSchedule schedule, SilcTask task)
   if (silc_unlikely(task == SILC_ALL_TASKS)) {
     SilcTask task;
     SilcHashTableList htl;
-    SilcUInt32 fd;
+    void *fd;
 
     /* Delete from fd queue */
     silc_hash_table_list(schedule->fd_queue, &htl);
-    while (silc_hash_table_get(&htl, (void *)&fd, (void *)&task))
-      silc_hash_table_del(schedule->fd_queue, SILC_32_TO_PTR(fd));
+    while (silc_hash_table_get(&htl, &fd, (void *)&task))
+      silc_hash_table_del(schedule->fd_queue, fd);
     silc_hash_table_list_reset(&htl);
 
     /* Delete from timeout queue */
@@ -312,27 +312,38 @@ void silc_schedule_stats(SilcSchedule schedule)
    scheduler can handle. The `app_context' is application specific
    context that is delivered to task callbacks. */
 
-SilcSchedule silc_schedule_init(int max_tasks, void *app_context)
+SilcSchedule silc_schedule_init(int max_tasks, void *app_context,
+                               SilcStack stack)
 {
   SilcSchedule schedule;
 
-  SILC_LOG_DEBUG(("Initializing scheduler"));
+  /* Initialize Tls, in case it hasn't been done yet */
+  silc_thread_tls_init();
+
+  stack = silc_stack_alloc(0, stack);
+  if (!stack)
+    return NULL;
 
-  schedule = silc_calloc(1, sizeof(*schedule));
+  /* Allocate scheduler from the stack */
+  schedule = silc_scalloc(stack, 1, sizeof(*schedule));
   if (!schedule)
     return NULL;
 
+  SILC_LOG_DEBUG(("Initializing scheduler %p", schedule));
+
+  /* Allocate Fd task hash table dynamically */
   schedule->fd_queue =
     silc_hash_table_alloc(NULL, 0, silc_hash_uint, NULL, NULL, NULL,
                          silc_schedule_fd_destructor, NULL, TRUE);
   if (!schedule->fd_queue) {
-    silc_free(schedule);
+    silc_stack_free(stack);
     return NULL;
   }
 
   silc_list_init(schedule->timeout_queue, struct SilcTaskStruct, next);
   silc_list_init(schedule->free_tasks, struct SilcTaskStruct, next);
 
+  schedule->stack = stack;
   schedule->app_context = app_context;
   schedule->valid = TRUE;
   schedule->max_tasks = max_tasks;
@@ -345,7 +356,7 @@ SilcSchedule silc_schedule_init(int max_tasks, void *app_context)
   if (!schedule->internal) {
     silc_hash_table_free(schedule->fd_queue);
     silc_mutex_free(schedule->lock);
-    silc_free(schedule);
+    silc_stack_free(stack);
     return NULL;
   }
 
@@ -365,7 +376,7 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule)
 {
   SilcTask task;
 
-  SILC_LOG_DEBUG(("Uninitializing scheduler"));
+  SILC_LOG_DEBUG(("Uninitializing scheduler %p", schedule));
 
   if (schedule->valid == TRUE)
     return FALSE;
@@ -397,7 +408,7 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule)
   schedule_ops.uninit(schedule, schedule->internal);
 
   silc_mutex_free(schedule->lock);
-  silc_free(schedule);
+  silc_stack_free(schedule->stack);
 
   return TRUE;
 }
@@ -548,6 +559,13 @@ void *silc_schedule_get_context(SilcSchedule schedule)
   return schedule->app_context;
 }
 
+/* Return the stack of the scheduler */
+
+SilcStack silc_schedule_get_stack(SilcSchedule schedule)
+{
+  return schedule->stack;
+}
+
 /* Set notify callback */
 
 void silc_schedule_set_notify(SilcSchedule schedule,
@@ -566,8 +584,10 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
 {
   SilcTask task = NULL;
 
-  if (silc_unlikely(!schedule->valid))
+  if (silc_unlikely(!schedule->valid)) {
+    silc_set_errno(SILC_ERR_NOT_VALID);
     return NULL;
+  }
 
   SILC_SCHEDULE_LOCK(schedule);
 
@@ -646,6 +666,7 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
                      schedule->max_tasks)) {
       SILC_LOG_WARNING(("Scheduler task limit reached: cannot add new task"));
       task = NULL;
+      silc_set_errno(SILC_ERR_LIMIT);
       goto out;
     }
 
@@ -790,6 +811,9 @@ SilcBool silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd)
     ret = TRUE;
   }
 
+  if (ret == FALSE)
+    silc_set_errno(SILC_ERR_NOT_FOUND);
+
   return ret;
 }
 
@@ -840,6 +864,9 @@ SilcBool silc_schedule_task_del_by_callback(SilcSchedule schedule,
 
   SILC_SCHEDULE_UNLOCK(schedule);
 
+  if (ret == FALSE)
+    silc_set_errno(SILC_ERR_NOT_FOUND);
+
   return ret;
 }
 
@@ -890,6 +917,9 @@ SilcBool silc_schedule_task_del_by_context(SilcSchedule schedule,
 
   SILC_SCHEDULE_UNLOCK(schedule);
 
+  if (ret == FALSE)
+    silc_set_errno(SILC_ERR_NOT_FOUND);
+
   return ret;
 }
 
@@ -928,6 +958,9 @@ SilcBool silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
 
   SILC_SCHEDULE_UNLOCK(schedule);
 
+  if (ret == FALSE)
+    silc_set_errno(SILC_ERR_NOT_FOUND);
+
   return TRUE;
 }
 
@@ -940,8 +973,10 @@ SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
 {
   SilcTaskFd task;
 
-  if (silc_unlikely(!schedule->valid))
+  if (silc_unlikely(!schedule->valid)) {
+    silc_set_errno(SILC_ERR_NOT_VALID);
     return FALSE;
+  }
 
   SILC_SCHEDULE_LOCK(schedule);
 
@@ -977,8 +1012,10 @@ SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule,
   SilcTaskFd task;
   SilcTaskEvent event = 0;
 
-  if (silc_unlikely(!schedule->valid))
+  if (silc_unlikely(!schedule->valid)) {
+    silc_set_errno(SILC_ERR_NOT_VALID);
     return 0;
+  }
 
   SILC_SCHEDULE_LOCK(schedule);
   if (silc_hash_table_find(schedule->fd_queue, SILC_32_TO_PTR(fd),