Added silc_schedule_[set|get]_global. Added many APIs to call
[crypto.git] / lib / silcutil / silcschedule.c
index ccd9abdb41328775a331181b00427daeaf7f035e..476d11f1031e3518b39442dab2a7fe31b1242dc8 100644 (file)
@@ -290,14 +290,14 @@ 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",
+  fprintf(stdout, "Num FD tasks         : %d (%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",
+  fprintf(stdout, "Num Timeout tasks    : %d (%lu 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",
+  fprintf(stdout, "Num Timeout freelist : %d (%lu bytes allocated)\n",
          silc_list_count(schedule->free_tasks),
          sizeof(struct SilcTaskTimeoutStruct) *
          silc_list_count(schedule->free_tasks));
@@ -317,6 +317,9 @@ SilcSchedule silc_schedule_init(int max_tasks, void *app_context,
 {
   SilcSchedule schedule;
 
+  /* Initialize Tls, in case it hasn't been done yet */
+  silc_thread_tls_init();
+
   stack = silc_stack_alloc(0, stack);
   if (!stack)
     return NULL;
@@ -373,6 +376,8 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule)
 {
   SilcTask task;
 
+  SILC_VERIFY(schedule);
+
   SILC_LOG_DEBUG(("Uninitializing scheduler %p", schedule));
 
   if (schedule->valid == TRUE)
@@ -417,6 +422,7 @@ SilcBool silc_schedule_uninit(SilcSchedule schedule)
 void silc_schedule_stop(SilcSchedule schedule)
 {
   SILC_LOG_DEBUG(("Stopping scheduler"));
+  SILC_VERIFY(schedule);
   SILC_SCHEDULE_LOCK(schedule);
   schedule->valid = FALSE;
   SILC_SCHEDULE_UNLOCK(schedule);
@@ -572,6 +578,39 @@ void silc_schedule_set_notify(SilcSchedule schedule,
   schedule->notify_context = context;
 }
 
+/* Set global scheduler */
+
+void silc_schedule_set_global(SilcSchedule schedule)
+{
+  SilcTls tls = silc_thread_get_tls();
+
+  if (!tls) {
+    /* Try to initialize Tls */
+    tls = silc_thread_tls_init();
+    SILC_VERIFY(tls);
+    if (!tls)
+      return;
+  }
+
+  SILC_LOG_DEBUG(("Setting global scheduler %p", schedule));
+
+  tls->schedule = schedule;
+}
+
+/* Return global scheduler */
+
+SilcSchedule silc_schedule_get_global(void)
+{
+  SilcTls tls = silc_thread_get_tls();
+
+  if (!tls)
+    return NULL;
+
+  SILC_LOG_DEBUG(("Return global scheduler %p", tls->schedule));
+
+  return tls->schedule;
+}
+
 /* Add new task to the scheduler */
 
 SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
@@ -581,8 +620,19 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
 {
   SilcTask task = NULL;
 
-  if (silc_unlikely(!schedule->valid))
+  if (!schedule) {
+    schedule = silc_schedule_get_global();
+    SILC_VERIFY(schedule);
+    if (!schedule) {
+      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+      return NULL;
+    }
+  }
+
+  if (silc_unlikely(!schedule->valid)) {
+    silc_set_errno(SILC_ERR_NOT_VALID);
     return NULL;
+  }
 
   SILC_SCHEDULE_LOCK(schedule);
 
@@ -661,6 +711,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;
     }
 
@@ -724,6 +775,15 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
 
 SilcBool silc_schedule_task_del(SilcSchedule schedule, SilcTask task)
 {
+  if (!schedule) {
+    schedule = silc_schedule_get_global();
+    SILC_VERIFY(schedule);
+    if (!schedule) {
+      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+      return FALSE;
+    }
+  }
+
   if (silc_unlikely(task == SILC_ALL_TASKS)) {
     SilcHashTableList htl;
 
@@ -781,6 +841,15 @@ SilcBool silc_schedule_task_del_by_fd(SilcSchedule schedule, SilcUInt32 fd)
 
   SILC_LOG_DEBUG(("Unregister task by fd %d", fd));
 
+  if (!schedule) {
+    schedule = silc_schedule_get_global();
+    SILC_VERIFY(schedule);
+    if (!schedule) {
+      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+      return FALSE;
+    }
+  }
+
   SILC_SCHEDULE_LOCK(schedule);
 
   /* fd is unique, so there is only one task with this fd in the table */
@@ -805,6 +874,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;
 }
 
@@ -820,6 +892,15 @@ SilcBool silc_schedule_task_del_by_callback(SilcSchedule schedule,
 
   SILC_LOG_DEBUG(("Unregister task by callback"));
 
+  if (!schedule) {
+    schedule = silc_schedule_get_global();
+    SILC_VERIFY(schedule);
+    if (!schedule) {
+      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+      return FALSE;
+    }
+  }
+
   SILC_SCHEDULE_LOCK(schedule);
 
   /* Delete from fd queue */
@@ -855,6 +936,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;
 }
 
@@ -870,6 +954,15 @@ SilcBool silc_schedule_task_del_by_context(SilcSchedule schedule,
 
   SILC_LOG_DEBUG(("Unregister task by context"));
 
+  if (!schedule) {
+    schedule = silc_schedule_get_global();
+    SILC_VERIFY(schedule);
+    if (!schedule) {
+      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+      return FALSE;
+    }
+  }
+
   SILC_SCHEDULE_LOCK(schedule);
 
   /* Delete from fd queue */
@@ -905,6 +998,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;
 }
 
@@ -924,6 +1020,15 @@ SilcBool silc_schedule_task_del_by_all(SilcSchedule schedule, int fd,
   if (fd)
     return silc_schedule_task_del_by_fd(schedule, fd);
 
+  if (!schedule) {
+    schedule = silc_schedule_get_global();
+    SILC_VERIFY(schedule);
+    if (!schedule) {
+      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+      return FALSE;
+    }
+  }
+
   SILC_SCHEDULE_LOCK(schedule);
 
   /* Delete from timeout queue */
@@ -943,6 +1048,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;
 }
 
@@ -955,8 +1063,19 @@ SilcBool silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
 {
   SilcTaskFd task;
 
-  if (silc_unlikely(!schedule->valid))
+  if (!schedule) {
+    schedule = silc_schedule_get_global();
+    SILC_VERIFY(schedule);
+    if (!schedule) {
+      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+      return FALSE;
+    }
+  }
+
+  if (silc_unlikely(!schedule->valid)) {
+    silc_set_errno(SILC_ERR_NOT_VALID);
     return FALSE;
+  }
 
   SILC_SCHEDULE_LOCK(schedule);
 
@@ -992,8 +1111,19 @@ SilcTaskEvent silc_schedule_get_fd_events(SilcSchedule schedule,
   SilcTaskFd task;
   SilcTaskEvent event = 0;
 
-  if (silc_unlikely(!schedule->valid))
+  if (!schedule) {
+    schedule = silc_schedule_get_global();
+    SILC_VERIFY(schedule);
+    if (!schedule) {
+      silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
+      return 0;
+    }
+  }
+
+  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),