5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1998 - 2001 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.
22 #include "silcincludes.h"
23 #include "silcschedule_i.h"
25 /* Calls normal select() system call. */
27 int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count,
28 struct timeval *timeout)
31 int ret, i, max_fd = 0;
36 for (i = 0; i < fds_count; i++) {
40 if (fds[i].fd > max_fd)
43 if (fds[i].events & SILC_TASK_READ)
44 FD_SET(fds[i].fd, &in);
45 if (fds[i].events & SILC_TASK_WRITE)
46 FD_SET(fds[i].fd, &out);
51 ret = select(max_fd + 1, &in, &out, NULL, timeout);
55 for (i = 0; i < fds_count; i++) {
59 if (FD_ISSET(fds[i].fd, &in))
60 fds[i].revents |= SILC_TASK_READ;
61 if (FD_ISSET(fds[i].fd, &out))
62 fds[i].revents |= SILC_TASK_WRITE;
68 /* Internal context. */
73 sigset_t signals_blocked;
78 SILC_TASK_CALLBACK(silc_schedule_wakeup_cb)
80 SilcUnixScheduler internal = (SilcUnixScheduler)context;
83 read(internal->wakeup_pipe[0], &c, 1);
86 #endif /* SILC_THREADS */
88 /* Initializes the platform specific scheduler. This for example initializes
89 the wakeup mechanism of the scheduler. In multi-threaded environment
90 the scheduler needs to be wakenup when tasks are added or removed from
91 the task queues. Returns context to the platform specific scheduler. */
93 void *silc_schedule_internal_init(SilcSchedule schedule)
95 SilcUnixScheduler internal;
97 internal = silc_calloc(1, sizeof(*internal));
101 sigemptyset(&internal->signals);
104 if (pipe(internal->wakeup_pipe)) {
109 internal->wakeup_task =
110 silc_schedule_task_add(schedule, internal->wakeup_pipe[0],
111 silc_schedule_wakeup_cb, internal,
113 SILC_TASK_PRI_NORMAL);
114 if (!internal->wakeup_task) {
115 close(internal->wakeup_pipe[0]);
116 close(internal->wakeup_pipe[1]);
122 return (void *)internal;
125 /* Uninitializes the platform specific scheduler context. */
127 void silc_schedule_internal_uninit(void *context)
129 SilcUnixScheduler internal = (SilcUnixScheduler)context;
135 close(internal->wakeup_pipe[0]);
136 close(internal->wakeup_pipe[1]);
142 /* Wakes up the scheduler */
144 void silc_schedule_internal_wakeup(void *context)
147 SilcUnixScheduler internal = (SilcUnixScheduler)context;
152 write(internal->wakeup_pipe[1], "!", 1);
156 void silc_schedule_internal_signal_register(void *context,
159 SilcUnixScheduler internal = (SilcUnixScheduler)context;
160 sigaddset(&internal->signals, signal);
163 void silc_schedule_internal_signal_unregister(void *context,
166 SilcUnixScheduler internal = (SilcUnixScheduler)context;
167 sigdelset(&internal->signals, signal);
170 /* Block registered signals in scheduler. */
172 void silc_schedule_internal_signals_block(void *context)
174 SilcUnixScheduler internal = (SilcUnixScheduler)context;
175 sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
178 /* Unblock registered signals in schedule. */
180 void silc_schedule_internal_signals_unblock(void *context)
182 SilcUnixScheduler internal = (SilcUnixScheduler)context;
183 sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL);