Added sort-of Quality of Service (QoS) support to the
[silc.git] / lib / silcutil / silcschedule.c
index af37e9fc10729166dfd591d78ed0d5e3bdae2d50..515d3a9fc8134e92567fb407957f1c0c3cd30510 100644 (file)
@@ -81,8 +81,6 @@ static SilcTask silc_task_get_first(SilcTaskQueue queue, SilcTask first);
 static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
                                      SilcTaskPriority priority);
 static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task);
-static int silc_schedule_task_timeout_compare(struct timeval *smaller, 
-                                             struct timeval *bigger);
 static void silc_task_del_by_context(SilcTaskQueue queue, void *context);
 static void silc_task_del_by_callback(SilcTaskQueue queue,
                                      SilcTaskCallback callback);
@@ -479,7 +477,7 @@ static void silc_schedule_dispatch_timeout(SilcSchedule schedule,
     while(1) {
       /* Execute the task if the timeout has expired */
       if (dispatch_all ||
-         silc_schedule_task_timeout_compare(&task->timeout, &curtime)) {
+         silc_compare_timeval(&task->timeout, &curtime)) {
         if (task->valid) {
          silc_mutex_unlock(queue->lock);
          SILC_SCHEDULE_UNLOCK(schedule);
@@ -533,7 +531,7 @@ static void silc_schedule_select_timeout(SilcSchedule schedule)
     if (task && task->valid == TRUE) {
       /* If the timeout is in past, we will run the task and all other
         timeout tasks from the past. */
-      if (silc_schedule_task_timeout_compare(&task->timeout, &curtime)) {
+      if (silc_compare_timeval(&task->timeout, &curtime)) {
        silc_schedule_dispatch_timeout(schedule, FALSE);
 
        /* The task(s) has expired and doesn't exist on the task queue
@@ -742,7 +740,7 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
 
          /* Add the fd to be listened, the task found now applies to this
             fd as well. */
-         silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ);
+         silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ, FALSE);
          return task;
        }
        
@@ -781,7 +779,7 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
   /* If the task is non-timeout task we have to tell the scheduler that we
      would like to have these tasks scheduled at some odd distant future. */
   if (type != SILC_TASK_TIMEOUT)
-    silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ);
+    silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ, FALSE);
 
   silc_mutex_lock(queue->lock);
 
@@ -882,8 +880,8 @@ void silc_schedule_task_del_by_context(SilcSchedule schedule, void *context)
    call this directly if wanted. This can be called multiple times for
    one file descriptor to set different iomasks. */
 
-void silc_schedule_set_listen_fd(SilcSchedule schedule,
-                                SilcUInt32 fd, SilcTaskEvent iomask)
+void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
+                                SilcTaskEvent mask, bool send_events)
 {
   int i;
   bool found = FALSE;
@@ -896,10 +894,14 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule,
   for (i = 0; i < schedule->max_fd; i++)
     if (schedule->fd_list[i].fd == fd) {
       schedule->fd_list[i].fd = fd;
-      schedule->fd_list[i].events = iomask;
+      schedule->fd_list[i].events = mask;
       if (i > schedule->last_fd)
        schedule->last_fd = i;
       found = TRUE;
+      if (send_events) {
+       schedule->fd_list[i].revents = mask;
+       silc_schedule_dispatch_nontimeout(schedule);
+      }
       break;
     }
 
@@ -907,9 +909,13 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule,
     for (i = 0; i < schedule->max_fd; i++)
       if (schedule->fd_list[i].events == 0) {
        schedule->fd_list[i].fd = fd;
-       schedule->fd_list[i].events = iomask;
+       schedule->fd_list[i].events = mask;
        if (i > schedule->last_fd)
          schedule->last_fd = i;
+       if (send_events) {
+         schedule->fd_list[i].revents = mask;
+         silc_schedule_dispatch_nontimeout(schedule);
+       }
        break;
       }
 
@@ -1078,7 +1084,7 @@ static SilcTask silc_task_get_first(SilcTaskQueue queue, SilcTask first)
     if (first == prev)
       break;
 
-    if (silc_schedule_task_timeout_compare(&prev->timeout, &task->timeout))
+    if (silc_compare_timeval(&prev->timeout, &task->timeout))
       task = prev;
 
     prev = prev->prev;
@@ -1111,13 +1117,11 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
 
       /* If we have longer timeout than with the task head of us
         we have found our spot. */
-      if (silc_schedule_task_timeout_compare(&prev->timeout, 
-                                            &newtask->timeout))
+      if (silc_compare_timeval(&prev->timeout, &newtask->timeout))
        break;
 
       /* If we are equal size of timeout we will be after it. */
-      if (!silc_schedule_task_timeout_compare(&newtask->timeout, 
-                                             &prev->timeout))
+      if (!silc_compare_timeval(&newtask->timeout, &prev->timeout))
        break;
 
       /* We have shorter timeout, compare to next one. */
@@ -1132,11 +1136,9 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
     
     if (prev == task) {
       /* Check if we are going to be the first task in the queue */
-      if (silc_schedule_task_timeout_compare(&prev->timeout, 
-                                            &newtask->timeout))
+      if (silc_compare_timeval(&prev->timeout, &newtask->timeout))
        break;
-      if (!silc_schedule_task_timeout_compare(&newtask->timeout, 
-                                             &prev->timeout))
+      if (!silc_compare_timeval(&newtask->timeout, &prev->timeout))
        break;
 
       /* We are now the first task in queue */
@@ -1150,13 +1152,11 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
 
       /* If we have longer timeout than with the task head of us
         we have found our spot. */
-      if (silc_schedule_task_timeout_compare(&prev->timeout, 
-                                            &newtask->timeout))
+      if (silc_compare_timeval(&prev->timeout, &newtask->timeout))
        break;
 
       /* If we are equal size of timeout, priority kicks in place. */
-      if (!silc_schedule_task_timeout_compare(&newtask->timeout, 
-                                             &prev->timeout))
+      if (!silc_compare_timeval(&newtask->timeout, &prev->timeout))
        if (prev->priority >= SILC_TASK_PRI_NORMAL)
          break;
 
@@ -1172,11 +1172,9 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
     
     if (prev == task) {
       /* Check if we are going to be the first task in the queue */
-      if (silc_schedule_task_timeout_compare(&prev->timeout, 
-                                            &newtask->timeout))
+      if (silc_compare_timeval(&prev->timeout, &newtask->timeout))
        break;
-      if (!silc_schedule_task_timeout_compare(&newtask->timeout, 
-                                             &prev->timeout))
+      if (!silc_compare_timeval(&newtask->timeout, &prev->timeout))
        if (prev->priority >= SILC_TASK_PRI_NORMAL)
          break;
 
@@ -1255,20 +1253,6 @@ static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task)
   }
 }
 
-/* Compare two time values. If the first argument is smaller than the
-   second this function returns TRUE. */
-
-static int silc_schedule_task_timeout_compare(struct timeval *smaller, 
-                                             struct timeval *bigger)
-{
-  if ((smaller->tv_sec < bigger->tv_sec) ||
-      ((smaller->tv_sec == bigger->tv_sec) &&
-       (smaller->tv_usec < bigger->tv_usec)))
-    return TRUE;
-
-  return FALSE;
-}
-
 static void silc_task_del_by_fd(SilcTaskQueue queue, SilcUInt32 fd)
 {
   SilcTask next;