aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-03-27 11:44:46 +0200
committerChristian Grothoff <christian@grothoff.org>2017-03-28 02:27:25 +0200
commitd486f5da0f495d817a19efd077501c25e4eef6fa (patch)
treebb785996088c46ed38012b23698d6354f8da7cfe /src
parent802f89d2979d3a92228543d42cee6bb8e3e786d1 (diff)
downloadgnunet-d486f5da0f495d817a19efd077501c25e4eef6fa.tar.gz
gnunet-d486f5da0f495d817a19efd077501c25e4eef6fa.zip
initial ideas for improving the scheduler API (far from finished)
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_scheduler_lib.h246
-rw-r--r--src/util/scheduler.c328
2 files changed, 563 insertions, 11 deletions
diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h
index 2be1858ce..a7385e31c 100644
--- a/src/include/gnunet_scheduler_lib.h
+++ b/src/include/gnunet_scheduler_lib.h
@@ -97,6 +97,84 @@ enum GNUNET_SCHEDULER_Reason
97 97
98 98
99/** 99/**
100 * Possible events on FDs, used as a bitmask.
101 * Modelled after GPollFD.
102 */
103enum GNUNET_SCHEDULER_EventType
104{
105
106 /**
107 * No event (useful for timeout).
108 */
109 GNUNET_SCHEDULER_ET_NONE = 0,
110
111 /**
112 * Data available for reading.
113 */
114 GNUNET_SCHEDULER_ET_IN = 1,
115
116 /**
117 * Buffer available for writing.
118 */
119 GNUNET_SCHEDULER_ET_OUT = 2,
120
121 /**
122 *
123 */
124 GNUNET_SCHEDULER_ET_HUP = 4,
125
126 /**
127 *
128 */
129 GNUNET_SCHEDULER_ET_ERR = 8,
130
131 /**
132 *
133 */
134 GNUNET_SCHEDULER_ET_PRI = 16,
135
136 /**
137 *
138 */
139 GNUNET_SCHEDULER_ET_NVAL = 32
140
141};
142
143
144/**
145 * Information about an event relating to a file descriptor/socket.
146 */
147struct GNUNET_SCHEDULER_FdInfo
148{
149
150 /**
151 * GNUnet network socket the event is about, matches @a sock,
152 * NULL if this is about a file handle or if no network
153 * handle was given to the scheduler originally.
154 */
155 struct GNUNET_NETWORK_Handle *fd;
156
157 /**
158 * GNUnet file handle the event is about, matches @a sock,
159 * NULL if this is about a network socket or if no network
160 * handle was given to the scheduler originally.
161 */
162 struct GNUNET_DISK_FileHandle *fh;
163
164 /**
165 * Type of the event that was generated related to @e sock.
166 */
167 enum GNUNET_SCHEDULER_EventType et;
168
169 /**
170 * Underlying OS handle the event was about.
171 */
172 int sock;
173
174};
175
176
177/**
100 * Context information passed to each scheduler task. 178 * Context information passed to each scheduler task.
101 */ 179 */
102struct GNUNET_SCHEDULER_TaskContext 180struct GNUNET_SCHEDULER_TaskContext
@@ -107,16 +185,29 @@ struct GNUNET_SCHEDULER_TaskContext
107 enum GNUNET_SCHEDULER_Reason reason; 185 enum GNUNET_SCHEDULER_Reason reason;
108 186
109 /** 187 /**
110 * Set of file descriptors ready for reading; 188 * Length of the following array.
111 * note that additional bits may be set 189 */
112 * that were not in the original request 190 unsigned int fds_len;
191
192 /**
193 * Array of length @e fds_len with information about ready FDs.
194 * Note that we use the same format regardless of the internal
195 * event loop that was used. The given array should only contain
196 * information about file descriptors relevant to the current task.
197 */
198 const struct GNUNET_SCHEDULER_FdInfo *fds;
199
200 /**
201 * Set of file descriptors ready for reading; note that additional
202 * bits may be set that were not in the original request.
203 * @deprecated
113 */ 204 */
114 const struct GNUNET_NETWORK_FDSet *read_ready; 205 const struct GNUNET_NETWORK_FDSet *read_ready;
115 206
116 /** 207 /**
117 * Set of file descriptors ready for writing; 208 * Set of file descriptors ready for writing; note that additional
118 * note that additional bits may be set 209 * bits may be set that were not in the original request.
119 * that were not in the original request. 210 * @deprecated
120 */ 211 */
121 const struct GNUNET_NETWORK_FDSet *write_ready; 212 const struct GNUNET_NETWORK_FDSet *write_ready;
122 213
@@ -124,16 +215,155 @@ struct GNUNET_SCHEDULER_TaskContext
124 215
125 216
126/** 217/**
218 * Function used by event-loop implementations to signal the scheduler
219 * that a particular @a task is ready due to an event of type @a et.
220 *
221 * This function will then queue the task to notify the application
222 * that the task is ready (with the respective priority).
223 *
224 * @param task the task that is ready
225 * @param et information about why the task is ready
226 */
227void
228GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
229 enum GNUNET_SCHEDULER_EventType et);
230
231
232/**
233 * Handle to the scheduler's state to be used by the driver.
234 */
235struct GNUNET_SCHEDULER_Handle;
236
237
238/**
239 * Function called by the driver to tell the scheduler to run some of
240 * the tasks that are ready. This function may return even though
241 * there are tasks left to run just to give other tasks a chance as
242 * well. If we return #GNUNET_YES, the driver should call this
243 * function again as soon as possible, while if we return #GNUNET_NO
244 * it must block until the operating system has more work as the
245 * scheduler has no more work to do right now.
246 *
247 * @param sh scheduler handle that was given to the `loop`
248 * @return #GNUNET_OK if there are more tasks that are ready,
249 * and thus we would like to run more (yield to avoid
250 * blocking other activities for too long)
251 * #GNUNET_NO if we are done running tasks (yield to block)
252 * #GNUNET_SYSERR on error
253 */
254int
255GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh);
256
257
258/**
259 * API a driver has to implement for
260 * #GNUNET_SCHEDULER_run_with_driver().
261 */
262struct GNUNET_SCHEDULER_Driver
263{
264
265 /**
266 * Closure to pass to the functions in this struct.
267 */
268 void *cls;
269
270 /**
271 * Add a @a task to be run if the conditions given
272 * in @a fdi are satisfied.
273 *
274 * @param cls closure
275 * @param task task to add
276 * @param fdi conditions to watch for
277 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
278 * (i.e. @a fdi too high or invalid)
279 */
280 int
281 (*add)(void *cls,
282 struct GNUNET_SCHEDULER_Task *task,
283 struct GNUNET_SCHEDULER_FdInfo *fdi);
284
285 /**
286 * Delete a @a task from the set of tasks to be run.
287 *
288 * @param cls closure
289 * @param task task to delete
290 * @param fdi conditions to watch for (must match @e add call)
291 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
292 * (i.e. @a task or @a fdi do not match prior @e add call)
293 */
294 int
295 (*del)(void *cls,
296 struct GNUNET_SCHEDULER_Task *task,
297 const struct GNUNET_SCHEDULER_FdInfo *fdi);
298
299 /**
300 * Set time at which we definitively want to get a wakeup call.
301 *
302 * @param cls closure
303 * @param dt time when we want to wake up next
304 */
305 void
306 (*set_wakeup)(void *cls,
307 struct GNUNET_TIME_Absolute dt);
308
309 /**
310 * Event loop's "main" function, to be called from
311 * #GNUNET_SCHEDULER_run_with_driver() to actually
312 * launch the loop.
313 *
314 * @param cls closure
315 * @param sh scheduler handle to pass to
316 * #GNUNET_SCHEDULER_run_from_driver()
317 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
318 */
319 int
320 (*loop)(void *cls,
321 struct GNUNET_SCHEDULER_Handle *sh);
322
323};
324
325
326/**
127 * Signature of the main function of a task. 327 * Signature of the main function of a task.
128 * 328 *
129 * @param cls closure 329 * @param cls closure
130 * @param tc context information (why was this task triggered now)
131 */ 330 */
132typedef void 331typedef void
133(*GNUNET_SCHEDULER_TaskCallback) (void *cls); 332(*GNUNET_SCHEDULER_TaskCallback) (void *cls);
134 333
135 334
136/** 335/**
336 * Initialize and run scheduler. This function will return when all
337 * tasks have completed. On systems with signals, receiving a SIGTERM
338 * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown
339 * to be run after the active task is complete. As a result, SIGTERM
340 * causes all shutdown tasks to be scheduled with reason
341 * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added
342 * afterwards will execute normally!). Note that any particular
343 * signal will only shut down one scheduler; applications should
344 * always only create a single scheduler.
345 *
346 * @param driver drive to use for the event loop
347 * @param task task to run first (and immediately)
348 * @param task_cls closure of @a task
349 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
350 */
351int
352GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
353 GNUNET_SCHEDULER_TaskCallback task,
354 void *task_cls);
355
356
357/**
358 * Obtain the driver for using select() as the event loop.
359 *
360 * @return NULL on error
361 */
362const struct GNUNET_SCHEDULER_Driver *
363GNUNET_SCHEDULER_driver_select (void);
364
365
366/**
137 * Signature of the select function used by the scheduler. 367 * Signature of the select function used by the scheduler.
138 * #GNUNET_NETWORK_socket_select matches it. 368 * #GNUNET_NETWORK_socket_select matches it.
139 * 369 *
@@ -571,7 +801,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
571 * Sets the select function to use in the scheduler (scheduler_select). 801 * Sets the select function to use in the scheduler (scheduler_select).
572 * 802 *
573 * @param new_select new select function to use (NULL to reset to default) 803 * @param new_select new select function to use (NULL to reset to default)
574 * @param new_select_cls closure for 'new_select' 804 * @param new_select_cls closure for @a new_select
575 */ 805 */
576void 806void
577GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select, 807GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select,
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 409a0942f..a7b1d8e2a 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 Copyright (C) 2009-2016 GNUnet e.V. 3 Copyright (C) 2009-2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -17,7 +17,6 @@
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA. 18 Boston, MA 02110-1301, USA.
19 */ 19 */
20
21/** 20/**
22 * @file util/scheduler.c 21 * @file util/scheduler.c
23 * @brief schedule computations using continuation passing style 22 * @brief schedule computations using continuation passing style
@@ -71,6 +70,35 @@
71 70
72 71
73/** 72/**
73 * Argument to be passed from the driver to
74 * #GNUNET_SCHEDULER_run_from_driver(). Contains the
75 * scheduler's internal state.
76 */
77struct GNUNET_SCHEDULER_Handle
78{
79 /**
80 * Passed here to avoid constantly allocating/deallocating
81 * this element, but generally we want to get rid of this.
82 * @deprecated
83 */
84 struct GNUNET_NETWORK_FDSet *rs;
85
86 /**
87 * Passed here to avoid constantly allocating/deallocating
88 * this element, but generally we want to get rid of this.
89 * @deprecated
90 */
91 struct GNUNET_NETWORK_FDSet *ws;
92
93 /**
94 * Driver we used for the event loop.
95 */
96 const struct GNUNET_SCHEDULER_Driver *driver;
97
98};
99
100
101/**
74 * Entry in list of pending tasks. 102 * Entry in list of pending tasks.
75 */ 103 */
76struct GNUNET_SCHEDULER_Task 104struct GNUNET_SCHEDULER_Task
@@ -96,6 +124,11 @@ struct GNUNET_SCHEDULER_Task
96 void *callback_cls; 124 void *callback_cls;
97 125
98 /** 126 /**
127 * Handle to the scheduler's state.
128 */
129 const struct GNUNET_SCHEDULER_Handle *sh;
130
131 /**
99 * Set of file descriptors this task is waiting 132 * Set of file descriptors this task is waiting
100 * for for reading. Once ready, this is updated 133 * for for reading. Once ready, this is updated
101 * to reflect the set of file descriptors ready 134 * to reflect the set of file descriptors ready
@@ -111,6 +144,18 @@ struct GNUNET_SCHEDULER_Task
111 struct GNUNET_NETWORK_FDSet *write_set; 144 struct GNUNET_NETWORK_FDSet *write_set;
112 145
113 /** 146 /**
147 * Information about which FDs are ready for this task (and why).
148 */
149 const struct GNUNET_SCHEDULER_FdInfo *fds;
150
151 /**
152 * Storage location used for @e fds if we want to avoid
153 * a separate malloc() call in the common case that this
154 * task is only about a single FD.
155 */
156 struct GNUNET_SCHEDULER_FdInfo fdx;
157
158 /**
114 * Absolute timeout value for the task, or 159 * Absolute timeout value for the task, or
115 * #GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout". 160 * #GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout".
116 */ 161 */
@@ -124,6 +169,11 @@ struct GNUNET_SCHEDULER_Task
124#endif 169#endif
125 170
126 /** 171 /**
172 * Size of the @e fds array.
173 */
174 unsigned int fds_len;
175
176 /**
127 * Why is the task ready? Set after task is added to ready queue. 177 * Why is the task ready? Set after task is added to ready queue.
128 * Initially set to zero. All reasons that have already been 178 * Initially set to zero. All reasons that have already been
129 * satisfied (i.e. read or write ready) will be set over time. 179 * satisfied (i.e. read or write ready) will be set over time.
@@ -1742,7 +1792,8 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1742 GNUNET_CONTAINER_DLL_insert (pending_head, 1792 GNUNET_CONTAINER_DLL_insert (pending_head,
1743 pending_tail, 1793 pending_tail,
1744 t); 1794 t);
1745 max_priority_added = GNUNET_MAX (max_priority_added, t->priority); 1795 max_priority_added = GNUNET_MAX (max_priority_added,
1796 t->priority);
1746 LOG (GNUNET_ERROR_TYPE_DEBUG, 1797 LOG (GNUNET_ERROR_TYPE_DEBUG,
1747 "Adding task %p\n", 1798 "Adding task %p\n",
1748 t); 1799 t);
@@ -1750,4 +1801,275 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1750 return t; 1801 return t;
1751} 1802}
1752 1803
1804
1805/**
1806 * Function used by event-loop implementations to signal the scheduler
1807 * that a particular @a task is ready due to an event of type @a et.
1808 *
1809 * This function will then queue the task to notify the application
1810 * that the task is ready (with the respective priority).
1811 *
1812 * @param task the task that is ready, NULL for wake up calls
1813 * @param et information about why the task is ready
1814 */
1815void
1816GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1817 enum GNUNET_SCHEDULER_EventType et)
1818{
1819 enum GNUNET_SCHEDULER_Reason reason;
1820 struct GNUNET_TIME_Absolute now;
1821
1822 now = GNUNET_TIME_absolute_get ();
1823 reason = task->reason;
1824 if (now.abs_value_us >= task->timeout.abs_value_us)
1825 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
1826 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1827 (0 != (GNUNET_SCHEDULER_ET_IN & et)) )
1828 reason |= GNUNET_SCHEDULER_REASON_READ_READY;
1829 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1830 (0 != (GNUNET_SCHEDULER_ET_OUT & et)) )
1831 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY;
1832 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE;
1833 task->reason = reason;
1834 task->fds = &task->fdx;
1835 task->fdx.et = et;
1836 task->fds_len = 1;
1837 queue_ready_task (task);
1838}
1839
1840
1841/**
1842 * Function called by the driver to tell the scheduler to run some of
1843 * the tasks that are ready. This function may return even though
1844 * there are tasks left to run just to give other tasks a chance as
1845 * well. If we return #GNUNET_YES, the driver should call this
1846 * function again as soon as possible, while if we return #GNUNET_NO
1847 * it must block until the operating system has more work as the
1848 * scheduler has no more work to do right now.
1849 *
1850 * @param sh scheduler handle that was given to the `loop`
1851 * @return #GNUNET_OK if there are more tasks that are ready,
1852 * and thus we would like to run more (yield to avoid
1853 * blocking other activities for too long)
1854 * #GNUNET_NO if we are done running tasks (yield to block)
1855 * #GNUNET_SYSERR on error
1856 */
1857int
1858GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1859{
1860 enum GNUNET_SCHEDULER_Priority p;
1861 struct GNUNET_SCHEDULER_Task *pos;
1862 struct GNUNET_TIME_Absolute now;
1863
1864 /* check for tasks that reached the timeout! */
1865 now = GNUNET_TIME_absolute_get ();
1866 while (NULL != (pos = pending_timeout_head))
1867 {
1868 if (now.abs_value_us >= pos->timeout.abs_value_us)
1869 pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
1870 if (0 == pos->reason)
1871 break;
1872 GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
1873 pending_timeout_tail,
1874 pos);
1875 if (pending_timeout_last == pos)
1876 pending_timeout_last = NULL;
1877 queue_ready_task (pos);
1878 }
1879
1880 if (0 == ready_count)
1881 return GNUNET_NO;
1882
1883 /* find out which task priority level we are going to
1884 process this time */
1885 max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP;
1886 GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]);
1887 /* yes, p>0 is correct, 0 is "KEEP" which should
1888 * always be an empty queue (see assertion)! */
1889 for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--)
1890 {
1891 pos = ready_head[p];
1892 if (NULL != pos)
1893 break;
1894 }
1895 GNUNET_assert (NULL != pos); /* ready_count wrong? */
1896
1897 /* process all tasks at this priority level, then yield */
1898 while (NULL != (pos = ready_head[p]))
1899 {
1900 GNUNET_CONTAINER_DLL_remove (ready_head[p],
1901 ready_tail[p],
1902 pos);
1903 ready_count--;
1904 current_priority = pos->priority;
1905 current_lifeness = pos->lifeness;
1906 active_task = pos;
1907#if PROFILE_DELAYS
1908 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
1909 DELAY_THRESHOLD.rel_value_us)
1910 {
1911 LOG (GNUNET_ERROR_TYPE_DEBUG,
1912 "Task %p took %s to be scheduled\n",
1913 pos,
1914 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time),
1915 GNUNET_YES));
1916 }
1917#endif
1918 tc.reason = pos->reason;
1919 GNUNET_NETWORK_fdset_zero (sh->rs);
1920 GNUNET_NETWORK_fdset_zero (sh->ws);
1921 tc.fds_len = pos->fds_len;
1922 tc.fds = pos->fds;
1923 tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set;
1924 if ( (-1 != pos->read_fd) &&
1925 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) )
1926 GNUNET_NETWORK_fdset_set_native (sh->rs,
1927 pos->read_fd);
1928 tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set;
1929 if ((-1 != pos->write_fd) &&
1930 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)))
1931 GNUNET_NETWORK_fdset_set_native (sh->ws,
1932 pos->write_fd);
1933 LOG (GNUNET_ERROR_TYPE_DEBUG,
1934 "Running task: %p\n",
1935 pos);
1936 pos->callback (pos->callback_cls);
1937 active_task = NULL;
1938 dump_backtrace (pos);
1939 destroy_task (pos);
1940 tasks_run++;
1941 }
1942 if (0 == ready_count)
1943 return GNUNET_NO;
1944 return GNUNET_OK;
1945}
1946
1947
1948/**
1949 * Initialize and run scheduler. This function will return when all
1950 * tasks have completed. On systems with signals, receiving a SIGTERM
1951 * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown
1952 * to be run after the active task is complete. As a result, SIGTERM
1953 * causes all shutdown tasks to be scheduled with reason
1954 * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added
1955 * afterwards will execute normally!). Note that any particular
1956 * signal will only shut down one scheduler; applications should
1957 * always only create a single scheduler.
1958 *
1959 * @param driver drive to use for the event loop
1960 * @param task task to run first (and immediately)
1961 * @param task_cls closure of @a task
1962 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1963 */
1964int
1965GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver,
1966 GNUNET_SCHEDULER_TaskCallback task,
1967 void *task_cls)
1968{
1969 int ret;
1970 struct GNUNET_SIGNAL_Context *shc_int;
1971 struct GNUNET_SIGNAL_Context *shc_term;
1972#if (SIGTERM != GNUNET_TERM_SIG)
1973 struct GNUNET_SIGNAL_Context *shc_gterm;
1974#endif
1975#ifndef MINGW
1976 struct GNUNET_SIGNAL_Context *shc_quit;
1977 struct GNUNET_SIGNAL_Context *shc_hup;
1978 struct GNUNET_SIGNAL_Context *shc_pipe;
1979#endif
1980 struct GNUNET_SCHEDULER_Task tsk;
1981 const struct GNUNET_DISK_FileHandle *pr;
1982 struct GNUNET_SCHEDULER_Handle sh;
1983
1984 /* general set-up */
1985 GNUNET_assert (NULL == active_task);
1986 GNUNET_assert (NULL == shutdown_pipe_handle);
1987 shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO,
1988 GNUNET_NO,
1989 GNUNET_NO,
1990 GNUNET_NO);
1991 GNUNET_assert (NULL != shutdown_pipe_handle);
1992 pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
1993 GNUNET_DISK_PIPE_END_READ);
1994 GNUNET_assert (NULL != pr);
1995 my_pid = getpid ();
1996
1997 /* install signal handlers */
1998 LOG (GNUNET_ERROR_TYPE_DEBUG,
1999 "Registering signal handlers\n");
2000 shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2001 &sighandler_shutdown);
2002 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2003 &sighandler_shutdown);
2004#if (SIGTERM != GNUNET_TERM_SIG)
2005 shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG,
2006 &sighandler_shutdown);
2007#endif
2008#ifndef MINGW
2009 shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2010 &sighandler_pipe);
2011 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2012 &sighandler_shutdown);
2013 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2014 &sighandler_shutdown);
2015#endif
2016
2017 /* Setup initial tasks */
2018 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
2019 current_lifeness = GNUNET_YES;
2020 memset (&tsk,
2021 0,
2022 sizeof (tsk));
2023 active_task = &tsk;
2024 tsk.sh = &sh;
2025 GNUNET_SCHEDULER_add_with_reason_and_priority (task,
2026 task_cls,
2027 GNUNET_SCHEDULER_REASON_STARTUP,
2028 GNUNET_SCHEDULER_PRIORITY_DEFAULT);
2029 GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO,
2030 &GNUNET_OS_install_parent_control_handler,
2031 NULL);
2032 active_task = NULL;
2033 driver->set_wakeup (driver->cls,
2034 GNUNET_TIME_absolute_get ());
2035
2036 /* begin main event loop */
2037 sh.rs = GNUNET_NETWORK_fdset_create ();
2038 sh.ws = GNUNET_NETWORK_fdset_create ();
2039 sh.driver = driver;
2040 ret = driver->loop (driver->cls,
2041 &sh);
2042 GNUNET_NETWORK_fdset_destroy (sh.rs);
2043 GNUNET_NETWORK_fdset_destroy (sh.ws);
2044
2045 /* uninstall signal handlers */
2046 GNUNET_SIGNAL_handler_uninstall (shc_int);
2047 GNUNET_SIGNAL_handler_uninstall (shc_term);
2048#if (SIGTERM != GNUNET_TERM_SIG)
2049 GNUNET_SIGNAL_handler_uninstall (shc_gterm);
2050#endif
2051#ifndef MINGW
2052 GNUNET_SIGNAL_handler_uninstall (shc_pipe);
2053 GNUNET_SIGNAL_handler_uninstall (shc_quit);
2054 GNUNET_SIGNAL_handler_uninstall (shc_hup);
2055#endif
2056 GNUNET_DISK_pipe_close (shutdown_pipe_handle);
2057 shutdown_pipe_handle = NULL;
2058 return ret;
2059}
2060
2061
2062/**
2063 * Obtain the driver for using select() as the event loop.
2064 *
2065 * @return NULL on error
2066 */
2067const struct GNUNET_SCHEDULER_Driver *
2068GNUNET_SCHEDULER_driver_select ()
2069{
2070 GNUNET_break (0); // not implemented
2071 return NULL;
2072}
2073
2074
1753/* end of scheduler.c */ 2075/* end of scheduler.c */