diff options
author | lurchi <lurchi@strangeplace.net> | 2018-02-01 19:54:54 +0100 |
---|---|---|
committer | lurchi <lurchi@strangeplace.net> | 2018-02-01 19:55:15 +0100 |
commit | 89d1b38101ea52dfe7ef20ab8f6604a6f973bbbd (patch) | |
tree | 5af6e4158cb3d996ed0e68abe0216d62ce4d6a86 /src/util/scheduler.c | |
parent | b3fdd5716f3e0622508e68450516d11a6d55a0ab (diff) | |
download | gnunet-89d1b38101ea52dfe7ef20ab8f6604a6f973bbbd.tar.gz gnunet-89d1b38101ea52dfe7ef20ab8f6604a6f973bbbd.zip |
scheduler API change to allow use with js event loop
- GNUNET_SCHEDUELR_run_with_driver has been replaced with
GNUNET_SCHEDULER_driver_init and GNUNET_SCHEDUELR_driver_done
- GNUNET_SCHEDULER_run_from_driver has been renamed to
GNUNET_SCHEDULER_do_work (as it's no longer being called from a driver
callback)
- documentation has been updated
Diffstat (limited to 'src/util/scheduler.c')
-rw-r--r-- | src/util/scheduler.c | 432 |
1 files changed, 257 insertions, 175 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 98334490b..05a951e19 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -73,7 +73,7 @@ | |||
73 | 73 | ||
74 | /** | 74 | /** |
75 | * Argument to be passed from the driver to | 75 | * Argument to be passed from the driver to |
76 | * #GNUNET_SCHEDULER_run_from_driver(). Contains the | 76 | * #GNUNET_SCHEDULER_do_work(). Contains the |
77 | * scheduler's internal state. | 77 | * scheduler's internal state. |
78 | */ | 78 | */ |
79 | struct GNUNET_SCHEDULER_Handle | 79 | struct GNUNET_SCHEDULER_Handle |
@@ -91,6 +91,40 @@ struct GNUNET_SCHEDULER_Handle | |||
91 | * @deprecated | 91 | * @deprecated |
92 | */ | 92 | */ |
93 | struct GNUNET_NETWORK_FDSet *ws; | 93 | struct GNUNET_NETWORK_FDSet *ws; |
94 | |||
95 | /** | ||
96 | * context of the SIGINT handler | ||
97 | */ | ||
98 | struct GNUNET_SIGNAL_Context *shc_int; | ||
99 | |||
100 | /** | ||
101 | * context of the SIGTERM handler | ||
102 | */ | ||
103 | struct GNUNET_SIGNAL_Context *shc_term; | ||
104 | |||
105 | #if (SIGTERM != GNUNET_TERM_SIG) | ||
106 | /** | ||
107 | * context of the TERM_SIG handler | ||
108 | */ | ||
109 | struct GNUNET_SIGNAL_Context *shc_gterm; | ||
110 | #endif | ||
111 | |||
112 | #ifndef MINGW | ||
113 | /** | ||
114 | * context of the SIGQUIT handler | ||
115 | */ | ||
116 | struct GNUNET_SIGNAL_Context *shc_quit; | ||
117 | |||
118 | /** | ||
119 | * context of the SIGHUP handler | ||
120 | */ | ||
121 | struct GNUNET_SIGNAL_Context *shc_hup; | ||
122 | |||
123 | /** | ||
124 | * context of hte SIGPIPE handler | ||
125 | */ | ||
126 | struct GNUNET_SIGNAL_Context *shc_pipe; | ||
127 | #endif | ||
94 | }; | 128 | }; |
95 | 129 | ||
96 | 130 | ||
@@ -265,7 +299,7 @@ struct DriverContext | |||
265 | 299 | ||
266 | /** | 300 | /** |
267 | * The driver used for the event loop. Will be handed over to | 301 | * The driver used for the event loop. Will be handed over to |
268 | * the scheduler in #GNUNET_SCHEDULER_run_from_driver(), peristed | 302 | * the scheduler in #GNUNET_SCHEDULER_do_work(), persisted |
269 | * there in this variable for later use in functions like | 303 | * there in this variable for later use in functions like |
270 | * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and | 304 | * #GNUNET_SCHEDULER_add_select(), #add_without_sets() and |
271 | * #GNUNET_SCHEDULER_cancel(). | 305 | * #GNUNET_SCHEDULER_cancel(). |
@@ -382,11 +416,6 @@ static struct GNUNET_SCHEDULER_TaskContext tc; | |||
382 | */ | 416 | */ |
383 | static void *scheduler_select_cls; | 417 | static void *scheduler_select_cls; |
384 | 418 | ||
385 | /** | ||
386 | * Scheduler handle used for the driver functions | ||
387 | */ | ||
388 | static struct GNUNET_SCHEDULER_Handle sh; | ||
389 | |||
390 | 419 | ||
391 | /** | 420 | /** |
392 | * Sets the select function to use in the scheduler (scheduler_select). | 421 | * Sets the select function to use in the scheduler (scheduler_select). |
@@ -659,6 +688,10 @@ shutdown_if_no_lifeness () | |||
659 | } | 688 | } |
660 | 689 | ||
661 | 690 | ||
691 | int | ||
692 | select_loop (struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context); | ||
693 | |||
694 | |||
662 | /** | 695 | /** |
663 | * Initialize and run scheduler. This function will return when all | 696 | * Initialize and run scheduler. This function will return when all |
664 | * tasks have completed. On systems with signals, receiving a SIGTERM | 697 | * tasks have completed. On systems with signals, receiving a SIGTERM |
@@ -677,16 +710,21 @@ void | |||
677 | GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, | 710 | GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, |
678 | void *task_cls) | 711 | void *task_cls) |
679 | { | 712 | { |
713 | struct GNUNET_SCHEDULER_Handle *sh; | ||
680 | struct GNUNET_SCHEDULER_Driver *driver; | 714 | struct GNUNET_SCHEDULER_Driver *driver; |
681 | struct DriverContext context = {.scheduled_head = NULL, | 715 | struct DriverContext context = {.scheduled_head = NULL, |
682 | .scheduled_tail = NULL, | 716 | .scheduled_tail = NULL, |
683 | .timeout = GNUNET_TIME_UNIT_FOREVER_ABS}; | 717 | .timeout = GNUNET_TIME_absolute_get ()}; |
684 | 718 | ||
685 | driver = GNUNET_SCHEDULER_driver_select (); | 719 | driver = GNUNET_SCHEDULER_driver_select (); |
686 | driver->cls = &context; | 720 | driver->cls = &context; |
687 | 721 | sh = GNUNET_SCHEDULER_driver_init (driver); | |
688 | GNUNET_SCHEDULER_run_with_driver (driver, task, task_cls); | 722 | GNUNET_SCHEDULER_add_with_reason_and_priority (task, |
689 | 723 | task_cls, | |
724 | GNUNET_SCHEDULER_REASON_STARTUP, | ||
725 | GNUNET_SCHEDULER_PRIORITY_DEFAULT); | ||
726 | select_loop (sh, &context); | ||
727 | GNUNET_SCHEDULER_driver_done (sh); | ||
690 | GNUNET_free (driver); | 728 | GNUNET_free (driver); |
691 | } | 729 | } |
692 | 730 | ||
@@ -900,8 +938,11 @@ shutdown_pipe_cb (void *cls) | |||
900 | /** | 938 | /** |
901 | * Cancel the task with the specified identifier. | 939 | * Cancel the task with the specified identifier. |
902 | * The task must not yet have run. Only allowed to be called as long as the | 940 | * The task must not yet have run. Only allowed to be called as long as the |
903 | * scheduler is running (#GNUNET_SCHEDULER_run or | 941 | * scheduler is running, that is one of the following conditions is met: |
904 | * #GNUNET_SCHEDULER_run_with_driver has been called and has not returned yet). | 942 | * |
943 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
944 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
945 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
905 | * | 946 | * |
906 | * @param task id of the task to cancel | 947 | * @param task id of the task to cancel |
907 | * @return original closure of the task | 948 | * @return original closure of the task |
@@ -1401,9 +1442,12 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1401 | * used as a timeout on the socket being ready. The task will be | 1442 | * used as a timeout on the socket being ready. The task will be |
1402 | * scheduled for execution once either the delay has expired or the | 1443 | * scheduled for execution once either the delay has expired or the |
1403 | * socket operation is ready. It will be run with the DEFAULT priority. | 1444 | * socket operation is ready. It will be run with the DEFAULT priority. |
1404 | * Only allowed to be called as long as the scheduler is running | 1445 | * Only allowed to be called as long as the scheduler is running, that |
1405 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1446 | * is one of the following conditions is met: |
1406 | * called and has not returned yet). | 1447 | * |
1448 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1449 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1450 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1407 | * | 1451 | * |
1408 | * @param delay when should this operation time out? | 1452 | * @param delay when should this operation time out? |
1409 | * @param rfd read file-descriptor | 1453 | * @param rfd read file-descriptor |
@@ -1431,9 +1475,12 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, | |||
1431 | * socket being ready. The task will be scheduled for execution once | 1475 | * socket being ready. The task will be scheduled for execution once |
1432 | * either the delay has expired or the socket operation is ready. It | 1476 | * either the delay has expired or the socket operation is ready. It |
1433 | * will be run with the DEFAULT priority. | 1477 | * will be run with the DEFAULT priority. |
1434 | * Only allowed to be called as long as the scheduler is running | 1478 | * Only allowed to be called as long as the scheduler is running, that |
1435 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1479 | * is one of the following conditions is met: |
1436 | * called and has not returned yet). | 1480 | * |
1481 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1482 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1483 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1437 | * | 1484 | * |
1438 | * @param delay when should this operation time out? | 1485 | * @param delay when should this operation time out? |
1439 | * @param priority priority to use for the task | 1486 | * @param priority priority to use for the task |
@@ -1465,9 +1512,12 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1465 | * scheduled for execution once either the delay has expired or the | 1512 | * scheduled for execution once either the delay has expired or the |
1466 | * socket operation is ready. It will be run with the priority of | 1513 | * socket operation is ready. It will be run with the priority of |
1467 | * the calling task. | 1514 | * the calling task. |
1468 | * Only allowed to be called as long as the scheduler is running | 1515 | * Only allowed to be called as long as the scheduler is running, that |
1469 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1516 | * is one of the following conditions is met: |
1470 | * called and has not returned yet). | 1517 | * |
1518 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1519 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1520 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1471 | * | 1521 | * |
1472 | * @param delay when should this operation time out? | 1522 | * @param delay when should this operation time out? |
1473 | * @param wfd write file-descriptor | 1523 | * @param wfd write file-descriptor |
@@ -1495,9 +1545,12 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, | |||
1495 | * used as a timeout on the socket being ready. The task will be | 1545 | * used as a timeout on the socket being ready. The task will be |
1496 | * scheduled for execution once either the delay has expired or the | 1546 | * scheduled for execution once either the delay has expired or the |
1497 | * socket operation is ready. | 1547 | * socket operation is ready. |
1498 | * Only allowed to be called as long as the scheduler is running | 1548 | * Only allowed to be called as long as the scheduler is running, that |
1499 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1549 | * is one of the following conditions is met: |
1500 | * called and has not returned yet). | 1550 | * |
1551 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1552 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1553 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1501 | * | 1554 | * |
1502 | * @param delay when should this operation time out? | 1555 | * @param delay when should this operation time out? |
1503 | * @param priority priority of the task | 1556 | * @param priority priority of the task |
@@ -1554,9 +1607,12 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1554 | * used as a timeout on the socket being ready. The task will be | 1607 | * used as a timeout on the socket being ready. The task will be |
1555 | * scheduled for execution once either the delay has expired or the | 1608 | * scheduled for execution once either the delay has expired or the |
1556 | * socket operation is ready. It will be run with the DEFAULT priority. | 1609 | * socket operation is ready. It will be run with the DEFAULT priority. |
1557 | * Only allowed to be called as long as the scheduler is running | 1610 | * Only allowed to be called as long as the scheduler is running, that |
1558 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1611 | * is one of the following conditions is met: |
1559 | * called and has not returned yet). | 1612 | * |
1613 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1614 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1615 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1560 | * | 1616 | * |
1561 | * @param delay when should this operation time out? | 1617 | * @param delay when should this operation time out? |
1562 | * @param rfd read file-descriptor | 1618 | * @param rfd read file-descriptor |
@@ -1583,9 +1639,12 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, | |||
1583 | * used as a timeout on the socket being ready. The task will be | 1639 | * used as a timeout on the socket being ready. The task will be |
1584 | * scheduled for execution once either the delay has expired or the | 1640 | * scheduled for execution once either the delay has expired or the |
1585 | * socket operation is ready. It will be run with the DEFAULT priority. | 1641 | * socket operation is ready. It will be run with the DEFAULT priority. |
1586 | * Only allowed to be called as long as the scheduler is running | 1642 | * Only allowed to be called as long as the scheduler is running, that |
1587 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1643 | * is one of the following conditions is met: |
1588 | * called and has not returned yet). | 1644 | * |
1645 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1646 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1647 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1589 | * | 1648 | * |
1590 | * @param delay when should this operation time out? | 1649 | * @param delay when should this operation time out? |
1591 | * @param wfd write file-descriptor | 1650 | * @param wfd write file-descriptor |
@@ -1612,9 +1671,12 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, | |||
1612 | * used as a timeout on the socket being ready. The task will be | 1671 | * used as a timeout on the socket being ready. The task will be |
1613 | * scheduled for execution once either the delay has expired or the | 1672 | * scheduled for execution once either the delay has expired or the |
1614 | * socket operation is ready. | 1673 | * socket operation is ready. |
1615 | * Only allowed to be called as long as the scheduler is running | 1674 | * Only allowed to be called as long as the scheduler is running, that |
1616 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1675 | * is one of the following conditions is met: |
1617 | * called and has not returned yet). | 1676 | * |
1677 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1678 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1679 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1618 | * | 1680 | * |
1619 | * @param delay when should this operation time out? | 1681 | * @param delay when should this operation time out? |
1620 | * @param priority priority of the task | 1682 | * @param priority priority of the task |
@@ -1729,9 +1791,12 @@ extract_handles (const struct GNUNET_NETWORK_FDSet *fdset, | |||
1729 | * || any-rs-ready | 1791 | * || any-rs-ready |
1730 | * || any-ws-ready) ) | 1792 | * || any-ws-ready) ) |
1731 | * </code> | 1793 | * </code> |
1732 | * Only allowed to be called as long as the scheduler is running | 1794 | * Only allowed to be called as long as the scheduler is running, that |
1733 | * (#GNUNET_SCHEDULER_run or #GNUNET_SCHEDULER_run_with_driver has been | 1795 | * is one of the following conditions is met: |
1734 | * called and has not returned yet). | 1796 | * |
1797 | * - #GNUNET_SCHEDULER_run has been called and has not returned yet | ||
1798 | * - #GNUNET_SCHEDULER_driver_init has been run and | ||
1799 | * #GNUNET_SCHEDULER_driver_done has not been called yet | ||
1735 | * | 1800 | * |
1736 | * @param prio how important is this task? | 1801 | * @param prio how important is this task? |
1737 | * @param delay how long should we wait? | 1802 | * @param delay how long should we wait? |
@@ -1886,23 +1951,27 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, | |||
1886 | 1951 | ||
1887 | 1952 | ||
1888 | /** | 1953 | /** |
1889 | * Function called by the driver to tell the scheduler to run some of | 1954 | * Function called by external event loop implementations to tell the |
1890 | * the tasks that are ready. This function may return even though | 1955 | * scheduler to run some of the tasks that are ready. Must be called |
1891 | * there are tasks left to run just to give other tasks a chance as | 1956 | * only after #GNUNET_SCHEDULER_driver_init has been called and before |
1892 | * well. If we return #GNUNET_YES, the driver should call this | 1957 | * #GNUNET_SCHEDULER_driver_done is called. |
1893 | * function again as soon as possible, while if we return #GNUNET_NO | 1958 | * This function may return even though there are tasks left to run |
1894 | * it must block until either the operating system has more work (the | 1959 | * just to give other tasks a chance as well. If we return #GNUNET_YES, |
1895 | * scheduler has no more work to do right now) or the timeout set by | 1960 | * the event loop implementation should call this function again as |
1896 | * the scheduler (using the set_wakeup callback) is reached. | 1961 | * soon as possible, while if we return #GNUNET_NO it must block until |
1962 | * either the operating system has more work (the scheduler has no more | ||
1963 | * work to do right now) or the timeout set by the scheduler (using the | ||
1964 | * set_wakeup callback) is reached. | ||
1897 | * | 1965 | * |
1898 | * @param sh scheduler handle that was given to the `loop` | 1966 | * @param sh scheduler handle that was returned by |
1967 | * #GNUNET_SCHEDULER_driver_init | ||
1899 | * @return #GNUNET_YES if there are more tasks that are ready, | 1968 | * @return #GNUNET_YES if there are more tasks that are ready, |
1900 | * and thus we would like to run more (yield to avoid | 1969 | * and thus we would like to run more (yield to avoid |
1901 | * blocking other activities for too long) | 1970 | * blocking other activities for too long) #GNUNET_NO |
1902 | * #GNUNET_NO if we are done running tasks (yield to block) | 1971 | * if we are done running tasks (yield to block) |
1903 | */ | 1972 | */ |
1904 | int | 1973 | int |
1905 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | 1974 | GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh) |
1906 | { | 1975 | { |
1907 | enum GNUNET_SCHEDULER_Priority p; | 1976 | enum GNUNET_SCHEDULER_Priority p; |
1908 | struct GNUNET_SCHEDULER_Task *pos; | 1977 | struct GNUNET_SCHEDULER_Task *pos; |
@@ -1955,7 +2024,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
1955 | * also be a programming error in the driver though. | 2024 | * also be a programming error in the driver though. |
1956 | */ | 2025 | */ |
1957 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 2026 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1958 | "GNUNET_SCHEDULER_run_from_driver did not find any ready " | 2027 | "GNUNET_SCHEDULER_do_work did not find any ready " |
1959 | "tasks and timeout has not been reached yet."); | 2028 | "tasks and timeout has not been reached yet."); |
1960 | return GNUNET_NO; | 2029 | return GNUNET_NO; |
1961 | } | 2030 | } |
@@ -2056,43 +2125,46 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
2056 | 2125 | ||
2057 | 2126 | ||
2058 | /** | 2127 | /** |
2059 | * Initialize and run scheduler. This function will return when all | 2128 | * Function called by external event loop implementations to initialize |
2060 | * tasks have completed. On systems with signals, receiving a SIGTERM | 2129 | * the scheduler. An external implementation has to provide @a driver |
2061 | * (and other similar signals) will cause #GNUNET_SCHEDULER_shutdown | 2130 | * which contains callbacks for the scheduler (see definition of struct |
2062 | * to be run after the active task is complete. As a result, SIGTERM | 2131 | * #GNUNET_SCHEDULER_Driver) for instructing the external implementation |
2063 | * causes all shutdown tasks to be scheduled with reason | 2132 | * to watch for events. If it detects any event it is expected to call |
2064 | * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added | 2133 | * #GNUNET_SCHEDULER_do_work to let the scheduler handle it. If an event |
2065 | * afterwards will execute normally!). Note that any particular | 2134 | * is related to a specific task (e.g. the scheduler gave instructions |
2066 | * signal will only shut down one scheduler; applications should | 2135 | * to watch a file descriptor), the external implementation is expected |
2067 | * always only create a single scheduler. | 2136 | * to mark that task ready before by calling #GNUNET_SCHEDULER_task_ready. |
2137 | |||
2138 | * This function has to be called before any tasks are scheduled and | ||
2139 | * before GNUNET_SCHEDULER_do_work is called for the first time. It | ||
2140 | * allocates resources that have to be freed again by calling | ||
2141 | * #GNUNET_SCHEDULER_driver_done. | ||
2068 | * | 2142 | * |
2069 | * @param driver drive to use for the event loop | 2143 | * This function installs the same signal handlers as |
2070 | * @param task task to run first (and immediately) | 2144 | * #GNUNET_SCHEDULER_run. This means SIGTERM (and other similar signals) |
2071 | * @param task_cls closure of @a task | 2145 | * will induce a call to #GNUNET_SCHEDULER_shutdown during the next |
2072 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | 2146 | * call to #GNUNET_SCHEDULER_do_work. As a result, SIGTERM causes all |
2147 | * active tasks to be scheduled with reason | ||
2148 | * #GNUNET_SCHEDULER_REASON_SHUTDOWN. (However, tasks added afterwards | ||
2149 | * will execute normally!). Note that any particular signal will only | ||
2150 | * shut down one scheduler; applications should always only create a | ||
2151 | * single scheduler. | ||
2152 | * | ||
2153 | * @param driver to use for the event loop | ||
2154 | * @return handle to be passed to #GNUNET_SCHEDULER_do_work and | ||
2155 | * #GNUNET_SCHEDULER_driver_done | ||
2073 | */ | 2156 | */ |
2074 | int | 2157 | struct GNUNET_SCHEDULER_Handle * |
2075 | GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | 2158 | GNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver) |
2076 | GNUNET_SCHEDULER_TaskCallback task, | ||
2077 | void *task_cls) | ||
2078 | { | 2159 | { |
2079 | int ret; | 2160 | struct GNUNET_SCHEDULER_Handle *sh; |
2080 | struct GNUNET_SIGNAL_Context *shc_int; | ||
2081 | struct GNUNET_SIGNAL_Context *shc_term; | ||
2082 | #if (SIGTERM != GNUNET_TERM_SIG) | ||
2083 | struct GNUNET_SIGNAL_Context *shc_gterm; | ||
2084 | #endif | ||
2085 | #ifndef MINGW | ||
2086 | struct GNUNET_SIGNAL_Context *shc_quit; | ||
2087 | struct GNUNET_SIGNAL_Context *shc_hup; | ||
2088 | struct GNUNET_SIGNAL_Context *shc_pipe; | ||
2089 | #endif | ||
2090 | struct GNUNET_SCHEDULER_Task tsk; | 2161 | struct GNUNET_SCHEDULER_Task tsk; |
2091 | const struct GNUNET_DISK_FileHandle *pr; | 2162 | const struct GNUNET_DISK_FileHandle *pr; |
2092 | 2163 | ||
2093 | /* general set-up */ | 2164 | /* general set-up */ |
2094 | GNUNET_assert (NULL == active_task); | 2165 | GNUNET_assert (NULL == active_task); |
2095 | GNUNET_assert (NULL == shutdown_pipe_handle); | 2166 | GNUNET_assert (NULL == shutdown_pipe_handle); |
2167 | sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle); | ||
2096 | shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, | 2168 | shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, |
2097 | GNUNET_NO, | 2169 | GNUNET_NO, |
2098 | GNUNET_NO, | 2170 | GNUNET_NO, |
@@ -2106,21 +2178,21 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | |||
2106 | /* install signal handlers */ | 2178 | /* install signal handlers */ |
2107 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2179 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2108 | "Registering signal handlers\n"); | 2180 | "Registering signal handlers\n"); |
2109 | shc_int = GNUNET_SIGNAL_handler_install (SIGINT, | 2181 | sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT, |
2110 | &sighandler_shutdown); | 2182 | &sighandler_shutdown); |
2111 | shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, | 2183 | sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, |
2112 | &sighandler_shutdown); | 2184 | &sighandler_shutdown); |
2113 | #if (SIGTERM != GNUNET_TERM_SIG) | 2185 | #if (SIGTERM != GNUNET_TERM_SIG) |
2114 | shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, | 2186 | sh->shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, |
2115 | &sighandler_shutdown); | 2187 | &sighandler_shutdown); |
2116 | #endif | 2188 | #endif |
2117 | #ifndef MINGW | 2189 | #ifndef MINGW |
2118 | shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, | 2190 | sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, |
2119 | &sighandler_pipe); | 2191 | &sighandler_pipe); |
2120 | shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, | 2192 | sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, |
2121 | &sighandler_shutdown); | 2193 | &sighandler_shutdown); |
2122 | shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, | 2194 | sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, |
2123 | &sighandler_shutdown); | 2195 | &sighandler_shutdown); |
2124 | #endif | 2196 | #endif |
2125 | 2197 | ||
2126 | /* Setup initial tasks */ | 2198 | /* Setup initial tasks */ |
@@ -2139,19 +2211,33 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | |||
2139 | &shutdown_pipe_cb, | 2211 | &shutdown_pipe_cb, |
2140 | NULL); | 2212 | NULL); |
2141 | current_lifeness = GNUNET_YES; | 2213 | current_lifeness = GNUNET_YES; |
2142 | GNUNET_SCHEDULER_add_with_reason_and_priority (task, | ||
2143 | task_cls, | ||
2144 | GNUNET_SCHEDULER_REASON_STARTUP, | ||
2145 | GNUNET_SCHEDULER_PRIORITY_DEFAULT); | ||
2146 | active_task = NULL; | 2214 | active_task = NULL; |
2147 | scheduler_driver->set_wakeup (scheduler_driver->cls, | 2215 | scheduler_driver->set_wakeup (scheduler_driver->cls, |
2148 | get_timeout ()); | 2216 | get_timeout ()); |
2149 | /* begin main event loop */ | 2217 | /* begin main event loop */ |
2150 | sh.rs = GNUNET_NETWORK_fdset_create (); | 2218 | sh->rs = GNUNET_NETWORK_fdset_create (); |
2151 | sh.ws = GNUNET_NETWORK_fdset_create (); | 2219 | sh->ws = GNUNET_NETWORK_fdset_create (); |
2152 | GNUNET_NETWORK_fdset_handle_set (sh.rs, pr); | 2220 | GNUNET_NETWORK_fdset_handle_set (sh->rs, pr); |
2153 | ret = driver->loop (driver->cls, | 2221 | return sh; |
2154 | &sh); | 2222 | } |
2223 | |||
2224 | |||
2225 | /** | ||
2226 | * Counter-part of #GNUNET_SCHEDULER_driver_init. Has to be called | ||
2227 | * by external event loop implementations after the scheduler has | ||
2228 | * shut down. This is the case if both of the following conditions | ||
2229 | * are met: | ||
2230 | * | ||
2231 | * - all tasks the scheduler has added through the driver's add | ||
2232 | * callback have been removed again through the driver's del | ||
2233 | * callback | ||
2234 | * - the timeout the scheduler has set through the driver's | ||
2235 | * add_wakeup callback is FOREVER | ||
2236 | * | ||
2237 | * @param sh the handle returned by #GNUNET_SCHEDULER_driver_init | ||
2238 | */ | ||
2239 | void GNUNET_SCHEDULER_driver_done (struct GNUNET_SCHEDULER_Handle *sh) | ||
2240 | { | ||
2155 | GNUNET_assert (NULL == pending_head); | 2241 | GNUNET_assert (NULL == pending_head); |
2156 | GNUNET_assert (NULL == pending_timeout_head); | 2242 | GNUNET_assert (NULL == pending_timeout_head); |
2157 | GNUNET_assert (NULL == shutdown_head); | 2243 | GNUNET_assert (NULL == shutdown_head); |
@@ -2159,97 +2245,34 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | |||
2159 | { | 2245 | { |
2160 | GNUNET_assert (NULL == ready_head[i]); | 2246 | GNUNET_assert (NULL == ready_head[i]); |
2161 | } | 2247 | } |
2162 | GNUNET_NETWORK_fdset_destroy (sh.rs); | 2248 | GNUNET_NETWORK_fdset_destroy (sh->rs); |
2163 | GNUNET_NETWORK_fdset_destroy (sh.ws); | 2249 | GNUNET_NETWORK_fdset_destroy (sh->ws); |
2164 | 2250 | ||
2165 | /* uninstall signal handlers */ | 2251 | /* uninstall signal handlers */ |
2166 | GNUNET_SIGNAL_handler_uninstall (shc_int); | 2252 | GNUNET_SIGNAL_handler_uninstall (sh->shc_int); |
2167 | GNUNET_SIGNAL_handler_uninstall (shc_term); | 2253 | GNUNET_SIGNAL_handler_uninstall (sh->shc_term); |
2168 | #if (SIGTERM != GNUNET_TERM_SIG) | 2254 | #if (SIGTERM != GNUNET_TERM_SIG) |
2169 | GNUNET_SIGNAL_handler_uninstall (shc_gterm); | 2255 | GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm); |
2170 | #endif | 2256 | #endif |
2171 | #ifndef MINGW | 2257 | #ifndef MINGW |
2172 | GNUNET_SIGNAL_handler_uninstall (shc_pipe); | 2258 | GNUNET_SIGNAL_handler_uninstall (sh->shc_pipe); |
2173 | GNUNET_SIGNAL_handler_uninstall (shc_quit); | 2259 | GNUNET_SIGNAL_handler_uninstall (sh->shc_quit); |
2174 | GNUNET_SIGNAL_handler_uninstall (shc_hup); | 2260 | GNUNET_SIGNAL_handler_uninstall (sh->shc_hup); |
2175 | #endif | 2261 | #endif |
2176 | GNUNET_DISK_pipe_close (shutdown_pipe_handle); | 2262 | GNUNET_DISK_pipe_close (shutdown_pipe_handle); |
2177 | shutdown_pipe_handle = NULL; | 2263 | shutdown_pipe_handle = NULL; |
2178 | scheduler_driver = NULL; | 2264 | scheduler_driver = NULL; |
2179 | return ret; | 2265 | GNUNET_free (sh); |
2180 | } | ||
2181 | |||
2182 | |||
2183 | int | ||
2184 | select_add (void *cls, | ||
2185 | struct GNUNET_SCHEDULER_Task *task, | ||
2186 | struct GNUNET_SCHEDULER_FdInfo *fdi) | ||
2187 | { | ||
2188 | struct DriverContext *context = cls; | ||
2189 | GNUNET_assert (NULL != context); | ||
2190 | GNUNET_assert (NULL != task); | ||
2191 | GNUNET_assert (NULL != fdi); | ||
2192 | GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) || | ||
2193 | 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)); | ||
2194 | |||
2195 | if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0)) | ||
2196 | { | ||
2197 | /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ | ||
2198 | return GNUNET_SYSERR; | ||
2199 | } | ||
2200 | |||
2201 | struct Scheduled *scheduled = GNUNET_new (struct Scheduled); | ||
2202 | scheduled->task = task; | ||
2203 | scheduled->fdi = fdi; | ||
2204 | scheduled->et = fdi->et; | ||
2205 | |||
2206 | GNUNET_CONTAINER_DLL_insert (context->scheduled_head, | ||
2207 | context->scheduled_tail, | ||
2208 | scheduled); | ||
2209 | return GNUNET_OK; | ||
2210 | } | 2266 | } |
2211 | 2267 | ||
2212 | 2268 | ||
2213 | int | 2269 | int |
2214 | select_del (void *cls, | 2270 | select_loop (struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context) |
2215 | struct GNUNET_SCHEDULER_Task *task) | ||
2216 | { | ||
2217 | struct DriverContext *context; | ||
2218 | struct Scheduled *pos; | ||
2219 | int ret; | ||
2220 | |||
2221 | GNUNET_assert (NULL != cls); | ||
2222 | |||
2223 | context = cls; | ||
2224 | ret = GNUNET_SYSERR; | ||
2225 | pos = context->scheduled_head; | ||
2226 | while (NULL != pos) | ||
2227 | { | ||
2228 | struct Scheduled *next = pos->next; | ||
2229 | if (pos->task == task) | ||
2230 | { | ||
2231 | GNUNET_CONTAINER_DLL_remove (context->scheduled_head, | ||
2232 | context->scheduled_tail, | ||
2233 | pos); | ||
2234 | GNUNET_free (pos); | ||
2235 | ret = GNUNET_OK; | ||
2236 | } | ||
2237 | pos = next; | ||
2238 | } | ||
2239 | return ret; | ||
2240 | } | ||
2241 | |||
2242 | |||
2243 | int | ||
2244 | select_loop (void *cls, | ||
2245 | struct GNUNET_SCHEDULER_Handle *sh) | ||
2246 | { | 2271 | { |
2247 | struct GNUNET_NETWORK_FDSet *rs; | 2272 | struct GNUNET_NETWORK_FDSet *rs; |
2248 | struct GNUNET_NETWORK_FDSet *ws; | 2273 | struct GNUNET_NETWORK_FDSet *ws; |
2249 | struct DriverContext *context; | ||
2250 | int select_result; | 2274 | int select_result; |
2251 | 2275 | ||
2252 | context = cls; | ||
2253 | GNUNET_assert (NULL != context); | 2276 | GNUNET_assert (NULL != context); |
2254 | rs = GNUNET_NETWORK_fdset_create (); | 2277 | rs = GNUNET_NETWORK_fdset_create (); |
2255 | ws = GNUNET_NETWORK_fdset_create (); | 2278 | ws = GNUNET_NETWORK_fdset_create (); |
@@ -2350,7 +2373,7 @@ select_loop (void *cls, | |||
2350 | } | 2373 | } |
2351 | } | 2374 | } |
2352 | } | 2375 | } |
2353 | if (GNUNET_YES == GNUNET_SCHEDULER_run_from_driver (sh)) | 2376 | if (GNUNET_YES == GNUNET_SCHEDULER_do_work (sh)) |
2354 | { | 2377 | { |
2355 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2378 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2356 | "scheduler has more tasks ready!\n"); | 2379 | "scheduler has more tasks ready!\n"); |
@@ -2362,6 +2385,66 @@ select_loop (void *cls, | |||
2362 | } | 2385 | } |
2363 | 2386 | ||
2364 | 2387 | ||
2388 | int | ||
2389 | select_add (void *cls, | ||
2390 | struct GNUNET_SCHEDULER_Task *task, | ||
2391 | struct GNUNET_SCHEDULER_FdInfo *fdi) | ||
2392 | { | ||
2393 | struct DriverContext *context = cls; | ||
2394 | GNUNET_assert (NULL != context); | ||
2395 | GNUNET_assert (NULL != task); | ||
2396 | GNUNET_assert (NULL != fdi); | ||
2397 | GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) || | ||
2398 | 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)); | ||
2399 | |||
2400 | if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0)) | ||
2401 | { | ||
2402 | /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ | ||
2403 | return GNUNET_SYSERR; | ||
2404 | } | ||
2405 | |||
2406 | struct Scheduled *scheduled = GNUNET_new (struct Scheduled); | ||
2407 | scheduled->task = task; | ||
2408 | scheduled->fdi = fdi; | ||
2409 | scheduled->et = fdi->et; | ||
2410 | |||
2411 | GNUNET_CONTAINER_DLL_insert (context->scheduled_head, | ||
2412 | context->scheduled_tail, | ||
2413 | scheduled); | ||
2414 | return GNUNET_OK; | ||
2415 | } | ||
2416 | |||
2417 | |||
2418 | int | ||
2419 | select_del (void *cls, | ||
2420 | struct GNUNET_SCHEDULER_Task *task) | ||
2421 | { | ||
2422 | struct DriverContext *context; | ||
2423 | struct Scheduled *pos; | ||
2424 | int ret; | ||
2425 | |||
2426 | GNUNET_assert (NULL != cls); | ||
2427 | |||
2428 | context = cls; | ||
2429 | ret = GNUNET_SYSERR; | ||
2430 | pos = context->scheduled_head; | ||
2431 | while (NULL != pos) | ||
2432 | { | ||
2433 | struct Scheduled *next = pos->next; | ||
2434 | if (pos->task == task) | ||
2435 | { | ||
2436 | GNUNET_CONTAINER_DLL_remove (context->scheduled_head, | ||
2437 | context->scheduled_tail, | ||
2438 | pos); | ||
2439 | GNUNET_free (pos); | ||
2440 | ret = GNUNET_OK; | ||
2441 | } | ||
2442 | pos = next; | ||
2443 | } | ||
2444 | return ret; | ||
2445 | } | ||
2446 | |||
2447 | |||
2365 | void | 2448 | void |
2366 | select_set_wakeup (void *cls, | 2449 | select_set_wakeup (void *cls, |
2367 | struct GNUNET_TIME_Absolute dt) | 2450 | struct GNUNET_TIME_Absolute dt) |
@@ -2384,7 +2467,6 @@ GNUNET_SCHEDULER_driver_select () | |||
2384 | struct GNUNET_SCHEDULER_Driver *select_driver; | 2467 | struct GNUNET_SCHEDULER_Driver *select_driver; |
2385 | select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver); | 2468 | select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver); |
2386 | 2469 | ||
2387 | select_driver->loop = &select_loop; | ||
2388 | select_driver->add = &select_add; | 2470 | select_driver->add = &select_add; |
2389 | select_driver->del = &select_del; | 2471 | select_driver->del = &select_del; |
2390 | select_driver->set_wakeup = &select_set_wakeup; | 2472 | select_driver->set_wakeup = &select_set_wakeup; |