diff options
Diffstat (limited to 'src/util/scheduler.c')
-rw-r--r-- | src/util/scheduler.c | 621 |
1 files changed, 291 insertions, 330 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 87a107dba..ec45889ea 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -71,19 +71,24 @@ | |||
71 | 71 | ||
72 | 72 | ||
73 | /** | 73 | /** |
74 | * Linked list of pending tasks. | 74 | * Entry in list of pending tasks. |
75 | */ | 75 | */ |
76 | struct Task | 76 | struct GNUNET_SCHEDULER_Task |
77 | { | 77 | { |
78 | /** | 78 | /** |
79 | * This is a linked list. | 79 | * This is a linked list. |
80 | */ | 80 | */ |
81 | struct Task *next; | 81 | struct GNUNET_SCHEDULER_Task *next; |
82 | |||
83 | /** | ||
84 | * This is a linked list. | ||
85 | */ | ||
86 | struct GNUNET_SCHEDULER_Task *prev; | ||
82 | 87 | ||
83 | /** | 88 | /** |
84 | * Function to run when ready. | 89 | * Function to run when ready. |
85 | */ | 90 | */ |
86 | GNUNET_SCHEDULER_Task callback; | 91 | GNUNET_SCHEDULER_TaskCallback callback; |
87 | 92 | ||
88 | /** | 93 | /** |
89 | * Closure for the @e callback. | 94 | * Closure for the @e callback. |
@@ -106,13 +111,8 @@ struct Task | |||
106 | struct GNUNET_NETWORK_FDSet *write_set; | 111 | struct GNUNET_NETWORK_FDSet *write_set; |
107 | 112 | ||
108 | /** | 113 | /** |
109 | * Unique task identifier. | ||
110 | */ | ||
111 | GNUNET_SCHEDULER_TaskIdentifier id; | ||
112 | |||
113 | /** | ||
114 | * Absolute timeout value for the task, or | 114 | * Absolute timeout value for the task, or |
115 | * GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout". | 115 | * #GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout". |
116 | */ | 116 | */ |
117 | struct GNUNET_TIME_Absolute timeout; | 117 | struct GNUNET_TIME_Absolute timeout; |
118 | 118 | ||
@@ -169,9 +169,14 @@ struct Task | |||
169 | 169 | ||
170 | 170 | ||
171 | /** | 171 | /** |
172 | * List of tasks waiting for an event. | 172 | * Head of list of tasks waiting for an event. |
173 | */ | ||
174 | static struct GNUNET_SCHEDULER_Task *pending_head; | ||
175 | |||
176 | /** | ||
177 | * Tail of list of tasks waiting for an event. | ||
173 | */ | 178 | */ |
174 | static struct Task *pending; | 179 | static struct GNUNET_SCHEDULER_Task *pending_tail; |
175 | 180 | ||
176 | /** | 181 | /** |
177 | * List of tasks waiting ONLY for a timeout event. | 182 | * List of tasks waiting ONLY for a timeout event. |
@@ -180,31 +185,37 @@ static struct Task *pending; | |||
180 | * building select sets (we just look at the head | 185 | * building select sets (we just look at the head |
181 | * to determine the respective timeout ONCE). | 186 | * to determine the respective timeout ONCE). |
182 | */ | 187 | */ |
183 | static struct Task *pending_timeout; | 188 | static struct GNUNET_SCHEDULER_Task *pending_timeout_head; |
189 | |||
190 | /** | ||
191 | * List of tasks waiting ONLY for a timeout event. | ||
192 | * Sorted by timeout (earliest first). Used so that | ||
193 | * we do not traverse the list of these tasks when | ||
194 | * building select sets (we just look at the head | ||
195 | * to determine the respective timeout ONCE). | ||
196 | */ | ||
197 | static struct GNUNET_SCHEDULER_Task *pending_timeout_tail; | ||
184 | 198 | ||
185 | /** | 199 | /** |
186 | * Last inserted task waiting ONLY for a timeout event. | 200 | * Last inserted task waiting ONLY for a timeout event. |
187 | * Used to (heuristically) speed up insertion. | 201 | * Used to (heuristically) speed up insertion. |
188 | */ | 202 | */ |
189 | static struct Task *pending_timeout_last; | 203 | static struct GNUNET_SCHEDULER_Task *pending_timeout_last; |
190 | 204 | ||
191 | /** | 205 | /** |
192 | * ID of the task that is running right now. | 206 | * ID of the task that is running right now. |
193 | */ | 207 | */ |
194 | static struct Task *active_task; | 208 | static struct GNUNET_SCHEDULER_Task *active_task; |
195 | 209 | ||
196 | /** | 210 | /** |
197 | * List of tasks ready to run right now, | 211 | * Head of list of tasks ready to run right now, grouped by importance. |
198 | * grouped by importance. | ||
199 | */ | 212 | */ |
200 | static struct Task *ready[GNUNET_SCHEDULER_PRIORITY_COUNT]; | 213 | static struct GNUNET_SCHEDULER_Task *ready_head[GNUNET_SCHEDULER_PRIORITY_COUNT]; |
201 | 214 | ||
202 | /** | 215 | /** |
203 | * Identity of the last task queued. Incremented for each task to | 216 | * Tail of list of tasks ready to run right now, grouped by importance. |
204 | * generate a unique task ID (it is virtually impossible to start | ||
205 | * more than 2^64 tasks during the lifetime of a process). | ||
206 | */ | 217 | */ |
207 | static GNUNET_SCHEDULER_TaskIdentifier last_id; | 218 | static struct GNUNET_SCHEDULER_Task *ready_tail[GNUNET_SCHEDULER_PRIORITY_COUNT]; |
208 | 219 | ||
209 | /** | 220 | /** |
210 | * Number of tasks on the ready list. | 221 | * Number of tasks on the ready list. |
@@ -240,10 +251,11 @@ static int current_lifeness; | |||
240 | static GNUNET_SCHEDULER_select scheduler_select; | 251 | static GNUNET_SCHEDULER_select scheduler_select; |
241 | 252 | ||
242 | /** | 253 | /** |
243 | * Closure for 'scheduler_select'. | 254 | * Closure for #scheduler_select. |
244 | */ | 255 | */ |
245 | static void *scheduler_select_cls; | 256 | static void *scheduler_select_cls; |
246 | 257 | ||
258 | |||
247 | /** | 259 | /** |
248 | * Sets the select function to use in the scheduler (scheduler_select). | 260 | * Sets the select function to use in the scheduler (scheduler_select). |
249 | * | 261 | * |
@@ -284,25 +296,25 @@ check_priority (enum GNUNET_SCHEDULER_Priority p) | |||
284 | * @param timeout next timeout (updated) | 296 | * @param timeout next timeout (updated) |
285 | */ | 297 | */ |
286 | static void | 298 | static void |
287 | update_sets (struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws, | 299 | update_sets (struct GNUNET_NETWORK_FDSet *rs, |
300 | struct GNUNET_NETWORK_FDSet *ws, | ||
288 | struct GNUNET_TIME_Relative *timeout) | 301 | struct GNUNET_TIME_Relative *timeout) |
289 | { | 302 | { |
290 | struct Task *pos; | 303 | struct GNUNET_SCHEDULER_Task *pos; |
291 | struct GNUNET_TIME_Absolute now; | 304 | struct GNUNET_TIME_Absolute now; |
292 | struct GNUNET_TIME_Relative to; | 305 | struct GNUNET_TIME_Relative to; |
293 | 306 | ||
294 | now = GNUNET_TIME_absolute_get (); | 307 | now = GNUNET_TIME_absolute_get (); |
295 | pos = pending_timeout; | 308 | pos = pending_timeout_head; |
296 | if (NULL != pos) | 309 | if (NULL != pos) |
297 | { | 310 | { |
298 | to = GNUNET_TIME_absolute_get_difference (now, pos->timeout); | 311 | to = GNUNET_TIME_absolute_get_difference (now, pos->timeout); |
299 | if (timeout->rel_value_us > to.rel_value_us) | 312 | if (timeout->rel_value_us > to.rel_value_us) |
300 | *timeout = to; | 313 | *timeout = to; |
301 | if (pos->reason != 0) | 314 | if (0 != pos->reason) |
302 | *timeout = GNUNET_TIME_UNIT_ZERO; | 315 | *timeout = GNUNET_TIME_UNIT_ZERO; |
303 | } | 316 | } |
304 | pos = pending; | 317 | for (pos = pending_head; NULL != pos; pos = pos->next) |
305 | while (NULL != pos) | ||
306 | { | 318 | { |
307 | if (pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) | 319 | if (pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) |
308 | { | 320 | { |
@@ -320,7 +332,6 @@ update_sets (struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws, | |||
320 | GNUNET_NETWORK_fdset_add (ws, pos->write_set); | 332 | GNUNET_NETWORK_fdset_add (ws, pos->write_set); |
321 | if (0 != pos->reason) | 333 | if (0 != pos->reason) |
322 | *timeout = GNUNET_TIME_UNIT_ZERO; | 334 | *timeout = GNUNET_TIME_UNIT_ZERO; |
323 | pos = pos->next; | ||
324 | } | 335 | } |
325 | } | 336 | } |
326 | 337 | ||
@@ -328,11 +339,11 @@ update_sets (struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws, | |||
328 | /** | 339 | /** |
329 | * Check if the ready set overlaps with the set we want to have ready. | 340 | * Check if the ready set overlaps with the set we want to have ready. |
330 | * If so, update the want set (set all FDs that are ready). If not, | 341 | * If so, update the want set (set all FDs that are ready). If not, |
331 | * return GNUNET_NO. | 342 | * return #GNUNET_NO. |
332 | * | 343 | * |
333 | * @param ready set that is ready | 344 | * @param ready set that is ready |
334 | * @param want set that we want to be ready | 345 | * @param want set that we want to be ready |
335 | * @return GNUNET_YES if there was some overlap | 346 | * @return #GNUNET_YES if there was some overlap |
336 | */ | 347 | */ |
337 | static int | 348 | static int |
338 | set_overlaps (const struct GNUNET_NETWORK_FDSet *ready, | 349 | set_overlaps (const struct GNUNET_NETWORK_FDSet *ready, |
@@ -362,7 +373,8 @@ set_overlaps (const struct GNUNET_NETWORK_FDSet *ready, | |||
362 | * @return #GNUNET_YES if we can run it, #GNUNET_NO if not. | 373 | * @return #GNUNET_YES if we can run it, #GNUNET_NO if not. |
363 | */ | 374 | */ |
364 | static int | 375 | static int |
365 | is_ready (struct Task *task, struct GNUNET_TIME_Absolute now, | 376 | is_ready (struct GNUNET_SCHEDULER_Task *task, |
377 | struct GNUNET_TIME_Absolute now, | ||
366 | const struct GNUNET_NETWORK_FDSet *rs, | 378 | const struct GNUNET_NETWORK_FDSet *rs, |
367 | const struct GNUNET_NETWORK_FDSet *ws) | 379 | const struct GNUNET_NETWORK_FDSet *ws) |
368 | { | 380 | { |
@@ -395,14 +407,15 @@ is_ready (struct Task *task, struct GNUNET_TIME_Absolute now, | |||
395 | * @param task task ready for execution | 407 | * @param task task ready for execution |
396 | */ | 408 | */ |
397 | static void | 409 | static void |
398 | queue_ready_task (struct Task *task) | 410 | queue_ready_task (struct GNUNET_SCHEDULER_Task *task) |
399 | { | 411 | { |
400 | enum GNUNET_SCHEDULER_Priority p = task->priority; | 412 | enum GNUNET_SCHEDULER_Priority p = check_priority (task->priority); |
401 | 413 | ||
402 | if (0 != (task->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 414 | if (0 != (task->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
403 | p = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN; | 415 | p = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN; |
404 | task->next = ready[check_priority (p)]; | 416 | GNUNET_CONTAINER_DLL_insert (ready_head[p], |
405 | ready[check_priority (p)] = task; | 417 | ready_tail[p], |
418 | task); | ||
406 | ready_count++; | 419 | ready_count++; |
407 | } | 420 | } |
408 | 421 | ||
@@ -418,45 +431,35 @@ static void | |||
418 | check_ready (const struct GNUNET_NETWORK_FDSet *rs, | 431 | check_ready (const struct GNUNET_NETWORK_FDSet *rs, |
419 | const struct GNUNET_NETWORK_FDSet *ws) | 432 | const struct GNUNET_NETWORK_FDSet *ws) |
420 | { | 433 | { |
421 | struct Task *pos; | 434 | struct GNUNET_SCHEDULER_Task *pos; |
422 | struct Task *prev; | 435 | struct GNUNET_SCHEDULER_Task *next; |
423 | struct Task *next; | ||
424 | struct GNUNET_TIME_Absolute now; | 436 | struct GNUNET_TIME_Absolute now; |
425 | 437 | ||
426 | now = GNUNET_TIME_absolute_get (); | 438 | now = GNUNET_TIME_absolute_get (); |
427 | prev = NULL; | 439 | while (NULL != (pos = pending_timeout_head)) |
428 | pos = pending_timeout; | ||
429 | while (NULL != pos) | ||
430 | { | 440 | { |
431 | next = pos->next; | ||
432 | if (now.abs_value_us >= pos->timeout.abs_value_us) | 441 | if (now.abs_value_us >= pos->timeout.abs_value_us) |
433 | pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; | 442 | pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; |
434 | if (0 == pos->reason) | 443 | if (0 == pos->reason) |
435 | break; | 444 | break; |
436 | pending_timeout = next; | 445 | GNUNET_CONTAINER_DLL_remove (pending_timeout_head, |
446 | pending_timeout_tail, | ||
447 | pos); | ||
437 | if (pending_timeout_last == pos) | 448 | if (pending_timeout_last == pos) |
438 | pending_timeout_last = NULL; | 449 | pending_timeout_last = NULL; |
439 | queue_ready_task (pos); | 450 | queue_ready_task (pos); |
440 | pos = next; | ||
441 | } | 451 | } |
442 | pos = pending; | 452 | pos = pending_head; |
443 | while (NULL != pos) | 453 | while (NULL != pos) |
444 | { | 454 | { |
445 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
446 | "Checking readiness of task: %llu / %p\n", | ||
447 | pos->id, pos->callback_cls); | ||
448 | next = pos->next; | 455 | next = pos->next; |
449 | if (GNUNET_YES == is_ready (pos, now, rs, ws)) | 456 | if (GNUNET_YES == is_ready (pos, now, rs, ws)) |
450 | { | 457 | { |
451 | if (NULL == prev) | 458 | GNUNET_CONTAINER_DLL_remove (pending_head, |
452 | pending = next; | 459 | pending_tail, |
453 | else | 460 | pos); |
454 | prev->next = next; | ||
455 | queue_ready_task (pos); | 461 | queue_ready_task (pos); |
456 | pos = next; | ||
457 | continue; | ||
458 | } | 462 | } |
459 | prev = pos; | ||
460 | pos = next; | 463 | pos = next; |
461 | } | 464 | } |
462 | } | 465 | } |
@@ -468,43 +471,24 @@ check_ready (const struct GNUNET_NETWORK_FDSet *rs, | |||
468 | * cause all tasks to run (as soon as possible, respecting | 471 | * cause all tasks to run (as soon as possible, respecting |
469 | * priorities and prerequisite tasks). Note that tasks | 472 | * priorities and prerequisite tasks). Note that tasks |
470 | * scheduled AFTER this call may still be delayed arbitrarily. | 473 | * scheduled AFTER this call may still be delayed arbitrarily. |
474 | * | ||
475 | * Note that we don't move the tasks into the ready queue yet; | ||
476 | * check_ready() will do that later, possibly adding additional | ||
477 | * readiness-factors | ||
471 | */ | 478 | */ |
472 | void | 479 | void |
473 | GNUNET_SCHEDULER_shutdown () | 480 | GNUNET_SCHEDULER_shutdown () |
474 | { | 481 | { |
475 | struct Task *pos; | 482 | struct GNUNET_SCHEDULER_Task *pos; |
476 | int i; | 483 | int i; |
477 | 484 | ||
478 | pos = pending_timeout; | 485 | for (pos = pending_timeout_head; NULL != pos; pos = pos->next) |
479 | while (NULL != pos) | ||
480 | { | ||
481 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; | 486 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; |
482 | /* we don't move the task into the ready queue yet; check_ready | 487 | for (pos = pending_head; NULL != pos; pos = pos->next) |
483 | * will do that later, possibly adding additional | ||
484 | * readiness-factors */ | ||
485 | pos = pos->next; | ||
486 | } | ||
487 | pos = pending; | ||
488 | while (NULL != pos) | ||
489 | { | ||
490 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; | 488 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; |
491 | /* we don't move the task into the ready queue yet; check_ready | ||
492 | * will do that later, possibly adding additional | ||
493 | * readiness-factors */ | ||
494 | pos = pos->next; | ||
495 | } | ||
496 | for (i = 0; i < GNUNET_SCHEDULER_PRIORITY_COUNT; i++) | 489 | for (i = 0; i < GNUNET_SCHEDULER_PRIORITY_COUNT; i++) |
497 | { | 490 | for (pos = ready_head[i]; NULL != pos; pos = pos->next) |
498 | pos = ready[i]; | ||
499 | while (NULL != pos) | ||
500 | { | ||
501 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; | 491 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; |
502 | /* we don't move the task into the ready queue yet; check_ready | ||
503 | * will do that later, possibly adding additional | ||
504 | * readiness-factors */ | ||
505 | pos = pos->next; | ||
506 | } | ||
507 | } | ||
508 | } | 492 | } |
509 | 493 | ||
510 | 494 | ||
@@ -514,7 +498,7 @@ GNUNET_SCHEDULER_shutdown () | |||
514 | * @param t task to destroy | 498 | * @param t task to destroy |
515 | */ | 499 | */ |
516 | static void | 500 | static void |
517 | destroy_task (struct Task *t) | 501 | destroy_task (struct GNUNET_SCHEDULER_Task *t) |
518 | { | 502 | { |
519 | if (NULL != t->read_set) | 503 | if (NULL != t->read_set) |
520 | GNUNET_NETWORK_fdset_destroy (t->read_set); | 504 | GNUNET_NETWORK_fdset_destroy (t->read_set); |
@@ -542,7 +526,7 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, | |||
542 | struct GNUNET_NETWORK_FDSet *ws) | 526 | struct GNUNET_NETWORK_FDSet *ws) |
543 | { | 527 | { |
544 | enum GNUNET_SCHEDULER_Priority p; | 528 | enum GNUNET_SCHEDULER_Priority p; |
545 | struct Task *pos; | 529 | struct GNUNET_SCHEDULER_Task *pos; |
546 | struct GNUNET_SCHEDULER_TaskContext tc; | 530 | struct GNUNET_SCHEDULER_TaskContext tc; |
547 | 531 | ||
548 | max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; | 532 | max_priority_added = GNUNET_SCHEDULER_PRIORITY_KEEP; |
@@ -550,17 +534,19 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, | |||
550 | { | 534 | { |
551 | if (0 == ready_count) | 535 | if (0 == ready_count) |
552 | return; | 536 | return; |
553 | GNUNET_assert (ready[GNUNET_SCHEDULER_PRIORITY_KEEP] == NULL); | 537 | GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]); |
554 | /* yes, p>0 is correct, 0 is "KEEP" which should | 538 | /* yes, p>0 is correct, 0 is "KEEP" which should |
555 | * always be an empty queue (see assertion)! */ | 539 | * always be an empty queue (see assertion)! */ |
556 | for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--) | 540 | for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--) |
557 | { | 541 | { |
558 | pos = ready[p]; | 542 | pos = ready_head[p]; |
559 | if (NULL != pos) | 543 | if (NULL != pos) |
560 | break; | 544 | break; |
561 | } | 545 | } |
562 | GNUNET_assert (NULL != pos); /* ready_count wrong? */ | 546 | GNUNET_assert (NULL != pos); /* ready_count wrong? */ |
563 | ready[p] = pos->next; | 547 | GNUNET_CONTAINER_DLL_remove (ready_head[p], |
548 | ready_tail[p], | ||
549 | pos); | ||
564 | ready_count--; | 550 | ready_count--; |
565 | current_priority = pos->priority; | 551 | current_priority = pos->priority; |
566 | current_lifeness = pos->lifeness; | 552 | current_lifeness = pos->lifeness; |
@@ -570,35 +556,35 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, | |||
570 | DELAY_THRESHOLD.rel_value_us) | 556 | DELAY_THRESHOLD.rel_value_us) |
571 | { | 557 | { |
572 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 558 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
573 | "Task %llu took %s to be scheduled\n", | 559 | "Task %p took %s to be scheduled\n", |
574 | (unsigned long long) pos->id, | 560 | pos, |
575 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), | 561 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), |
576 | GNUNET_YES)); | 562 | GNUNET_YES)); |
577 | } | 563 | } |
578 | #endif | 564 | #endif |
579 | tc.reason = pos->reason; | 565 | tc.reason = pos->reason; |
580 | tc.read_ready = (pos->read_set == NULL) ? rs : pos->read_set; | 566 | tc.read_ready = (NULL == pos->read_set) ? rs : pos->read_set; |
581 | if ((pos->read_fd != -1) && | 567 | if ((-1 != pos->read_fd) && |
582 | (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY))) | 568 | (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY))) |
583 | GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd); | 569 | GNUNET_NETWORK_fdset_set_native (rs, pos->read_fd); |
584 | tc.write_ready = (pos->write_set == NULL) ? ws : pos->write_set; | 570 | tc.write_ready = (NULL == pos->write_set) ? ws : pos->write_set; |
585 | if ((pos->write_fd != -1) && | 571 | if ((-1 != pos->write_fd) && |
586 | (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) | 572 | (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))) |
587 | GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd); | 573 | GNUNET_NETWORK_fdset_set_native (ws, pos->write_fd); |
588 | if (((tc.reason & GNUNET_SCHEDULER_REASON_WRITE_READY) != 0) && | 574 | if ((0 != (tc.reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && |
589 | (pos->write_fd != -1) && | 575 | (-1 != pos->write_fd) && |
590 | (!GNUNET_NETWORK_fdset_test_native (ws, pos->write_fd))) | 576 | (!GNUNET_NETWORK_fdset_test_native (ws, pos->write_fd))) |
591 | GNUNET_abort (); // added to ready in previous select loop! | 577 | GNUNET_abort (); // added to ready in previous select loop! |
592 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 578 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
593 | "Running task: %llu / %p\n", pos->id, | 579 | "Running task: %p\n", |
594 | pos->callback_cls); | 580 | pos); |
595 | pos->callback (pos->callback_cls, &tc); | 581 | pos->callback (pos->callback_cls, &tc); |
596 | #if EXECINFO | 582 | #if EXECINFO |
597 | int i; | 583 | unsigned int i; |
598 | 584 | ||
599 | for (i = 0; i < pos->num_backtrace_strings; i++) | 585 | for (i = 0; i < pos->num_backtrace_strings; i++) |
600 | LOG (GNUNET_ERROR_TYPE_ERROR, | 586 | LOG (GNUNET_ERROR_TYPE_ERROR, |
601 | "Task %llu trace %d: %s\n", | 587 | "Task %llu trace %u: %s\n", |
602 | pos->id, | 588 | pos->id, |
603 | i, | 589 | i, |
604 | pos->backtrace_strings[i]); | 590 | pos->backtrace_strings[i]); |
@@ -607,9 +593,10 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, | |||
607 | destroy_task (pos); | 593 | destroy_task (pos); |
608 | tasks_run++; | 594 | tasks_run++; |
609 | } | 595 | } |
610 | while ((NULL == pending) || (p >= max_priority_added)); | 596 | while ((NULL == pending_head) || (p >= max_priority_added)); |
611 | } | 597 | } |
612 | 598 | ||
599 | |||
613 | /** | 600 | /** |
614 | * Pipe used to communicate shutdown via signal. | 601 | * Pipe used to communicate shutdown via signal. |
615 | */ | 602 | */ |
@@ -680,17 +667,17 @@ sighandler_shutdown () | |||
680 | static int | 667 | static int |
681 | check_lifeness () | 668 | check_lifeness () |
682 | { | 669 | { |
683 | struct Task *t; | 670 | struct GNUNET_SCHEDULER_Task *t; |
684 | 671 | ||
685 | if (ready_count > 0) | 672 | if (ready_count > 0) |
686 | return GNUNET_OK; | 673 | return GNUNET_OK; |
687 | for (t = pending; NULL != t; t = t->next) | 674 | for (t = pending_head; NULL != t; t = t->next) |
688 | if (t->lifeness == GNUNET_YES) | 675 | if (t->lifeness == GNUNET_YES) |
689 | return GNUNET_OK; | 676 | return GNUNET_OK; |
690 | for (t = pending_timeout; NULL != t; t = t->next) | 677 | for (t = pending_timeout_head; NULL != t; t = t->next) |
691 | if (t->lifeness == GNUNET_YES) | 678 | if (t->lifeness == GNUNET_YES) |
692 | return GNUNET_OK; | 679 | return GNUNET_OK; |
693 | if ((NULL != pending) || (NULL != pending_timeout)) | 680 | if ((NULL != pending_head) || (NULL != pending_timeout_head)) |
694 | { | 681 | { |
695 | GNUNET_SCHEDULER_shutdown (); | 682 | GNUNET_SCHEDULER_shutdown (); |
696 | return GNUNET_OK; | 683 | return GNUNET_OK; |
@@ -714,7 +701,8 @@ check_lifeness () | |||
714 | * @param task_cls closure of @a task | 701 | * @param task_cls closure of @a task |
715 | */ | 702 | */ |
716 | void | 703 | void |
717 | GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) | 704 | GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, |
705 | void *task_cls) | ||
718 | { | 706 | { |
719 | struct GNUNET_NETWORK_FDSet *rs; | 707 | struct GNUNET_NETWORK_FDSet *rs; |
720 | struct GNUNET_NETWORK_FDSet *ws; | 708 | struct GNUNET_NETWORK_FDSet *ws; |
@@ -740,13 +728,17 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) | |||
740 | rs = GNUNET_NETWORK_fdset_create (); | 728 | rs = GNUNET_NETWORK_fdset_create (); |
741 | ws = GNUNET_NETWORK_fdset_create (); | 729 | ws = GNUNET_NETWORK_fdset_create (); |
742 | GNUNET_assert (NULL == shutdown_pipe_handle); | 730 | GNUNET_assert (NULL == shutdown_pipe_handle); |
743 | shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); | 731 | shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO, |
732 | GNUNET_NO, | ||
733 | GNUNET_NO, | ||
734 | GNUNET_NO); | ||
744 | GNUNET_assert (NULL != shutdown_pipe_handle); | 735 | GNUNET_assert (NULL != shutdown_pipe_handle); |
745 | pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, | 736 | pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle, |
746 | GNUNET_DISK_PIPE_END_READ); | 737 | GNUNET_DISK_PIPE_END_READ); |
747 | GNUNET_assert (pr != NULL); | 738 | GNUNET_assert (NULL != pr); |
748 | my_pid = getpid (); | 739 | my_pid = getpid (); |
749 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering signal handlers\n"); | 740 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
741 | "Registering signal handlers\n"); | ||
750 | shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); | 742 | shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); |
751 | shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown); | 743 | shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown); |
752 | #if (SIGTERM != GNUNET_TERM_SIG) | 744 | #if (SIGTERM != GNUNET_TERM_SIG) |
@@ -759,7 +751,8 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) | |||
759 | #endif | 751 | #endif |
760 | current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; | 752 | current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; |
761 | current_lifeness = GNUNET_YES; | 753 | current_lifeness = GNUNET_YES; |
762 | GNUNET_SCHEDULER_add_continuation (task, task_cls, | 754 | GNUNET_SCHEDULER_add_continuation (task, |
755 | task_cls, | ||
763 | GNUNET_SCHEDULER_REASON_STARTUP); | 756 | GNUNET_SCHEDULER_REASON_STARTUP); |
764 | active_task = (void *) (long) -1; /* force passing of sanity check */ | 757 | active_task = (void *) (long) -1; /* force passing of sanity check */ |
765 | GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, | 758 | GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, |
@@ -860,7 +853,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) | |||
860 | enum GNUNET_SCHEDULER_Reason | 853 | enum GNUNET_SCHEDULER_Reason |
861 | GNUNET_SCHEDULER_get_reason () | 854 | GNUNET_SCHEDULER_get_reason () |
862 | { | 855 | { |
863 | GNUNET_assert (active_task != NULL); | 856 | GNUNET_assert (NULL != active_task); |
864 | return active_task->reason; | 857 | return active_task->reason; |
865 | } | 858 | } |
866 | 859 | ||
@@ -877,21 +870,17 @@ GNUNET_SCHEDULER_get_reason () | |||
877 | unsigned int | 870 | unsigned int |
878 | GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) | 871 | GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) |
879 | { | 872 | { |
880 | struct Task *pos; | 873 | struct GNUNET_SCHEDULER_Task *pos; |
881 | unsigned int ret; | 874 | unsigned int ret; |
882 | 875 | ||
883 | GNUNET_assert (active_task != NULL); | 876 | GNUNET_assert (NULL != active_task); |
884 | if (p == GNUNET_SCHEDULER_PRIORITY_COUNT) | 877 | if (p == GNUNET_SCHEDULER_PRIORITY_COUNT) |
885 | return ready_count; | 878 | return ready_count; |
886 | if (p == GNUNET_SCHEDULER_PRIORITY_KEEP) | 879 | if (p == GNUNET_SCHEDULER_PRIORITY_KEEP) |
887 | p = current_priority; | 880 | p = current_priority; |
888 | ret = 0; | 881 | ret = 0; |
889 | pos = ready[check_priority (p)]; | 882 | for (pos = ready_head[check_priority (p)]; NULL != pos; pos = pos->next) |
890 | while (NULL != pos) | ||
891 | { | ||
892 | pos = pos->next; | ||
893 | ret++; | 883 | ret++; |
894 | } | ||
895 | return ret; | 884 | return ret; |
896 | } | 885 | } |
897 | 886 | ||
@@ -904,92 +893,45 @@ GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p) | |||
904 | * @return original closure of the task | 893 | * @return original closure of the task |
905 | */ | 894 | */ |
906 | void * | 895 | void * |
907 | GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task) | 896 | GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) |
908 | { | 897 | { |
909 | struct Task *t; | ||
910 | struct Task *prev; | ||
911 | enum GNUNET_SCHEDULER_Priority p; | 898 | enum GNUNET_SCHEDULER_Priority p; |
912 | int to; | ||
913 | void *ret; | 899 | void *ret; |
914 | 900 | ||
915 | GNUNET_assert (NULL != active_task); | 901 | GNUNET_assert (NULL != active_task); |
916 | to = 0; | 902 | if (GNUNET_SCHEDULER_REASON_NONE == task->reason) |
917 | prev = NULL; | ||
918 | t = pending; | ||
919 | while (NULL != t) | ||
920 | { | ||
921 | if (t->id == task) | ||
922 | break; | ||
923 | prev = t; | ||
924 | t = t->next; | ||
925 | } | ||
926 | if (NULL == t) | ||
927 | { | ||
928 | prev = NULL; | ||
929 | to = 1; | ||
930 | t = pending_timeout; | ||
931 | while (t != NULL) | ||
932 | { | ||
933 | if (t->id == task) | ||
934 | break; | ||
935 | prev = t; | ||
936 | t = t->next; | ||
937 | } | ||
938 | if (pending_timeout_last == t) | ||
939 | pending_timeout_last = NULL; | ||
940 | } | ||
941 | p = 0; | ||
942 | while (NULL == t) | ||
943 | { | ||
944 | p++; | ||
945 | if (p >= GNUNET_SCHEDULER_PRIORITY_COUNT) | ||
946 | { | ||
947 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
948 | _("Attempt to cancel dead task %llu!\n"), | ||
949 | (unsigned long long) task); | ||
950 | GNUNET_assert (0); | ||
951 | } | ||
952 | prev = NULL; | ||
953 | t = ready[p]; | ||
954 | while (NULL != t) | ||
955 | { | ||
956 | if (t->id == task) | ||
957 | { | ||
958 | ready_count--; | ||
959 | break; | ||
960 | } | ||
961 | prev = t; | ||
962 | t = t->next; | ||
963 | } | ||
964 | } | ||
965 | if (NULL == prev) | ||
966 | { | 903 | { |
967 | if (0 == p) | 904 | if ( (-1 == task->read_fd) && |
905 | (-1 == task->write_fd) && | ||
906 | (NULL == task->read_set) && | ||
907 | (NULL == task->write_set) ) | ||
968 | { | 908 | { |
969 | if (0 == to) | 909 | GNUNET_CONTAINER_DLL_remove (pending_timeout_head, |
970 | { | 910 | pending_timeout_tail, |
971 | pending = t->next; | 911 | task); |
972 | } | 912 | if (task == pending_timeout_last) |
973 | else | 913 | pending_timeout_last = NULL; |
974 | { | ||
975 | pending_timeout = t->next; | ||
976 | } | ||
977 | } | 914 | } |
978 | else | 915 | else |
979 | { | 916 | { |
980 | ready[p] = t->next; | 917 | GNUNET_CONTAINER_DLL_remove (pending_head, |
918 | pending_tail, | ||
919 | task); | ||
981 | } | 920 | } |
982 | } | 921 | } |
983 | else | 922 | else |
984 | { | 923 | { |
985 | prev->next = t->next; | 924 | p = check_priority (task->priority); |
925 | GNUNET_CONTAINER_DLL_remove (ready_head[p], | ||
926 | ready_tail[p], | ||
927 | task); | ||
928 | ready_count--; | ||
986 | } | 929 | } |
987 | ret = t->callback_cls; | 930 | ret = task->callback_cls; |
988 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 931 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
989 | "Canceling task: %llu / %p\n", | 932 | "Canceling task %p\n", |
990 | task, | 933 | task); |
991 | t->callback_cls); | 934 | destroy_task (task); |
992 | destroy_task (t); | ||
993 | return ret; | 935 | return ret; |
994 | } | 936 | } |
995 | 937 | ||
@@ -1005,11 +947,12 @@ GNUNET_SCHEDULER_cancel (GNUNET_SCHEDULER_TaskIdentifier task) | |||
1005 | * @param priority priority to use for the task | 947 | * @param priority priority to use for the task |
1006 | */ | 948 | */ |
1007 | void | 949 | void |
1008 | GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, void *task_cls, | 950 | GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_TaskCallback task, |
951 | void *task_cls, | ||
1009 | enum GNUNET_SCHEDULER_Reason reason, | 952 | enum GNUNET_SCHEDULER_Reason reason, |
1010 | enum GNUNET_SCHEDULER_Priority priority) | 953 | enum GNUNET_SCHEDULER_Priority priority) |
1011 | { | 954 | { |
1012 | struct Task *t; | 955 | struct GNUNET_SCHEDULER_Task *t; |
1013 | 956 | ||
1014 | #if EXECINFO | 957 | #if EXECINFO |
1015 | void *backtrace_array[50]; | 958 | void *backtrace_array[50]; |
@@ -1018,7 +961,7 @@ GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, voi | |||
1018 | GNUNET_assert (NULL != task); | 961 | GNUNET_assert (NULL != task); |
1019 | GNUNET_assert ((NULL != active_task) || | 962 | GNUNET_assert ((NULL != active_task) || |
1020 | (GNUNET_SCHEDULER_REASON_STARTUP == reason)); | 963 | (GNUNET_SCHEDULER_REASON_STARTUP == reason)); |
1021 | t = GNUNET_new (struct Task); | 964 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1022 | #if EXECINFO | 965 | #if EXECINFO |
1023 | t->num_backtrace_strings = backtrace (backtrace_array, 50); | 966 | t->num_backtrace_strings = backtrace (backtrace_array, 50); |
1024 | t->backtrace_strings = | 967 | t->backtrace_strings = |
@@ -1028,7 +971,6 @@ GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, voi | |||
1028 | t->write_fd = -1; | 971 | t->write_fd = -1; |
1029 | t->callback = task; | 972 | t->callback = task; |
1030 | t->callback_cls = task_cls; | 973 | t->callback_cls = task_cls; |
1031 | t->id = ++last_id; | ||
1032 | #if PROFILE_DELAYS | 974 | #if PROFILE_DELAYS |
1033 | t->start_time = GNUNET_TIME_absolute_get (); | 975 | t->start_time = GNUNET_TIME_absolute_get (); |
1034 | #endif | 976 | #endif |
@@ -1036,9 +978,8 @@ GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, voi | |||
1036 | t->priority = priority; | 978 | t->priority = priority; |
1037 | t->lifeness = current_lifeness; | 979 | t->lifeness = current_lifeness; |
1038 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 980 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1039 | "Adding continuation task: %llu / %p\n", | 981 | "Adding continuation task %p\n", |
1040 | t->id, | 982 | t); |
1041 | t->callback_cls); | ||
1042 | queue_ready_task (t); | 983 | queue_ready_task (t); |
1043 | } | 984 | } |
1044 | 985 | ||
@@ -1053,7 +994,7 @@ GNUNET_SCHEDULER_add_continuation_with_priority (GNUNET_SCHEDULER_Task task, voi | |||
1053 | * @param reason reason for task invocation | 994 | * @param reason reason for task invocation |
1054 | */ | 995 | */ |
1055 | void | 996 | void |
1056 | GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, void *task_cls, | 997 | GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_TaskCallback task, void *task_cls, |
1057 | enum GNUNET_SCHEDULER_Reason reason) | 998 | enum GNUNET_SCHEDULER_Reason reason) |
1058 | { | 999 | { |
1059 | GNUNET_SCHEDULER_add_continuation_with_priority (task, task_cls, | 1000 | GNUNET_SCHEDULER_add_continuation_with_priority (task, task_cls, |
@@ -1063,26 +1004,6 @@ GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, void *task_cls, | |||
1063 | 1004 | ||
1064 | 1005 | ||
1065 | /** | 1006 | /** |
1066 | * Schedule a new task to be run with a specified priority. | ||
1067 | * | ||
1068 | * @param prio how important is the new task? | ||
1069 | * @param task main function of the task | ||
1070 | * @param task_cls closure of @a task | ||
1071 | * @return unique task identifier for the job | ||
1072 | * only valid until @a task is started! | ||
1073 | */ | ||
1074 | GNUNET_SCHEDULER_TaskIdentifier | ||
1075 | GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio, | ||
1076 | GNUNET_SCHEDULER_Task task, void *task_cls) | ||
1077 | { | ||
1078 | return GNUNET_SCHEDULER_add_select (prio, | ||
1079 | GNUNET_TIME_UNIT_ZERO, NULL, NULL, task, | ||
1080 | task_cls); | ||
1081 | } | ||
1082 | |||
1083 | |||
1084 | |||
1085 | /** | ||
1086 | * Schedule a new task to be run with a specified delay. The task | 1007 | * Schedule a new task to be run with a specified delay. The task |
1087 | * will be scheduled for execution once the delay has expired. | 1008 | * will be scheduled for execution once the delay has expired. |
1088 | * | 1009 | * |
@@ -1094,14 +1015,15 @@ GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio, | |||
1094 | * @return unique task identifier for the job | 1015 | * @return unique task identifier for the job |
1095 | * only valid until @a task is started! | 1016 | * only valid until @a task is started! |
1096 | */ | 1017 | */ |
1097 | GNUNET_SCHEDULER_TaskIdentifier | 1018 | struct GNUNET_SCHEDULER_Task * |
1098 | GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, | 1019 | GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, |
1099 | enum GNUNET_SCHEDULER_Priority priority, | 1020 | enum GNUNET_SCHEDULER_Priority priority, |
1100 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1021 | GNUNET_SCHEDULER_TaskCallback task, |
1022 | void *task_cls) | ||
1101 | { | 1023 | { |
1102 | struct Task *t; | 1024 | struct GNUNET_SCHEDULER_Task *t; |
1103 | struct Task *pos; | 1025 | struct GNUNET_SCHEDULER_Task *pos; |
1104 | struct Task *prev; | 1026 | struct GNUNET_SCHEDULER_Task *prev; |
1105 | 1027 | ||
1106 | #if EXECINFO | 1028 | #if EXECINFO |
1107 | void *backtrace_array[MAX_TRACE_DEPTH]; | 1029 | void *backtrace_array[MAX_TRACE_DEPTH]; |
@@ -1109,7 +1031,7 @@ GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, | |||
1109 | 1031 | ||
1110 | GNUNET_assert (NULL != active_task); | 1032 | GNUNET_assert (NULL != active_task); |
1111 | GNUNET_assert (NULL != task); | 1033 | GNUNET_assert (NULL != task); |
1112 | t = GNUNET_new (struct Task); | 1034 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1113 | t->callback = task; | 1035 | t->callback = task; |
1114 | t->callback_cls = task_cls; | 1036 | t->callback_cls = task_cls; |
1115 | #if EXECINFO | 1037 | #if EXECINFO |
@@ -1119,7 +1041,6 @@ GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, | |||
1119 | #endif | 1041 | #endif |
1120 | t->read_fd = -1; | 1042 | t->read_fd = -1; |
1121 | t->write_fd = -1; | 1043 | t->write_fd = -1; |
1122 | t->id = ++last_id; | ||
1123 | #if PROFILE_DELAYS | 1044 | #if PROFILE_DELAYS |
1124 | t->start_time = GNUNET_TIME_absolute_get (); | 1045 | t->start_time = GNUNET_TIME_absolute_get (); |
1125 | #endif | 1046 | #endif |
@@ -1128,44 +1049,74 @@ GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, | |||
1128 | t->lifeness = current_lifeness; | 1049 | t->lifeness = current_lifeness; |
1129 | /* try tail first (optimization in case we are | 1050 | /* try tail first (optimization in case we are |
1130 | * appending to a long list of tasks with timeouts) */ | 1051 | * appending to a long list of tasks with timeouts) */ |
1131 | prev = pending_timeout_last; | 1052 | if (0 == delay.rel_value_us) |
1132 | if (prev != NULL) | ||
1133 | { | 1053 | { |
1134 | if (prev->timeout.abs_value_us > t->timeout.abs_value_us) | 1054 | GNUNET_CONTAINER_DLL_insert (pending_timeout_head, |
1135 | prev = NULL; | 1055 | pending_timeout_tail, |
1136 | else | 1056 | t); |
1137 | pos = prev->next; /* heuristic success! */ | ||
1138 | } | ||
1139 | if (prev == NULL) | ||
1140 | { | ||
1141 | /* heuristic failed, do traversal of timeout list */ | ||
1142 | pos = pending_timeout; | ||
1143 | } | 1057 | } |
1144 | while ((pos != NULL) && | 1058 | else |
1145 | ((pos->timeout.abs_value_us <= t->timeout.abs_value_us) || | ||
1146 | (0 != pos->reason))) | ||
1147 | { | 1059 | { |
1148 | prev = pos; | 1060 | /* first move from heuristic start backwards to before start time */ |
1149 | pos = pos->next; | 1061 | prev = pending_timeout_last; |
1062 | while ( (NULL != prev) && | ||
1063 | (prev->timeout.abs_value_us > t->timeout.abs_value_us) ) | ||
1064 | prev = prev->prev; | ||
1065 | /* now, move from heuristic start (or head of list) forward to insertion point */ | ||
1066 | if (NULL == prev) | ||
1067 | pos = pending_timeout_head; | ||
1068 | else | ||
1069 | pos = prev->next; | ||
1070 | while ( (NULL != pos) && | ||
1071 | ( (pos->timeout.abs_value_us <= t->timeout.abs_value_us) || | ||
1072 | (0 != pos->reason) ) ) | ||
1073 | { | ||
1074 | prev = pos; | ||
1075 | pos = pos->next; | ||
1076 | } | ||
1077 | GNUNET_CONTAINER_DLL_insert_after (pending_timeout_head, | ||
1078 | pending_timeout_tail, | ||
1079 | prev, | ||
1080 | t); | ||
1081 | /* finally, update heuristic insertion point to last insertion... */ | ||
1082 | pending_timeout_last = t; | ||
1150 | } | 1083 | } |
1151 | if (prev == NULL) | ||
1152 | pending_timeout = t; | ||
1153 | else | ||
1154 | prev->next = t; | ||
1155 | t->next = pos; | ||
1156 | /* hyper-optimization... */ | ||
1157 | pending_timeout_last = t; | ||
1158 | 1084 | ||
1159 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding task: %llu / %p\n", t->id, | 1085 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1160 | t->callback_cls); | 1086 | "Adding task: %p\n", |
1087 | t); | ||
1161 | #if EXECINFO | 1088 | #if EXECINFO |
1162 | int i; | 1089 | unsigned int i; |
1163 | 1090 | ||
1164 | for (i = 0; i < t->num_backtrace_strings; i++) | 1091 | for (i = 0; i < t->num_backtrace_strings; i++) |
1165 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Task %llu trace %d: %s\n", t->id, i, | 1092 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1093 | "Task %p trace %d: %s\n", | ||
1094 | t, | ||
1095 | i, | ||
1166 | t->backtrace_strings[i]); | 1096 | t->backtrace_strings[i]); |
1167 | #endif | 1097 | #endif |
1168 | return t->id; | 1098 | return t; |
1099 | } | ||
1100 | |||
1101 | |||
1102 | /** | ||
1103 | * Schedule a new task to be run with a specified priority. | ||
1104 | * | ||
1105 | * @param prio how important is the new task? | ||
1106 | * @param task main function of the task | ||
1107 | * @param task_cls closure of @a task | ||
1108 | * @return unique task identifier for the job | ||
1109 | * only valid until @a task is started! | ||
1110 | */ | ||
1111 | struct GNUNET_SCHEDULER_Task * | ||
1112 | GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio, | ||
1113 | GNUNET_SCHEDULER_TaskCallback task, | ||
1114 | void *task_cls) | ||
1115 | { | ||
1116 | return GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_UNIT_ZERO, | ||
1117 | prio, | ||
1118 | task, | ||
1119 | task_cls); | ||
1169 | } | 1120 | } |
1170 | 1121 | ||
1171 | 1122 | ||
@@ -1181,9 +1132,9 @@ GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, | |||
1181 | * @return unique task identifier for the job | 1132 | * @return unique task identifier for the job |
1182 | * only valid until "task" is started! | 1133 | * only valid until "task" is started! |
1183 | */ | 1134 | */ |
1184 | GNUNET_SCHEDULER_TaskIdentifier | 1135 | struct GNUNET_SCHEDULER_Task * |
1185 | GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, | 1136 | GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, |
1186 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1137 | GNUNET_SCHEDULER_TaskCallback task, void *task_cls) |
1187 | { | 1138 | { |
1188 | return GNUNET_SCHEDULER_add_delayed_with_priority (delay, | 1139 | return GNUNET_SCHEDULER_add_delayed_with_priority (delay, |
1189 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 1140 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
@@ -1206,8 +1157,8 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, | |||
1206 | * @return unique task identifier for the job | 1157 | * @return unique task identifier for the job |
1207 | * only valid until "task" is started! | 1158 | * only valid until "task" is started! |
1208 | */ | 1159 | */ |
1209 | GNUNET_SCHEDULER_TaskIdentifier | 1160 | struct GNUNET_SCHEDULER_Task * |
1210 | GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, void *task_cls) | 1161 | GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, void *task_cls) |
1211 | { | 1162 | { |
1212 | return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, task, task_cls); | 1163 | return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, task, task_cls); |
1213 | } | 1164 | } |
@@ -1227,19 +1178,15 @@ GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, void *task_cls) | |||
1227 | * @return unique task identifier for the job | 1178 | * @return unique task identifier for the job |
1228 | * only valid until @a task is started! | 1179 | * only valid until @a task is started! |
1229 | */ | 1180 | */ |
1230 | GNUNET_SCHEDULER_TaskIdentifier | 1181 | struct GNUNET_SCHEDULER_Task * |
1231 | GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, | 1182 | GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, |
1232 | GNUNET_SCHEDULER_Task task, | 1183 | GNUNET_SCHEDULER_TaskCallback task, |
1233 | void *task_cls) | 1184 | void *task_cls) |
1234 | { | 1185 | { |
1235 | GNUNET_SCHEDULER_TaskIdentifier ret; | 1186 | struct GNUNET_SCHEDULER_Task *ret; |
1236 | 1187 | ||
1237 | ret = | 1188 | ret = GNUNET_SCHEDULER_add_now (task, task_cls); |
1238 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 1189 | ret->lifeness = lifeness; |
1239 | GNUNET_TIME_UNIT_ZERO, NULL, NULL, task, | ||
1240 | task_cls); | ||
1241 | GNUNET_assert (pending->id == ret); | ||
1242 | pending->lifeness = lifeness; | ||
1243 | return ret; | 1190 | return ret; |
1244 | } | 1191 | } |
1245 | 1192 | ||
@@ -1269,16 +1216,18 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, | |||
1269 | * @param task main function of the task | 1216 | * @param task main function of the task |
1270 | * @param task_cls closure of @a task | 1217 | * @param task_cls closure of @a task |
1271 | * @return unique task identifier for the job | 1218 | * @return unique task identifier for the job |
1272 | * only valid until "task" is started! | 1219 | * only valid until @a task is started! |
1273 | */ | 1220 | */ |
1274 | #ifndef MINGW | 1221 | #ifndef MINGW |
1275 | static GNUNET_SCHEDULER_TaskIdentifier | 1222 | static struct GNUNET_SCHEDULER_Task * |
1276 | add_without_sets (struct GNUNET_TIME_Relative delay, | 1223 | add_without_sets (struct GNUNET_TIME_Relative delay, |
1277 | enum GNUNET_SCHEDULER_Priority priority, | 1224 | enum GNUNET_SCHEDULER_Priority priority, |
1278 | int rfd, int wfd, | 1225 | int rfd, |
1279 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1226 | int wfd, |
1227 | GNUNET_SCHEDULER_TaskCallback task, | ||
1228 | void *task_cls) | ||
1280 | { | 1229 | { |
1281 | struct Task *t; | 1230 | struct GNUNET_SCHEDULER_Task *t; |
1282 | 1231 | ||
1283 | #if EXECINFO | 1232 | #if EXECINFO |
1284 | void *backtrace_array[MAX_TRACE_DEPTH]; | 1233 | void *backtrace_array[MAX_TRACE_DEPTH]; |
@@ -1286,7 +1235,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1286 | 1235 | ||
1287 | GNUNET_assert (NULL != active_task); | 1236 | GNUNET_assert (NULL != active_task); |
1288 | GNUNET_assert (NULL != task); | 1237 | GNUNET_assert (NULL != task); |
1289 | t = GNUNET_new (struct Task); | 1238 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1290 | t->callback = task; | 1239 | t->callback = task; |
1291 | t->callback_cls = task_cls; | 1240 | t->callback_cls = task_cls; |
1292 | #if EXECINFO | 1241 | #if EXECINFO |
@@ -1339,36 +1288,35 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1339 | t->read_fd = rfd; | 1288 | t->read_fd = rfd; |
1340 | GNUNET_assert (wfd >= -1); | 1289 | GNUNET_assert (wfd >= -1); |
1341 | t->write_fd = wfd; | 1290 | t->write_fd = wfd; |
1342 | t->id = ++last_id; | ||
1343 | #if PROFILE_DELAYS | 1291 | #if PROFILE_DELAYS |
1344 | t->start_time = GNUNET_TIME_absolute_get (); | 1292 | t->start_time = GNUNET_TIME_absolute_get (); |
1345 | #endif | 1293 | #endif |
1346 | t->timeout = GNUNET_TIME_relative_to_absolute (delay); | 1294 | t->timeout = GNUNET_TIME_relative_to_absolute (delay); |
1347 | t->priority = check_priority ((priority == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : priority); | 1295 | t->priority = check_priority ((priority == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : priority); |
1348 | t->lifeness = current_lifeness; | 1296 | t->lifeness = current_lifeness; |
1349 | t->next = pending; | 1297 | GNUNET_CONTAINER_DLL_insert (pending_head, |
1350 | pending = t; | 1298 | pending_tail, |
1351 | max_priority_added = GNUNET_MAX (max_priority_added, t->priority); | 1299 | t); |
1300 | max_priority_added = GNUNET_MAX (max_priority_added, | ||
1301 | t->priority); | ||
1352 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1302 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1353 | "Adding task: %llu / %p\n", | 1303 | "Adding task %p\n", |
1354 | t->id, | 1304 | t); |
1355 | t->callback_cls); | ||
1356 | #if EXECINFO | 1305 | #if EXECINFO |
1357 | int i; | 1306 | unsigned int i; |
1358 | 1307 | ||
1359 | for (i = 0; i < t->num_backtrace_strings; i++) | 1308 | for (i = 0; i < t->num_backtrace_strings; i++) |
1360 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1309 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1361 | "Task %llu trace %d: %s\n", | 1310 | "Task %p trace %d: %s\n", |
1362 | t->id, | 1311 | t, |
1363 | i, | 1312 | i, |
1364 | t->backtrace_strings[i]); | 1313 | t->backtrace_strings[i]); |
1365 | #endif | 1314 | #endif |
1366 | return t->id; | 1315 | return t; |
1367 | } | 1316 | } |
1368 | #endif | 1317 | #endif |
1369 | 1318 | ||
1370 | 1319 | ||
1371 | |||
1372 | /** | 1320 | /** |
1373 | * Schedule a new task to be run with a specified delay or when the | 1321 | * Schedule a new task to be run with a specified delay or when the |
1374 | * specified file descriptor is ready for reading. The delay can be | 1322 | * specified file descriptor is ready for reading. The delay can be |
@@ -1384,10 +1332,11 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1384 | * @return unique task identifier for the job | 1332 | * @return unique task identifier for the job |
1385 | * only valid until @a task is started! | 1333 | * only valid until @a task is started! |
1386 | */ | 1334 | */ |
1387 | GNUNET_SCHEDULER_TaskIdentifier | 1335 | struct GNUNET_SCHEDULER_Task * |
1388 | GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, | 1336 | GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, |
1389 | struct GNUNET_NETWORK_Handle *rfd, | 1337 | struct GNUNET_NETWORK_Handle *rfd, |
1390 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1338 | GNUNET_SCHEDULER_TaskCallback task, |
1339 | void *task_cls) | ||
1391 | { | 1340 | { |
1392 | return GNUNET_SCHEDULER_add_read_net_with_priority (delay, | 1341 | return GNUNET_SCHEDULER_add_read_net_with_priority (delay, |
1393 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 1342 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
@@ -1412,16 +1361,18 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, | |||
1412 | * @return unique task identifier for the job | 1361 | * @return unique task identifier for the job |
1413 | * only valid until @a task is started! | 1362 | * only valid until @a task is started! |
1414 | */ | 1363 | */ |
1415 | GNUNET_SCHEDULER_TaskIdentifier | 1364 | struct GNUNET_SCHEDULER_Task * |
1416 | GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, | 1365 | GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, |
1417 | enum GNUNET_SCHEDULER_Priority priority, | 1366 | enum GNUNET_SCHEDULER_Priority priority, |
1418 | struct GNUNET_NETWORK_Handle *rfd, | 1367 | struct GNUNET_NETWORK_Handle *rfd, |
1419 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1368 | GNUNET_SCHEDULER_TaskCallback task, |
1369 | void *task_cls) | ||
1420 | { | 1370 | { |
1421 | return GNUNET_SCHEDULER_add_net_with_priority ( | 1371 | return GNUNET_SCHEDULER_add_net_with_priority (delay, priority, |
1422 | delay, priority, | 1372 | rfd, |
1423 | rfd, GNUNET_YES, GNUNET_NO, | 1373 | GNUNET_YES, |
1424 | task, task_cls); | 1374 | GNUNET_NO, |
1375 | task, task_cls); | ||
1425 | } | 1376 | } |
1426 | 1377 | ||
1427 | 1378 | ||
@@ -1441,15 +1392,17 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1441 | * @return unique task identifier for the job | 1392 | * @return unique task identifier for the job |
1442 | * only valid until @a task is started! | 1393 | * only valid until @a task is started! |
1443 | */ | 1394 | */ |
1444 | GNUNET_SCHEDULER_TaskIdentifier | 1395 | struct GNUNET_SCHEDULER_Task * |
1445 | GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, | 1396 | GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, |
1446 | struct GNUNET_NETWORK_Handle *wfd, | 1397 | struct GNUNET_NETWORK_Handle *wfd, |
1447 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1398 | GNUNET_SCHEDULER_TaskCallback task, |
1399 | void *task_cls) | ||
1448 | { | 1400 | { |
1449 | return GNUNET_SCHEDULER_add_net_with_priority ( | 1401 | return GNUNET_SCHEDULER_add_net_with_priority (delay, |
1450 | delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 1402 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
1451 | wfd, GNUNET_NO, GNUNET_YES, | 1403 | wfd, |
1452 | task, task_cls); | 1404 | GNUNET_NO, GNUNET_YES, |
1405 | task, task_cls); | ||
1453 | } | 1406 | } |
1454 | 1407 | ||
1455 | /** | 1408 | /** |
@@ -1460,7 +1413,7 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, | |||
1460 | * socket operation is ready. | 1413 | * socket operation is ready. |
1461 | * | 1414 | * |
1462 | * @param delay when should this operation time out? Use | 1415 | * @param delay when should this operation time out? Use |
1463 | * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | 1416 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" |
1464 | * @param priority priority of the task | 1417 | * @param priority priority of the task |
1465 | * @param fd file-descriptor | 1418 | * @param fd file-descriptor |
1466 | * @param on_read whether to poll the file-descriptor for readability | 1419 | * @param on_read whether to poll the file-descriptor for readability |
@@ -1470,18 +1423,20 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, | |||
1470 | * @return unique task identifier for the job | 1423 | * @return unique task identifier for the job |
1471 | * only valid until "task" is started! | 1424 | * only valid until "task" is started! |
1472 | */ | 1425 | */ |
1473 | GNUNET_SCHEDULER_TaskIdentifier | 1426 | struct GNUNET_SCHEDULER_Task * |
1474 | GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, | 1427 | GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, |
1475 | enum GNUNET_SCHEDULER_Priority priority, | 1428 | enum GNUNET_SCHEDULER_Priority priority, |
1476 | struct GNUNET_NETWORK_Handle *fd, | 1429 | struct GNUNET_NETWORK_Handle *fd, |
1477 | int on_read, int on_write, | 1430 | int on_read, |
1478 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1431 | int on_write, |
1432 | GNUNET_SCHEDULER_TaskCallback task, | ||
1433 | void *task_cls) | ||
1479 | { | 1434 | { |
1480 | #if MINGW | 1435 | #if MINGW |
1481 | struct GNUNET_NETWORK_FDSet *s; | 1436 | struct GNUNET_NETWORK_FDSet *s; |
1482 | GNUNET_SCHEDULER_TaskIdentifier ret; | 1437 | struct GNUNET_SCHEDULER_Task * ret; |
1483 | 1438 | ||
1484 | GNUNET_assert (fd != NULL); | 1439 | GNUNET_assert (NULL != fd); |
1485 | s = GNUNET_NETWORK_fdset_create (); | 1440 | s = GNUNET_NETWORK_fdset_create (); |
1486 | GNUNET_NETWORK_fdset_set (s, fd); | 1441 | GNUNET_NETWORK_fdset_set (s, fd); |
1487 | ret = GNUNET_SCHEDULER_add_select ( | 1442 | ret = GNUNET_SCHEDULER_add_select ( |
@@ -1493,11 +1448,10 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1493 | return ret; | 1448 | return ret; |
1494 | #else | 1449 | #else |
1495 | GNUNET_assert (GNUNET_NETWORK_get_fd (fd) >= 0); | 1450 | GNUNET_assert (GNUNET_NETWORK_get_fd (fd) >= 0); |
1496 | return add_without_sets ( | 1451 | return add_without_sets (delay, priority, |
1497 | delay, priority, | 1452 | on_read ? GNUNET_NETWORK_get_fd (fd) : -1, |
1498 | on_read ? GNUNET_NETWORK_get_fd (fd) : -1, | 1453 | on_write ? GNUNET_NETWORK_get_fd (fd) : -1, |
1499 | on_write ? GNUNET_NETWORK_get_fd (fd) : -1, | 1454 | task, task_cls); |
1500 | task, task_cls); | ||
1501 | #endif | 1455 | #endif |
1502 | } | 1456 | } |
1503 | 1457 | ||
@@ -1517,10 +1471,10 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1517 | * @return unique task identifier for the job | 1471 | * @return unique task identifier for the job |
1518 | * only valid until @a task is started! | 1472 | * only valid until @a task is started! |
1519 | */ | 1473 | */ |
1520 | GNUNET_SCHEDULER_TaskIdentifier | 1474 | struct GNUNET_SCHEDULER_Task * |
1521 | GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, | 1475 | GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, |
1522 | const struct GNUNET_DISK_FileHandle *rfd, | 1476 | const struct GNUNET_DISK_FileHandle *rfd, |
1523 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1477 | GNUNET_SCHEDULER_TaskCallback task, void *task_cls) |
1524 | { | 1478 | { |
1525 | return GNUNET_SCHEDULER_add_file_with_priority ( | 1479 | return GNUNET_SCHEDULER_add_file_with_priority ( |
1526 | delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 1480 | delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
@@ -1544,10 +1498,10 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, | |||
1544 | * @return unique task identifier for the job | 1498 | * @return unique task identifier for the job |
1545 | * only valid until @a task is started! | 1499 | * only valid until @a task is started! |
1546 | */ | 1500 | */ |
1547 | GNUNET_SCHEDULER_TaskIdentifier | 1501 | struct GNUNET_SCHEDULER_Task * |
1548 | GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, | 1502 | GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, |
1549 | const struct GNUNET_DISK_FileHandle *wfd, | 1503 | const struct GNUNET_DISK_FileHandle *wfd, |
1550 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1504 | GNUNET_SCHEDULER_TaskCallback task, void *task_cls) |
1551 | { | 1505 | { |
1552 | return GNUNET_SCHEDULER_add_file_with_priority ( | 1506 | return GNUNET_SCHEDULER_add_file_with_priority ( |
1553 | delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 1507 | delay, GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
@@ -1574,18 +1528,18 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, | |||
1574 | * @return unique task identifier for the job | 1528 | * @return unique task identifier for the job |
1575 | * only valid until @a task is started! | 1529 | * only valid until @a task is started! |
1576 | */ | 1530 | */ |
1577 | GNUNET_SCHEDULER_TaskIdentifier | 1531 | struct GNUNET_SCHEDULER_Task * |
1578 | GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, | 1532 | GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, |
1579 | enum GNUNET_SCHEDULER_Priority priority, | 1533 | enum GNUNET_SCHEDULER_Priority priority, |
1580 | const struct GNUNET_DISK_FileHandle *fd, | 1534 | const struct GNUNET_DISK_FileHandle *fd, |
1581 | int on_read, int on_write, | 1535 | int on_read, int on_write, |
1582 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1536 | GNUNET_SCHEDULER_TaskCallback task, void *task_cls) |
1583 | { | 1537 | { |
1584 | #if MINGW | 1538 | #if MINGW |
1585 | struct GNUNET_NETWORK_FDSet *s; | 1539 | struct GNUNET_NETWORK_FDSet *s; |
1586 | GNUNET_SCHEDULER_TaskIdentifier ret; | 1540 | struct GNUNET_SCHEDULER_Task * ret; |
1587 | 1541 | ||
1588 | GNUNET_assert (fd != NULL); | 1542 | GNUNET_assert (NULL != fd); |
1589 | s = GNUNET_NETWORK_fdset_create (); | 1543 | s = GNUNET_NETWORK_fdset_create (); |
1590 | GNUNET_NETWORK_fdset_handle_set (s, fd); | 1544 | GNUNET_NETWORK_fdset_handle_set (s, fd); |
1591 | ret = GNUNET_SCHEDULER_add_select ( | 1545 | ret = GNUNET_SCHEDULER_add_select ( |
@@ -1636,21 +1590,28 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, | |||
1636 | * @return unique task identifier for the job | 1590 | * @return unique task identifier for the job |
1637 | * only valid until @a task is started! | 1591 | * only valid until @a task is started! |
1638 | */ | 1592 | */ |
1639 | GNUNET_SCHEDULER_TaskIdentifier | 1593 | struct GNUNET_SCHEDULER_Task * |
1640 | GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | 1594 | GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, |
1641 | struct GNUNET_TIME_Relative delay, | 1595 | struct GNUNET_TIME_Relative delay, |
1642 | const struct GNUNET_NETWORK_FDSet *rs, | 1596 | const struct GNUNET_NETWORK_FDSet *rs, |
1643 | const struct GNUNET_NETWORK_FDSet *ws, | 1597 | const struct GNUNET_NETWORK_FDSet *ws, |
1644 | GNUNET_SCHEDULER_Task task, void *task_cls) | 1598 | GNUNET_SCHEDULER_TaskCallback task, |
1599 | void *task_cls) | ||
1645 | { | 1600 | { |
1646 | struct Task *t; | 1601 | struct GNUNET_SCHEDULER_Task *t; |
1647 | #if EXECINFO | 1602 | #if EXECINFO |
1648 | void *backtrace_array[MAX_TRACE_DEPTH]; | 1603 | void *backtrace_array[MAX_TRACE_DEPTH]; |
1649 | #endif | 1604 | #endif |
1650 | 1605 | ||
1606 | if ( (NULL == rs) && | ||
1607 | (NULL == ws) ) | ||
1608 | return GNUNET_SCHEDULER_add_delayed_with_priority (delay, | ||
1609 | prio, | ||
1610 | task, | ||
1611 | task_cls); | ||
1651 | GNUNET_assert (NULL != active_task); | 1612 | GNUNET_assert (NULL != active_task); |
1652 | GNUNET_assert (NULL != task); | 1613 | GNUNET_assert (NULL != task); |
1653 | t = GNUNET_new (struct Task); | 1614 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1654 | t->callback = task; | 1615 | t->callback = task; |
1655 | t->callback_cls = task_cls; | 1616 | t->callback_cls = task_cls; |
1656 | #if EXECINFO | 1617 | #if EXECINFO |
@@ -1670,7 +1631,6 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | |||
1670 | t->write_set = GNUNET_NETWORK_fdset_create (); | 1631 | t->write_set = GNUNET_NETWORK_fdset_create (); |
1671 | GNUNET_NETWORK_fdset_copy (t->write_set, ws); | 1632 | GNUNET_NETWORK_fdset_copy (t->write_set, ws); |
1672 | } | 1633 | } |
1673 | t->id = ++last_id; | ||
1674 | #if PROFILE_DELAYS | 1634 | #if PROFILE_DELAYS |
1675 | t->start_time = GNUNET_TIME_absolute_get (); | 1635 | t->start_time = GNUNET_TIME_absolute_get (); |
1676 | #endif | 1636 | #endif |
@@ -1680,23 +1640,24 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | |||
1680 | GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : | 1640 | GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : |
1681 | prio); | 1641 | prio); |
1682 | t->lifeness = current_lifeness; | 1642 | t->lifeness = current_lifeness; |
1683 | t->next = pending; | 1643 | GNUNET_CONTAINER_DLL_insert (pending_head, |
1684 | pending = t; | 1644 | pending_tail, |
1645 | t); | ||
1685 | max_priority_added = GNUNET_MAX (max_priority_added, t->priority); | 1646 | max_priority_added = GNUNET_MAX (max_priority_added, t->priority); |
1686 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1647 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1687 | "Adding task: %llu / %p\n", | 1648 | "Adding task %p\n", |
1688 | t->id, | 1649 | t); |
1689 | t->callback_cls); | ||
1690 | #if EXECINFO | 1650 | #if EXECINFO |
1691 | int i; | 1651 | int i; |
1692 | 1652 | ||
1693 | for (i = 0; i < t->num_backtrace_strings; i++) | 1653 | for (i = 0; i < t->num_backtrace_strings; i++) |
1694 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1654 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1695 | "Task %llu trace %d: %s\n", | 1655 | "Task p trace %d: %s\n", |
1696 | t->id, i, | 1656 | t, |
1657 | i, | ||
1697 | t->backtrace_strings[i]); | 1658 | t->backtrace_strings[i]); |
1698 | #endif | 1659 | #endif |
1699 | return t->id; | 1660 | return t; |
1700 | } | 1661 | } |
1701 | 1662 | ||
1702 | /* end of scheduler.c */ | 1663 | /* end of scheduler.c */ |