diff options
author | lurchi <lurchi@strangeplace.net> | 2017-09-04 11:56:48 +0200 |
---|---|---|
committer | lurchi <lurchi@strangeplace.net> | 2017-09-04 11:56:48 +0200 |
commit | b851ecf1aa048e51439e3be631cd19ca84e4dc5a (patch) | |
tree | 22e0a9f43d340e9e1ae16476fb4b1ba21ea4df62 /src | |
parent | 652198e93fb05d301e6a8873b0364692f7f47ce4 (diff) | |
download | gnunet-b851ecf1aa048e51439e3be631cd19ca84e4dc5a.tar.gz gnunet-b851ecf1aa048e51439e3be631cd19ca84e4dc5a.zip |
Remove busy waiting checks
Busy waiting should never happen (at least the shutdown pipe is always
there for the driver to wait for).
When busy waiting happens, i.e. GNUNET_SCHEDULER_run_from_driver is
called without any task ready, it is a programming error (at least I
don't know any valid use case for busy waiting).
Hence, remove the busy waiting checks and let
GNUNET_SCHEDULER_run_from_driver return GNUNET_SYSERR instead in this
case.
Diffstat (limited to 'src')
-rw-r--r-- | src/util/scheduler.c | 79 |
1 files changed, 26 insertions, 53 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index ac9494fa0..5f627cfb5 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -595,22 +595,22 @@ sighandler_pipe () | |||
595 | #endif | 595 | #endif |
596 | 596 | ||
597 | 597 | ||
598 | /** | 598 | ///** |
599 | * Wait for a short time. | 599 | // * Wait for a short time. |
600 | * Sleeps for @a ms ms (as that should be long enough for virtually all | 600 | // * Sleeps for @a ms ms (as that should be long enough for virtually all |
601 | * modern systems to context switch and allow another process to do | 601 | // * modern systems to context switch and allow another process to do |
602 | * some 'real' work). | 602 | // * some 'real' work). |
603 | * | 603 | // * |
604 | * @param ms how many ms to wait | 604 | // * @param ms how many ms to wait |
605 | */ | 605 | // */ |
606 | static void | 606 | //static void |
607 | short_wait (unsigned int ms) | 607 | //short_wait (unsigned int ms) |
608 | { | 608 | //{ |
609 | struct GNUNET_TIME_Relative timeout; | 609 | // struct GNUNET_TIME_Relative timeout; |
610 | 610 | // | |
611 | timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms); | 611 | // timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms); |
612 | (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); | 612 | // (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); |
613 | } | 613 | //} |
614 | 614 | ||
615 | 615 | ||
616 | /** | 616 | /** |
@@ -1873,15 +1873,16 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, | |||
1873 | * there are tasks left to run just to give other tasks a chance as | 1873 | * there are tasks left to run just to give other tasks a chance as |
1874 | * well. If we return #GNUNET_YES, the driver should call this | 1874 | * well. If we return #GNUNET_YES, the driver should call this |
1875 | * function again as soon as possible, while if we return #GNUNET_NO | 1875 | * function again as soon as possible, while if we return #GNUNET_NO |
1876 | * it must block until the operating system has more work as the | 1876 | * it must block until either the operating system has more work (the |
1877 | * scheduler has no more work to do right now. | 1877 | * scheduler has no more work to do right now) or the timeout set by |
1878 | * the scheduler (using the set_wakeup callback) is reached. | ||
1878 | * | 1879 | * |
1879 | * @param sh scheduler handle that was given to the `loop` | 1880 | * @param sh scheduler handle that was given to the `loop` |
1880 | * @return #GNUNET_OK if there are more tasks that are ready, | 1881 | * @return #GNUNET_OK if there are more tasks that are ready, |
1881 | * and thus we would like to run more (yield to avoid | 1882 | * and thus we would like to run more (yield to avoid |
1882 | * blocking other activities for too long) | 1883 | * blocking other activities for too long) |
1883 | * #GNUNET_NO if we are done running tasks (yield to block) | 1884 | * #GNUNET_NO if we are done running tasks (yield to block) |
1884 | * #GNUNET_SYSERR on error | 1885 | * #GNUNET_SYSERR on error, e.g. no tasks were ready |
1885 | */ | 1886 | */ |
1886 | int | 1887 | int |
1887 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | 1888 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) |
@@ -1922,7 +1923,9 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
1922 | 1923 | ||
1923 | if (0 == ready_count) | 1924 | if (0 == ready_count) |
1924 | { | 1925 | { |
1925 | return GNUNET_NO; | 1926 | LOG (GNUNET_ERROR_TYPE_ERROR, |
1927 | "GNUNET_SCHEDULER_run_from_driver was called, but no tasks are ready!\n"); | ||
1928 | return GNUNET_SYSERR; | ||
1926 | } | 1929 | } |
1927 | 1930 | ||
1928 | /* find out which task priority level we are going to | 1931 | /* find out which task priority level we are going to |
@@ -1985,6 +1988,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
1985 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1988 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1986 | "Running task %p\n", | 1989 | "Running task %p\n", |
1987 | pos); | 1990 | pos); |
1991 | GNUNET_assert (NULL != pos->callback); | ||
1988 | pos->callback (pos->callback_cls); | 1992 | pos->callback (pos->callback_cls); |
1989 | if (NULL != pos->fds) | 1993 | if (NULL != pos->fds) |
1990 | { | 1994 | { |
@@ -2199,16 +2203,12 @@ select_loop (void *cls, | |||
2199 | struct DriverContext *context; | 2203 | struct DriverContext *context; |
2200 | int select_result; | 2204 | int select_result; |
2201 | int tasks_ready; | 2205 | int tasks_ready; |
2202 | unsigned long long last_tr; | 2206 | |
2203 | unsigned int busy_wait_warning; | ||
2204 | |||
2205 | context = cls; | 2207 | context = cls; |
2206 | GNUNET_assert (NULL != context); | 2208 | GNUNET_assert (NULL != context); |
2207 | rs = GNUNET_NETWORK_fdset_create (); | 2209 | rs = GNUNET_NETWORK_fdset_create (); |
2208 | ws = GNUNET_NETWORK_fdset_create (); | 2210 | ws = GNUNET_NETWORK_fdset_create (); |
2209 | tasks_ready = GNUNET_NO; | 2211 | tasks_ready = GNUNET_NO; |
2210 | last_tr = 0; | ||
2211 | busy_wait_warning = 0; | ||
2212 | while (NULL != context->scheduled_head || GNUNET_YES == tasks_ready) | 2212 | while (NULL != context->scheduled_head || GNUNET_YES == tasks_ready) |
2213 | { | 2213 | { |
2214 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2214 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -2294,16 +2294,6 @@ select_loop (void *cls, | |||
2294 | GNUNET_assert (0); | 2294 | GNUNET_assert (0); |
2295 | return GNUNET_SYSERR; | 2295 | return GNUNET_SYSERR; |
2296 | } | 2296 | } |
2297 | if ( (0 == select_result) && | ||
2298 | (0 == context->timeout.rel_value_us) && | ||
2299 | (busy_wait_warning > 16) ) | ||
2300 | { | ||
2301 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2302 | "[%p] Looks like we're busy waiting...\n", | ||
2303 | sh); | ||
2304 | //GNUNET_assert (0); | ||
2305 | short_wait (100); /* mitigate */ | ||
2306 | } | ||
2307 | for (pos = context->scheduled_head; NULL != pos; pos = pos->next) | 2297 | for (pos = context->scheduled_head; NULL != pos; pos = pos->next) |
2308 | { | 2298 | { |
2309 | int is_ready = GNUNET_NO; | 2299 | int is_ready = GNUNET_NO; |
@@ -2321,28 +2311,11 @@ select_loop (void *cls, | |||
2321 | } | 2311 | } |
2322 | if (GNUNET_YES == is_ready) | 2312 | if (GNUNET_YES == is_ready) |
2323 | { | 2313 | { |
2324 | //GNUNET_CONTAINER_DLL_remove (context->scheduled_head, | ||
2325 | // context->scheduled_tail, | ||
2326 | // pos); | ||
2327 | GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); | 2314 | GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); |
2328 | } | 2315 | } |
2329 | } | 2316 | } |
2330 | tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); | 2317 | tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); |
2331 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2318 | GNUNET_assert (GNUNET_SYSERR != tasks_ready); |
2332 | "tasks_ready: %d\n", | ||
2333 | tasks_ready); | ||
2334 | // FIXME: tasks_run is a driver-internal variable! Instead we should increment | ||
2335 | // a local variable tasks_ready_count everytime we're calling GNUNET_SCHEDULER_task_ready. | ||
2336 | if (last_tr == tasks_run) | ||
2337 | { | ||
2338 | short_wait (1); | ||
2339 | busy_wait_warning++; | ||
2340 | } | ||
2341 | else | ||
2342 | { | ||
2343 | last_tr = tasks_run; | ||
2344 | busy_wait_warning = 0; | ||
2345 | } | ||
2346 | } | 2319 | } |
2347 | return GNUNET_OK; | 2320 | return GNUNET_OK; |
2348 | } | 2321 | } |