aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlurchi <lurchi@strangeplace.net>2017-09-04 11:56:48 +0200
committerlurchi <lurchi@strangeplace.net>2017-09-04 11:56:48 +0200
commitb851ecf1aa048e51439e3be631cd19ca84e4dc5a (patch)
tree22e0a9f43d340e9e1ae16476fb4b1ba21ea4df62 /src
parent652198e93fb05d301e6a8873b0364692f7f47ce4 (diff)
downloadgnunet-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.c79
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// */
606static void 606//static void
607short_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 */
1886int 1887int
1887GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) 1888GNUNET_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}