diff options
author | lurchi <lurchi@strangeplace.net> | 2018-07-29 18:18:34 +0200 |
---|---|---|
committer | lurchi <lurchi@strangeplace.net> | 2018-07-29 18:18:34 +0200 |
commit | 5bd70d462b4b50afd729eb234e0c2b6a02388bea (patch) | |
tree | e26bca5ad87b1564d11895bb8a03445d0466b637 | |
parent | 88d8593d0b28b81ced737da13a9c52e39faa8ec4 (diff) | |
download | gnunet-5bd70d462b4b50afd729eb234e0c2b6a02388bea.tar.gz gnunet-5bd70d462b4b50afd729eb234e0c2b6a02388bea.zip |
GNUNET_SCHEDULER_do_work: always check if shutdown is necessary and update wakeup
time
-rw-r--r-- | src/util/scheduler.c | 162 |
1 files changed, 86 insertions, 76 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 014288944..5d3836639 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -2022,99 +2022,109 @@ GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh) | |||
2022 | if (timeout.abs_value_us > now.abs_value_us) | 2022 | if (timeout.abs_value_us > now.abs_value_us) |
2023 | { | 2023 | { |
2024 | /** | 2024 | /** |
2025 | * The driver called this function before the current timeout was | 2025 | * The event loop called this function before the current timeout was |
2026 | * reached (and no FD tasks are ready). This can happen in the | 2026 | * reached (and no FD tasks are ready). This is acceptable if |
2027 | * rare case when the system time is changed while the driver is | 2027 | * |
2028 | * waiting for the timeout, so we handle this gracefully. It might | 2028 | * - the system time was changed while the driver was waiting for |
2029 | * also be a programming error in the driver though. | 2029 | * the timeout |
2030 | * - an external event loop called GNUnet API functions outside of | ||
2031 | * the callbacks called in GNUNET_SCHEDULER_do_work and thus | ||
2032 | * wasn't notified about the new timeout | ||
2033 | * | ||
2034 | * It might also mean we are busy-waiting because of a programming | ||
2035 | * error in the external event loop. | ||
2030 | */ | 2036 | */ |
2031 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2037 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2032 | "GNUNET_SCHEDULER_do_work did not find any ready " | 2038 | "GNUNET_SCHEDULER_do_work did not find any ready " |
2033 | "tasks and timeout has not been reached yet.\n"); | 2039 | "tasks and timeout has not been reached yet.\n"); |
2034 | return GNUNET_NO; | ||
2035 | } | 2040 | } |
2036 | /** | 2041 | else |
2037 | * the current timeout was reached but no ready tasks were found, | 2042 | { |
2038 | * internal scheduler error! | 2043 | /** |
2039 | */ | 2044 | * the current timeout was reached but no ready tasks were found, |
2040 | GNUNET_assert (0); | 2045 | * internal scheduler error! |
2041 | } | 2046 | */ |
2042 | 2047 | GNUNET_assert (0); | |
2043 | /* find out which task priority level we are going to | 2048 | } |
2044 | process this time */ | ||
2045 | max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; | ||
2046 | GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]); | ||
2047 | /* yes, p>0 is correct, 0 is "KEEP" which should | ||
2048 | * always be an empty queue (see assertion)! */ | ||
2049 | for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--) | ||
2050 | { | ||
2051 | pos = ready_head[p]; | ||
2052 | if (NULL != pos) | ||
2053 | break; | ||
2054 | } | 2049 | } |
2055 | GNUNET_assert (NULL != pos); /* ready_count wrong? */ | 2050 | else |
2056 | |||
2057 | /* process all tasks at this priority level, then yield */ | ||
2058 | while (NULL != (pos = ready_head[p])) | ||
2059 | { | 2051 | { |
2060 | GNUNET_CONTAINER_DLL_remove (ready_head[p], | 2052 | /* find out which task priority level we are going to |
2061 | ready_tail[p], | 2053 | process this time */ |
2062 | pos); | 2054 | max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; |
2063 | ready_count--; | 2055 | GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]); |
2064 | current_priority = pos->priority; | 2056 | /* yes, p>0 is correct, 0 is "KEEP" which should |
2065 | current_lifeness = pos->lifeness; | 2057 | * always be an empty queue (see assertion)! */ |
2066 | active_task = pos; | 2058 | for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--) |
2067 | #if PROFILE_DELAYS | ||
2068 | if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > | ||
2069 | DELAY_THRESHOLD.rel_value_us) | ||
2070 | { | 2059 | { |
2071 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2060 | pos = ready_head[p]; |
2072 | "Task %p took %s to be scheduled\n", | 2061 | if (NULL != pos) |
2073 | pos, | 2062 | break; |
2074 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), | ||
2075 | GNUNET_YES)); | ||
2076 | } | 2063 | } |
2077 | #endif | 2064 | GNUNET_assert (NULL != pos); /* ready_count wrong? */ |
2078 | tc.reason = pos->reason; | 2065 | |
2079 | GNUNET_NETWORK_fdset_zero (sh->rs); | 2066 | /* process all tasks at this priority level, then yield */ |
2080 | GNUNET_NETWORK_fdset_zero (sh->ws); | 2067 | while (NULL != (pos = ready_head[p])) |
2081 | // FIXME: do we have to remove FdInfos from fds if they are not ready? | ||
2082 | tc.fds_len = pos->fds_len; | ||
2083 | tc.fds = pos->fds; | ||
2084 | for (unsigned int i = 0; i != pos->fds_len; ++i) | ||
2085 | { | 2068 | { |
2086 | struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i]; | 2069 | GNUNET_CONTAINER_DLL_remove (ready_head[p], |
2087 | if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) | 2070 | ready_tail[p], |
2071 | pos); | ||
2072 | ready_count--; | ||
2073 | current_priority = pos->priority; | ||
2074 | current_lifeness = pos->lifeness; | ||
2075 | active_task = pos; | ||
2076 | #if PROFILE_DELAYS | ||
2077 | if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us > | ||
2078 | DELAY_THRESHOLD.rel_value_us) | ||
2088 | { | 2079 | { |
2089 | GNUNET_NETWORK_fdset_set_native (sh->rs, | 2080 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2090 | fdi->sock); | 2081 | "Task %p took %s to be scheduled\n", |
2082 | pos, | ||
2083 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), | ||
2084 | GNUNET_YES)); | ||
2091 | } | 2085 | } |
2092 | if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) | 2086 | #endif |
2087 | tc.reason = pos->reason; | ||
2088 | GNUNET_NETWORK_fdset_zero (sh->rs); | ||
2089 | GNUNET_NETWORK_fdset_zero (sh->ws); | ||
2090 | // FIXME: do we have to remove FdInfos from fds if they are not ready? | ||
2091 | tc.fds_len = pos->fds_len; | ||
2092 | tc.fds = pos->fds; | ||
2093 | for (unsigned int i = 0; i != pos->fds_len; ++i) | ||
2093 | { | 2094 | { |
2094 | GNUNET_NETWORK_fdset_set_native (sh->ws, | 2095 | struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i]; |
2095 | fdi->sock); | 2096 | if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) |
2097 | { | ||
2098 | GNUNET_NETWORK_fdset_set_native (sh->rs, | ||
2099 | fdi->sock); | ||
2100 | } | ||
2101 | if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) | ||
2102 | { | ||
2103 | GNUNET_NETWORK_fdset_set_native (sh->ws, | ||
2104 | fdi->sock); | ||
2105 | } | ||
2096 | } | 2106 | } |
2097 | } | 2107 | tc.read_ready = sh->rs; |
2098 | tc.read_ready = sh->rs; | 2108 | tc.write_ready = sh->ws; |
2099 | tc.write_ready = sh->ws; | 2109 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2100 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2110 | "Running task %p\n", |
2101 | "Running task %p\n", | 2111 | pos); |
2102 | pos); | 2112 | GNUNET_assert (NULL != pos->callback); |
2103 | GNUNET_assert (NULL != pos->callback); | 2113 | pos->callback (pos->callback_cls); |
2104 | pos->callback (pos->callback_cls); | 2114 | if (NULL != pos->fds) |
2105 | if (NULL != pos->fds) | ||
2106 | { | ||
2107 | int del_result = scheduler_driver->del (scheduler_driver->cls, pos); | ||
2108 | if (GNUNET_OK != del_result) | ||
2109 | { | 2115 | { |
2110 | LOG (GNUNET_ERROR_TYPE_ERROR, | 2116 | int del_result = scheduler_driver->del (scheduler_driver->cls, pos); |
2111 | "driver could not delete task %p\n", pos); | 2117 | if (GNUNET_OK != del_result) |
2112 | GNUNET_assert (0); | 2118 | { |
2119 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
2120 | "driver could not delete task %p\n", pos); | ||
2121 | GNUNET_assert (0); | ||
2122 | } | ||
2113 | } | 2123 | } |
2124 | active_task = NULL; | ||
2125 | dump_backtrace (pos); | ||
2126 | destroy_task (pos); | ||
2114 | } | 2127 | } |
2115 | active_task = NULL; | ||
2116 | dump_backtrace (pos); | ||
2117 | destroy_task (pos); | ||
2118 | } | 2128 | } |
2119 | shutdown_if_no_lifeness (); | 2129 | shutdown_if_no_lifeness (); |
2120 | if (0 == ready_count) | 2130 | if (0 == ready_count) |