5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1998 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
29 File descriptor. This usually is a network socket but can be
30 any file descriptor. On generic tasks, that applies to all file
31 descriptors, this is set to -1.
33 struct timeval timeout
35 The timeout when this task is supposed to be run. This is defined
36 only if the task is a timeout task.
40 Context structure passed to callback function as argument.
42 SilcTaskCallback callback
44 The callback function Silc scheduler calls when this task is scheduled
45 to be run. First argument is the task queue this task belongs to. This
46 is a void pointer and the task queue has to casted out of it. Second
47 argument is the type of the event just occured inside the scheduler
48 (SILC_TASK_READ or SILC_TASK_WRITE). Third argument is the context
49 structure of the task. Last argument is the file descriptor of the
54 Marks for validity of the task. Task that is not valid scheduler
55 will skip. This is boolean value.
59 Priority of the task. This field is used internally only and it
60 should not be touched otherwise.
64 I/O mask which tells to the scheduler for what kind of I/O this
65 task is ready. If the task is ready for both reading and writing
66 SILC_TASK_READ and SILC_TASK_WRITE are masked into this variable.
67 Masking is done by OR'ing (1 << SILC_TASK_*) values. One can check
68 the mask by AND'ing (1L << SILC_TASK_*) against the mask. At the
69 registering of a new task this mask is set to SILC_TASK_READ by
70 default. If a task doesn't perform reading this value must be
71 reset to SILC_TASK_WRITE. If it performs both reading and writing
72 SILC_TASK_WRITE must be added to the mask. A task must always be
73 ready for at least for one I/O type.
75 struct SilcTaskStruct *next
76 struct SilcTaskStruct *prev
78 Next and previous task. If the task is first in the list, prev is
79 set to the last task in the list. If the task is last in the list,
80 next is set to the first task in the list (forms a circular list).
84 typedef void (*SilcTaskCallback)(void *, int, void *, int);
86 typedef struct SilcTaskStruct {
88 struct timeval timeout;
90 SilcTaskCallback callback;
95 struct SilcTaskStruct *next;
96 struct SilcTaskStruct *prev;
99 typedef SilcTaskObject *SilcTask;
104 SILC has three types of tasks, non-timeout tasks (tasks that perform
105 over file descriptors), timeout tasks and generic tasks (tasks that apply
106 to every file descriptor). This type is sent as argument for the
107 task registering function.
117 SILC Task priorities.
119 Following description of the priorities uses timeout tasks as example
120 how the priority behaves. However, non-timeout tasks behaves same as
121 timeout tasks with following priorities.
125 Lowest priority. The task is scheduled to run after its timeout
126 has expired only and only when every other task with higher priority
127 has already been run. For non-timeout tasks this priority behaves
128 same way. Life is not fair for tasks with this priority.
132 Normal priority that is used mostly in Silc. This is priority that
133 should always be used unless you specificly need some other priority.
134 The scheduler will run this task as soon as its timeout has expired.
135 For non-timeout tasks this priority behaves same way. Tasks are run
136 in FIFO (First-In-First-Out) order.
141 SILC_TASK_PRI_NORMAL,
145 SILC Task Queue object.
147 Usually there are three task queues in SILC. Tasks with timeouts
148 has their own queue, tasks without timeout has one as well and generic
149 tasks has their own also. Scheduler has timeout queue hooks and
150 non-timeout queue hooks in the scheduler and it does not check for
151 timeouts in non-timeout hooks and vice versa, respectively. Ie. Register
152 timeout queues to their own SilcTaskQueue pointer and non-timeout queues
153 to their own pointer.
155 Generic tasks, mentioned earlier, has their own task queue. These tasks
156 are non-timeout tasks and they apply to all file descriptors, except to
157 those that have explicitly registered a non-timeout task. These tasks
158 are there to make it simpler and faster to execute common code that
159 applies to all connections. These are, for example, receiving packets
160 from network and sending packets to network. It doesn't make much sense
161 to register a task that receives a packet from network to every connection
162 when you can have one task that applies to all connections. This is what
163 generic tasks are for. Generic tasks are not bound to any specific file
164 descriptor, however, the correct file descriptor must be passed as
165 argument to task registering function.
167 Short description of the field following:
171 Pointer to the tasks in the queue.
175 Marks for validity of the queue. If the task queue is not valid
176 scheduler will skip it. This is boolean value.
178 struct timeval timeout
180 Timeout when earliest some tasks in this queue should expire. The
181 value of this timeout is updated automatically by schedule. This
182 is used only and only if this queue is a timeout queue. For normal
183 task queue this is not defined. This is meant only for internal
184 use and it should be considered to be read-only field.
188 typedef struct SilcTaskQueueStruct {
191 struct timeval timeout;
192 } SilcTaskQueueObject;
194 typedef SilcTaskQueueObject *SilcTaskQueue;
196 /* Marks for all tasks in a task queue. This can be passed to
197 unregister_task function to cancel all tasks at once. */
198 #define SILC_ALL_TASKS ((SilcTask)1)
200 /* Marks for all task queues. This can be passed to
201 silc_task_queue_unregister function to cancel all task queues at once. */
202 #define SILC_ALL_TASK_QUEUES ((SilcTaskQueue)1)
204 /* Silc Task event types. One of these are passed to the task callback
205 function from the schedule. These values are also masked into a task
206 so that scheduler knows for what kind of I/O it needs to perform
208 #define SILC_TASK_READ 0
209 #define SILC_TASK_WRITE 1
213 /* These can be used instead of calling directly the registering function.
214 XXX: These are not used currently, maybe they should be :) */
215 #define SILC_REGISTER_FD_TASK(queue, fd, cb, ctx, pri) \
216 (silc_task_register((queue), (fd), (cb), (ctx), 0, 0, \
217 SILC_TASK_FD, (pri)))
218 #define SILC_REGISTER_TIMEOUT_TASK(queue, fd, cb, ctx, sec, usec, pri) \
219 (silc_task_register((queue), (fd), (cb), (ctx), (sec), (usec), \
220 SILC_TASK_TIMEOUT, (pri)))
221 #define SILC_REGISTER_GENERIC_TASK(queue, fd, cb, ctx, pri) \
222 (silc_task_register((queue), (fd), (cb), (ctx), 0, 0, \
223 SILC_TASK_GENERIC, (pri)))
225 /* Generic macro to define task callback functions. This defines a function
226 with name 'func' as a task callback function. */
227 #define SILC_TASK_CALLBACK(func) \
228 static void func(void *qptr, int type, void *context, int fd)
229 #define SILC_TASK_CALLBACK_GLOBAL(func) \
230 void func(void *qptr, int type, void *context, int fd)
233 void silc_task_queue_alloc(SilcTaskQueue *new, int valid);
234 void silc_task_queue_free(SilcTaskQueue old);
235 SilcTask silc_task_add(SilcTaskQueue queue, SilcTask new,
236 SilcTaskPriority priority);
237 SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask new,
238 SilcTaskPriority priority);
239 SilcTask silc_task_register(SilcTaskQueue queue, int fd,
240 SilcTaskCallback cb, void *context,
241 long seconds, long useconds,
243 SilcTaskPriority priority);
244 int silc_task_remove(SilcTaskQueue queue, SilcTask task);
245 void silc_task_unregister(SilcTaskQueue queue, SilcTask task);
246 void silc_task_unregister_by_fd(SilcTaskQueue queue, int fd);
247 void silc_task_unregister_by_callback(SilcTaskQueue queue,
248 SilcTaskCallback callback);
249 void silc_task_unregister_by_context(SilcTaskQueue queue, void *context);
250 void silc_task_set_iotype(SilcTask task, int type);
251 void silc_task_reset_iotype(SilcTask task, int type);
252 int silc_task_timeout_compare(struct timeval *smaller,
253 struct timeval *bigger);