diff options
Diffstat (limited to 'src/util/scheduler.c')
-rw-r--r-- | src/util/scheduler.c | 337 |
1 files changed, 168 insertions, 169 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index dcf5aeeaa..81f968dee 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet | 2 | This file is part of GNUnet |
3 | Copyright (C) 2009-2013 GNUnet e.V. | 3 | Copyright (C) 2009-2016 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -152,6 +152,11 @@ struct GNUNET_SCHEDULER_Task | |||
152 | int lifeness; | 152 | int lifeness; |
153 | 153 | ||
154 | /** | 154 | /** |
155 | * Is this task run on shutdown? | ||
156 | */ | ||
157 | int on_shutdown; | ||
158 | |||
159 | /** | ||
155 | * Is this task in the ready list? | 160 | * Is this task in the ready list? |
156 | */ | 161 | */ |
157 | int in_ready_list; | 162 | int in_ready_list; |
@@ -184,6 +189,16 @@ static struct GNUNET_SCHEDULER_Task *pending_head; | |||
184 | static struct GNUNET_SCHEDULER_Task *pending_tail; | 189 | static struct GNUNET_SCHEDULER_Task *pending_tail; |
185 | 190 | ||
186 | /** | 191 | /** |
192 | * Head of list of tasks waiting for shutdown. | ||
193 | */ | ||
194 | static struct GNUNET_SCHEDULER_Task *shutdown_head; | ||
195 | |||
196 | /** | ||
197 | * Tail of list of tasks waiting for shutdown. | ||
198 | */ | ||
199 | static struct GNUNET_SCHEDULER_Task *shutdown_tail; | ||
200 | |||
201 | /** | ||
187 | * List of tasks waiting ONLY for a timeout event. | 202 | * List of tasks waiting ONLY for a timeout event. |
188 | * Sorted by timeout (earliest first). Used so that | 203 | * Sorted by timeout (earliest first). Used so that |
189 | * we do not traverse the list of these tasks when | 204 | * we do not traverse the list of these tasks when |
@@ -421,8 +436,6 @@ queue_ready_task (struct GNUNET_SCHEDULER_Task *task) | |||
421 | { | 436 | { |
422 | enum GNUNET_SCHEDULER_Priority p = check_priority (task->priority); | 437 | enum GNUNET_SCHEDULER_Priority p = check_priority (task->priority); |
423 | 438 | ||
424 | if (0 != (task->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
425 | p = task->priority = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN; | ||
426 | GNUNET_CONTAINER_DLL_insert (ready_head[p], | 439 | GNUNET_CONTAINER_DLL_insert (ready_head[p], |
427 | ready_tail[p], | 440 | ready_tail[p], |
428 | task); | 441 | task); |
@@ -477,29 +490,24 @@ check_ready (const struct GNUNET_NETWORK_FDSet *rs, | |||
477 | 490 | ||
478 | 491 | ||
479 | /** | 492 | /** |
480 | * Request the shutdown of a scheduler. Marks all currently | 493 | * Request the shutdown of a scheduler. Marks all tasks |
481 | * pending tasks as ready because of shutdown. This will | 494 | * awaiting shutdown as ready. Note that tasks |
482 | * cause all tasks to run (as soon as possible, respecting | 495 | * scheduled with #GNUNET_SCHEDULER_add_shutdown() AFTER this call |
483 | * priorities and prerequisite tasks). Note that tasks | 496 | * will be delayed until the next shutdown signal. |
484 | * scheduled AFTER this call may still be delayed arbitrarily. | ||
485 | * | ||
486 | * Note that we don't move the tasks into the ready queue yet; | ||
487 | * check_ready() will do that later, possibly adding additional | ||
488 | * readiness-factors | ||
489 | */ | 497 | */ |
490 | void | 498 | void |
491 | GNUNET_SCHEDULER_shutdown () | 499 | GNUNET_SCHEDULER_shutdown () |
492 | { | 500 | { |
493 | struct GNUNET_SCHEDULER_Task *pos; | 501 | struct GNUNET_SCHEDULER_Task *pos; |
494 | int i; | ||
495 | 502 | ||
496 | for (pos = pending_timeout_head; NULL != pos; pos = pos->next) | 503 | while (NULL != (pos = shutdown_head)) |
497 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; | 504 | { |
498 | for (pos = pending_head; NULL != pos; pos = pos->next) | 505 | GNUNET_CONTAINER_DLL_remove (shutdown_head, |
506 | shutdown_tail, | ||
507 | pos); | ||
499 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; | 508 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; |
500 | for (i = 0; i < GNUNET_SCHEDULER_PRIORITY_COUNT; i++) | 509 | queue_ready_task (pos); |
501 | for (pos = ready_head[i]; NULL != pos; pos = pos->next) | 510 | } |
502 | pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN; | ||
503 | } | 511 | } |
504 | 512 | ||
505 | 513 | ||
@@ -523,6 +531,27 @@ destroy_task (struct GNUNET_SCHEDULER_Task *t) | |||
523 | 531 | ||
524 | 532 | ||
525 | /** | 533 | /** |
534 | * Output stack trace of task @a t. | ||
535 | * | ||
536 | * @param t task to dump stack trace of | ||
537 | */ | ||
538 | static void | ||
539 | dump_backtrace (struct GNUNET_SCHEDULER_Task *t) | ||
540 | { | ||
541 | #if EXECINFO | ||
542 | unsigned int i; | ||
543 | |||
544 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
545 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
546 | "Task %p trace %u: %s\n", | ||
547 | t, | ||
548 | i, | ||
549 | t->backtrace_strings[i]); | ||
550 | #endif | ||
551 | } | ||
552 | |||
553 | |||
554 | /** | ||
526 | * Run at least one task in the highest-priority queue that is not | 555 | * Run at least one task in the highest-priority queue that is not |
527 | * empty. Keep running tasks until we are either no longer running | 556 | * empty. Keep running tasks until we are either no longer running |
528 | * "URGENT" tasks or until we have at least one "pending" task (which | 557 | * "URGENT" tasks or until we have at least one "pending" task (which |
@@ -589,16 +618,7 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, | |||
589 | "Running task: %p\n", | 618 | "Running task: %p\n", |
590 | pos); | 619 | pos); |
591 | pos->callback (pos->callback_cls); | 620 | pos->callback (pos->callback_cls); |
592 | #if EXECINFO | 621 | dump_backtrace (pos); |
593 | unsigned int i; | ||
594 | |||
595 | for (i = 0; i < pos->num_backtrace_strings; i++) | ||
596 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
597 | "Task %p trace %u: %s\n", | ||
598 | pos, | ||
599 | i, | ||
600 | pos->backtrace_strings[i]); | ||
601 | #endif | ||
602 | active_task = NULL; | 622 | active_task = NULL; |
603 | destroy_task (pos); | 623 | destroy_task (pos); |
604 | tasks_run++; | 624 | tasks_run++; |
@@ -684,10 +704,13 @@ check_lifeness () | |||
684 | for (t = pending_head; NULL != t; t = t->next) | 704 | for (t = pending_head; NULL != t; t = t->next) |
685 | if (t->lifeness == GNUNET_YES) | 705 | if (t->lifeness == GNUNET_YES) |
686 | return GNUNET_OK; | 706 | return GNUNET_OK; |
707 | for (t = shutdown_head; NULL != t; t = t->next) | ||
708 | if (t->lifeness == GNUNET_YES) | ||
709 | return GNUNET_OK; | ||
687 | for (t = pending_timeout_head; NULL != t; t = t->next) | 710 | for (t = pending_timeout_head; NULL != t; t = t->next) |
688 | if (t->lifeness == GNUNET_YES) | 711 | if (t->lifeness == GNUNET_YES) |
689 | return GNUNET_OK; | 712 | return GNUNET_OK; |
690 | if ((NULL != pending_head) || (NULL != pending_timeout_head)) | 713 | if (NULL != shutdown_head) |
691 | { | 714 | { |
692 | GNUNET_SCHEDULER_shutdown (); | 715 | GNUNET_SCHEDULER_shutdown (); |
693 | return GNUNET_OK; | 716 | return GNUNET_OK; |
@@ -749,15 +772,21 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, | |||
749 | my_pid = getpid (); | 772 | my_pid = getpid (); |
750 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 773 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
751 | "Registering signal handlers\n"); | 774 | "Registering signal handlers\n"); |
752 | shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); | 775 | shc_int = GNUNET_SIGNAL_handler_install (SIGINT, |
753 | shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown); | 776 | &sighandler_shutdown); |
777 | shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, | ||
778 | &sighandler_shutdown); | ||
754 | #if (SIGTERM != GNUNET_TERM_SIG) | 779 | #if (SIGTERM != GNUNET_TERM_SIG) |
755 | shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, &sighandler_shutdown); | 780 | shc_gterm = GNUNET_SIGNAL_handler_install (GNUNET_TERM_SIG, |
781 | &sighandler_shutdown); | ||
756 | #endif | 782 | #endif |
757 | #ifndef MINGW | 783 | #ifndef MINGW |
758 | shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, &sighandler_pipe); | 784 | shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE, |
759 | shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, &sighandler_shutdown); | 785 | &sighandler_pipe); |
760 | shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown); | 786 | shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, |
787 | &sighandler_shutdown); | ||
788 | shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, | ||
789 | &sighandler_shutdown); | ||
761 | #endif | 790 | #endif |
762 | current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; | 791 | current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; |
763 | current_lifeness = GNUNET_YES; | 792 | current_lifeness = GNUNET_YES; |
@@ -826,14 +855,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, | |||
826 | LOG (GNUNET_ERROR_TYPE_ERROR, | 855 | LOG (GNUNET_ERROR_TYPE_ERROR, |
827 | "Got invalid file descriptor %d!\n", | 856 | "Got invalid file descriptor %d!\n", |
828 | t->read_fd); | 857 | t->read_fd); |
829 | #if EXECINFO | 858 | dump_backtrace (t); |
830 | unsigned int i; | ||
831 | |||
832 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
833 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
834 | "Trace: %s\n", | ||
835 | t->backtrace_strings[i]); | ||
836 | #endif | ||
837 | } | 859 | } |
838 | } | 860 | } |
839 | if (-1 != t->write_fd) | 861 | if (-1 != t->write_fd) |
@@ -844,14 +866,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, | |||
844 | LOG (GNUNET_ERROR_TYPE_ERROR, | 866 | LOG (GNUNET_ERROR_TYPE_ERROR, |
845 | "Got invalid file descriptor %d!\n", | 867 | "Got invalid file descriptor %d!\n", |
846 | t->write_fd); | 868 | t->write_fd); |
847 | #if EXECINFO | 869 | dump_backtrace (t); |
848 | unsigned int i; | ||
849 | |||
850 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
851 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
852 | "Trace: %s\n", | ||
853 | t->backtrace_strings[i]); | ||
854 | #endif | ||
855 | } | 870 | } |
856 | } | 871 | } |
857 | } | 872 | } |
@@ -959,7 +974,8 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) | |||
959 | enum GNUNET_SCHEDULER_Priority p; | 974 | enum GNUNET_SCHEDULER_Priority p; |
960 | void *ret; | 975 | void *ret; |
961 | 976 | ||
962 | GNUNET_assert (NULL != active_task); | 977 | GNUNET_assert ( (NULL != active_task) || |
978 | (GNUNET_NO == task->lifeness) ); | ||
963 | if (! task->in_ready_list) | 979 | if (! task->in_ready_list) |
964 | { | 980 | { |
965 | if ( (-1 == task->read_fd) && | 981 | if ( (-1 == task->read_fd) && |
@@ -967,9 +983,14 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) | |||
967 | (NULL == task->read_set) && | 983 | (NULL == task->read_set) && |
968 | (NULL == task->write_set) ) | 984 | (NULL == task->write_set) ) |
969 | { | 985 | { |
970 | GNUNET_CONTAINER_DLL_remove (pending_timeout_head, | 986 | if (GNUNET_YES == task->on_shutdown) |
971 | pending_timeout_tail, | 987 | GNUNET_CONTAINER_DLL_remove (shutdown_head, |
972 | task); | 988 | shutdown_tail, |
989 | task); | ||
990 | else | ||
991 | GNUNET_CONTAINER_DLL_remove (pending_timeout_head, | ||
992 | pending_timeout_tail, | ||
993 | task); | ||
973 | if (task == pending_timeout_last) | 994 | if (task == pending_timeout_last) |
974 | pending_timeout_last = NULL; | 995 | pending_timeout_last = NULL; |
975 | } | 996 | } |
@@ -998,6 +1019,27 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) | |||
998 | 1019 | ||
999 | 1020 | ||
1000 | /** | 1021 | /** |
1022 | * Initialize backtrace data for task @a t | ||
1023 | * | ||
1024 | * @param t task to initialize | ||
1025 | */ | ||
1026 | static void | ||
1027 | init_backtrace (struct GNUNET_SCHEDULER_Task *t) | ||
1028 | { | ||
1029 | #if EXECINFO | ||
1030 | void *backtrace_array[MAX_TRACE_DEPTH]; | ||
1031 | |||
1032 | t->num_backtrace_strings | ||
1033 | = backtrace (backtrace_array, MAX_TRACE_DEPTH); | ||
1034 | t->backtrace_strings = | ||
1035 | backtrace_symbols (backtrace_array, | ||
1036 | t->num_backtrace_strings); | ||
1037 | dump_backtrace (t); | ||
1038 | #endif | ||
1039 | } | ||
1040 | |||
1041 | |||
1042 | /** | ||
1001 | * Continue the current execution with the given function. This is | 1043 | * Continue the current execution with the given function. This is |
1002 | * similar to the other "add" functions except that there is no delay | 1044 | * similar to the other "add" functions except that there is no delay |
1003 | * and the reason code can be specified. | 1045 | * and the reason code can be specified. |
@@ -1015,19 +1057,10 @@ GNUNET_SCHEDULER_add_with_reason_and_priority (GNUNET_SCHEDULER_TaskCallback tas | |||
1015 | { | 1057 | { |
1016 | struct GNUNET_SCHEDULER_Task *t; | 1058 | struct GNUNET_SCHEDULER_Task *t; |
1017 | 1059 | ||
1018 | #if EXECINFO | ||
1019 | void *backtrace_array[50]; | ||
1020 | #endif | ||
1021 | |||
1022 | GNUNET_assert (NULL != task); | 1060 | GNUNET_assert (NULL != task); |
1023 | GNUNET_assert ((NULL != active_task) || | 1061 | GNUNET_assert ((NULL != active_task) || |
1024 | (GNUNET_SCHEDULER_REASON_STARTUP == reason)); | 1062 | (GNUNET_SCHEDULER_REASON_STARTUP == reason)); |
1025 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); | 1063 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1026 | #if EXECINFO | ||
1027 | t->num_backtrace_strings = backtrace (backtrace_array, 50); | ||
1028 | t->backtrace_strings = | ||
1029 | backtrace_symbols (backtrace_array, t->num_backtrace_strings); | ||
1030 | #endif | ||
1031 | t->read_fd = -1; | 1064 | t->read_fd = -1; |
1032 | t->write_fd = -1; | 1065 | t->write_fd = -1; |
1033 | t->callback = task; | 1066 | t->callback = task; |
@@ -1041,6 +1074,7 @@ GNUNET_SCHEDULER_add_with_reason_and_priority (GNUNET_SCHEDULER_TaskCallback tas | |||
1041 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1074 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1042 | "Adding continuation task %p\n", | 1075 | "Adding continuation task %p\n", |
1043 | t); | 1076 | t); |
1077 | init_backtrace (t); | ||
1044 | queue_ready_task (t); | 1078 | queue_ready_task (t); |
1045 | } | 1079 | } |
1046 | 1080 | ||
@@ -1049,8 +1083,7 @@ GNUNET_SCHEDULER_add_with_reason_and_priority (GNUNET_SCHEDULER_TaskCallback tas | |||
1049 | * Schedule a new task to be run with a specified delay. The task | 1083 | * Schedule a new task to be run with a specified delay. The task |
1050 | * will be scheduled for execution once the delay has expired. | 1084 | * will be scheduled for execution once the delay has expired. |
1051 | * | 1085 | * |
1052 | * @param delay when should this operation time out? Use | 1086 | * @param delay when should this operation time out? |
1053 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1054 | * @param priority priority to use for the task | 1087 | * @param priority priority to use for the task |
1055 | * @param task main function of the task | 1088 | * @param task main function of the task |
1056 | * @param task_cls closure of @a task | 1089 | * @param task_cls closure of @a task |
@@ -1067,20 +1100,11 @@ GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, | |||
1067 | struct GNUNET_SCHEDULER_Task *pos; | 1100 | struct GNUNET_SCHEDULER_Task *pos; |
1068 | struct GNUNET_SCHEDULER_Task *prev; | 1101 | struct GNUNET_SCHEDULER_Task *prev; |
1069 | 1102 | ||
1070 | #if EXECINFO | ||
1071 | void *backtrace_array[MAX_TRACE_DEPTH]; | ||
1072 | #endif | ||
1073 | |||
1074 | GNUNET_assert (NULL != active_task); | 1103 | GNUNET_assert (NULL != active_task); |
1075 | GNUNET_assert (NULL != task); | 1104 | GNUNET_assert (NULL != task); |
1076 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); | 1105 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1077 | t->callback = task; | 1106 | t->callback = task; |
1078 | t->callback_cls = task_cls; | 1107 | t->callback_cls = task_cls; |
1079 | #if EXECINFO | ||
1080 | t->num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH); | ||
1081 | t->backtrace_strings = | ||
1082 | backtrace_symbols (backtrace_array, t->num_backtrace_strings); | ||
1083 | #endif | ||
1084 | t->read_fd = -1; | 1108 | t->read_fd = -1; |
1085 | t->write_fd = -1; | 1109 | t->write_fd = -1; |
1086 | #if PROFILE_DELAYS | 1110 | #if PROFILE_DELAYS |
@@ -1127,16 +1151,7 @@ GNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, | |||
1127 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1151 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1128 | "Adding task: %p\n", | 1152 | "Adding task: %p\n", |
1129 | t); | 1153 | t); |
1130 | #if EXECINFO | 1154 | init_backtrace (t); |
1131 | unsigned int i; | ||
1132 | |||
1133 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
1134 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1135 | "Task %p trace %d: %s\n", | ||
1136 | t, | ||
1137 | i, | ||
1138 | t->backtrace_strings[i]); | ||
1139 | #endif | ||
1140 | return t; | 1155 | return t; |
1141 | } | 1156 | } |
1142 | 1157 | ||
@@ -1167,16 +1182,16 @@ GNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio, | |||
1167 | * will be scheduled for execution once the delay has expired. It | 1182 | * will be scheduled for execution once the delay has expired. It |
1168 | * will be run with the DEFAULT priority. | 1183 | * will be run with the DEFAULT priority. |
1169 | * | 1184 | * |
1170 | * @param delay when should this operation time out? Use | 1185 | * @param delay when should this operation time out? |
1171 | * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1172 | * @param task main function of the task | 1186 | * @param task main function of the task |
1173 | * @param task_cls closure of task | 1187 | * @param task_cls closure of @a task |
1174 | * @return unique task identifier for the job | 1188 | * @return unique task identifier for the job |
1175 | * only valid until "task" is started! | 1189 | * only valid until @a task is started! |
1176 | */ | 1190 | */ |
1177 | struct GNUNET_SCHEDULER_Task * | 1191 | struct GNUNET_SCHEDULER_Task * |
1178 | GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, | 1192 | GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, |
1179 | GNUNET_SCHEDULER_TaskCallback task, void *task_cls) | 1193 | GNUNET_SCHEDULER_TaskCallback task, |
1194 | void *task_cls) | ||
1180 | { | 1195 | { |
1181 | return GNUNET_SCHEDULER_add_delayed_with_priority (delay, | 1196 | return GNUNET_SCHEDULER_add_delayed_with_priority (delay, |
1182 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 1197 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
@@ -1197,12 +1212,56 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, | |||
1197 | * @param task main function of the task | 1212 | * @param task main function of the task |
1198 | * @param task_cls closure of @a task | 1213 | * @param task_cls closure of @a task |
1199 | * @return unique task identifier for the job | 1214 | * @return unique task identifier for the job |
1200 | * only valid until "task" is started! | 1215 | * only valid until @a task is started! |
1201 | */ | 1216 | */ |
1202 | struct GNUNET_SCHEDULER_Task * | 1217 | struct GNUNET_SCHEDULER_Task * |
1203 | GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, void *task_cls) | 1218 | GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, |
1219 | void *task_cls) | ||
1204 | { | 1220 | { |
1205 | return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, task, task_cls); | 1221 | return GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_ZERO, |
1222 | task, | ||
1223 | task_cls); | ||
1224 | } | ||
1225 | |||
1226 | |||
1227 | /** | ||
1228 | * Schedule a new task to be run on shutdown, that is when a CTRL-C | ||
1229 | * signal is received, or when #GNUNET_SCHEDULER_shutdown() is being | ||
1230 | * invoked. | ||
1231 | * | ||
1232 | * @param task main function of the task | ||
1233 | * @param task_cls closure of @a task | ||
1234 | * @return unique task identifier for the job | ||
1235 | * only valid until @a task is started! | ||
1236 | */ | ||
1237 | struct GNUNET_SCHEDULER_Task * | ||
1238 | GNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, | ||
1239 | void *task_cls) | ||
1240 | { | ||
1241 | struct GNUNET_SCHEDULER_Task *t; | ||
1242 | |||
1243 | GNUNET_assert (NULL != active_task); | ||
1244 | GNUNET_assert (NULL != task); | ||
1245 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); | ||
1246 | t->callback = task; | ||
1247 | t->callback_cls = task_cls; | ||
1248 | t->read_fd = -1; | ||
1249 | t->write_fd = -1; | ||
1250 | #if PROFILE_DELAYS | ||
1251 | t->start_time = GNUNET_TIME_absolute_get (); | ||
1252 | #endif | ||
1253 | t->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1254 | t->priority = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN; | ||
1255 | t->on_shutdown = GNUNET_YES; | ||
1256 | t->lifeness = GNUNET_YES; | ||
1257 | GNUNET_CONTAINER_DLL_insert (shutdown_head, | ||
1258 | shutdown_tail, | ||
1259 | t); | ||
1260 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1261 | "Adding task: %p\n", | ||
1262 | t); | ||
1263 | init_backtrace (t); | ||
1264 | return t; | ||
1206 | } | 1265 | } |
1207 | 1266 | ||
1208 | 1267 | ||
@@ -1246,12 +1305,10 @@ GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, | |||
1246 | * (prerequisite-run) | 1305 | * (prerequisite-run) |
1247 | * && (delay-ready | 1306 | * && (delay-ready |
1248 | * || any-rs-ready | 1307 | * || any-rs-ready |
1249 | * || any-ws-ready | 1308 | * || any-ws-ready) |
1250 | * || shutdown-active ) | ||
1251 | * </code> | 1309 | * </code> |
1252 | * | 1310 | * |
1253 | * @param delay how long should we wait? Use #GNUNET_TIME_UNIT_FOREVER_REL for "forever", | 1311 | * @param delay how long should we wait? |
1254 | * which means that the task will only be run after we receive SIGTERM | ||
1255 | * @param priority priority to use | 1312 | * @param priority priority to use |
1256 | * @param rfd file descriptor we want to read (can be -1) | 1313 | * @param rfd file descriptor we want to read (can be -1) |
1257 | * @param wfd file descriptors we want to write (can be -1) | 1314 | * @param wfd file descriptors we want to write (can be -1) |
@@ -1271,20 +1328,11 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1271 | { | 1328 | { |
1272 | struct GNUNET_SCHEDULER_Task *t; | 1329 | struct GNUNET_SCHEDULER_Task *t; |
1273 | 1330 | ||
1274 | #if EXECINFO | ||
1275 | void *backtrace_array[MAX_TRACE_DEPTH]; | ||
1276 | #endif | ||
1277 | |||
1278 | GNUNET_assert (NULL != active_task); | 1331 | GNUNET_assert (NULL != active_task); |
1279 | GNUNET_assert (NULL != task); | 1332 | GNUNET_assert (NULL != task); |
1280 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); | 1333 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1281 | t->callback = task; | 1334 | t->callback = task; |
1282 | t->callback_cls = task_cls; | 1335 | t->callback_cls = task_cls; |
1283 | #if EXECINFO | ||
1284 | t->num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH); | ||
1285 | t->backtrace_strings = | ||
1286 | backtrace_symbols (backtrace_array, t->num_backtrace_strings); | ||
1287 | #endif | ||
1288 | #if DEBUG_FDS | 1336 | #if DEBUG_FDS |
1289 | if (-1 != rfd) | 1337 | if (-1 != rfd) |
1290 | { | 1338 | { |
@@ -1295,14 +1343,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1295 | LOG (GNUNET_ERROR_TYPE_ERROR, | 1343 | LOG (GNUNET_ERROR_TYPE_ERROR, |
1296 | "Got invalid file descriptor %d!\n", | 1344 | "Got invalid file descriptor %d!\n", |
1297 | rfd); | 1345 | rfd); |
1298 | #if EXECINFO | 1346 | init_backtrace (t); |
1299 | unsigned int i; | ||
1300 | |||
1301 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
1302 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1303 | "Trace: %s\n", | ||
1304 | t->backtrace_strings[i]); | ||
1305 | #endif | ||
1306 | GNUNET_assert (0); | 1347 | GNUNET_assert (0); |
1307 | } | 1348 | } |
1308 | } | 1349 | } |
@@ -1315,14 +1356,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1315 | LOG (GNUNET_ERROR_TYPE_ERROR, | 1356 | LOG (GNUNET_ERROR_TYPE_ERROR, |
1316 | "Got invalid file descriptor %d!\n", | 1357 | "Got invalid file descriptor %d!\n", |
1317 | wfd); | 1358 | wfd); |
1318 | #if EXECINFO | 1359 | init_backtrace (t); |
1319 | unsigned int i; | ||
1320 | |||
1321 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
1322 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1323 | "Trace: %s\n", | ||
1324 | t->backtrace_strings[i]); | ||
1325 | #endif | ||
1326 | GNUNET_assert (0); | 1360 | GNUNET_assert (0); |
1327 | } | 1361 | } |
1328 | } | 1362 | } |
@@ -1344,16 +1378,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1344 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1378 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1345 | "Adding task %p\n", | 1379 | "Adding task %p\n", |
1346 | t); | 1380 | t); |
1347 | #if EXECINFO | 1381 | init_backtrace (t); |
1348 | unsigned int i; | ||
1349 | |||
1350 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
1351 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1352 | "Task %p trace %d: %s\n", | ||
1353 | t, | ||
1354 | i, | ||
1355 | t->backtrace_strings[i]); | ||
1356 | #endif | ||
1357 | return t; | 1382 | return t; |
1358 | } | 1383 | } |
1359 | #endif | 1384 | #endif |
@@ -1366,8 +1391,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1366 | * scheduled for execution once either the delay has expired or the | 1391 | * scheduled for execution once either the delay has expired or the |
1367 | * socket operation is ready. It will be run with the DEFAULT priority. | 1392 | * socket operation is ready. It will be run with the DEFAULT priority. |
1368 | * | 1393 | * |
1369 | * @param delay when should this operation time out? Use | 1394 | * @param delay when should this operation time out? |
1370 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1371 | * @param rfd read file-descriptor | 1395 | * @param rfd read file-descriptor |
1372 | * @param task main function of the task | 1396 | * @param task main function of the task |
1373 | * @param task_cls closure of @a task | 1397 | * @param task_cls closure of @a task |
@@ -1394,8 +1418,7 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, | |||
1394 | * either the delay has expired or the socket operation is ready. It | 1418 | * either the delay has expired or the socket operation is ready. It |
1395 | * will be run with the DEFAULT priority. | 1419 | * will be run with the DEFAULT priority. |
1396 | * | 1420 | * |
1397 | * @param delay when should this operation time out? Use | 1421 | * @param delay when should this operation time out? |
1398 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1399 | * @param priority priority to use for the task | 1422 | * @param priority priority to use for the task |
1400 | * @param rfd read file-descriptor | 1423 | * @param rfd read file-descriptor |
1401 | * @param task main function of the task | 1424 | * @param task main function of the task |
@@ -1426,8 +1449,7 @@ GNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1426 | * socket operation is ready. It will be run with the priority of | 1449 | * socket operation is ready. It will be run with the priority of |
1427 | * the calling task. | 1450 | * the calling task. |
1428 | * | 1451 | * |
1429 | * @param delay when should this operation time out? Use | 1452 | * @param delay when should this operation time out? |
1430 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1431 | * @param wfd write file-descriptor | 1453 | * @param wfd write file-descriptor |
1432 | * @param task main function of the task | 1454 | * @param task main function of the task |
1433 | * @param task_cls closure of @a task | 1455 | * @param task_cls closure of @a task |
@@ -1454,8 +1476,7 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, | |||
1454 | * scheduled for execution once either the delay has expired or the | 1476 | * scheduled for execution once either the delay has expired or the |
1455 | * socket operation is ready. | 1477 | * socket operation is ready. |
1456 | * | 1478 | * |
1457 | * @param delay when should this operation time out? Use | 1479 | * @param delay when should this operation time out? |
1458 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1459 | * @param priority priority of the task | 1480 | * @param priority priority of the task |
1460 | * @param fd file-descriptor | 1481 | * @param fd file-descriptor |
1461 | * @param on_read whether to poll the file-descriptor for readability | 1482 | * @param on_read whether to poll the file-descriptor for readability |
@@ -1505,8 +1526,7 @@ GNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, | |||
1505 | * scheduled for execution once either the delay has expired or the | 1526 | * scheduled for execution once either the delay has expired or the |
1506 | * socket operation is ready. It will be run with the DEFAULT priority. | 1527 | * socket operation is ready. It will be run with the DEFAULT priority. |
1507 | * | 1528 | * |
1508 | * @param delay when should this operation time out? Use | 1529 | * @param delay when should this operation time out? |
1509 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1510 | * @param rfd read file-descriptor | 1530 | * @param rfd read file-descriptor |
1511 | * @param task main function of the task | 1531 | * @param task main function of the task |
1512 | * @param task_cls closure of @a task | 1532 | * @param task_cls closure of @a task |
@@ -1532,8 +1552,7 @@ GNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, | |||
1532 | * scheduled for execution once either the delay has expired or the | 1552 | * scheduled for execution once either the delay has expired or the |
1533 | * socket operation is ready. It will be run with the DEFAULT priority. | 1553 | * socket operation is ready. It will be run with the DEFAULT priority. |
1534 | * | 1554 | * |
1535 | * @param delay when should this operation time out? Use | 1555 | * @param delay when should this operation time out? |
1536 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1537 | * @param wfd write file-descriptor | 1556 | * @param wfd write file-descriptor |
1538 | * @param task main function of the task | 1557 | * @param task main function of the task |
1539 | * @param task_cls closure of @a task | 1558 | * @param task_cls closure of @a task |
@@ -1559,8 +1578,7 @@ GNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, | |||
1559 | * scheduled for execution once either the delay has expired or the | 1578 | * scheduled for execution once either the delay has expired or the |
1560 | * socket operation is ready. | 1579 | * socket operation is ready. |
1561 | * | 1580 | * |
1562 | * @param delay when should this operation time out? Use | 1581 | * @param delay when should this operation time out? |
1563 | * #GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown" | ||
1564 | * @param priority priority of the task | 1582 | * @param priority priority of the task |
1565 | * @param fd file-descriptor | 1583 | * @param fd file-descriptor |
1566 | * @param on_read whether to poll the file-descriptor for readability | 1584 | * @param on_read whether to poll the file-descriptor for readability |
@@ -1618,13 +1636,11 @@ GNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, | |||
1618 | * (prerequisite-run) | 1636 | * (prerequisite-run) |
1619 | * && (delay-ready | 1637 | * && (delay-ready |
1620 | * || any-rs-ready | 1638 | * || any-rs-ready |
1621 | * || any-ws-ready | 1639 | * || any-ws-ready) ) |
1622 | * || (shutdown-active && run-on-shutdown) ) | ||
1623 | * </code> | 1640 | * </code> |
1624 | * | 1641 | * |
1625 | * @param prio how important is this task? | 1642 | * @param prio how important is this task? |
1626 | * @param delay how long should we wait? Use #GNUNET_TIME_UNIT_FOREVER_REL for "forever", | 1643 | * @param delay how long should we wait? |
1627 | * which means that the task will only be run after we receive SIGTERM | ||
1628 | * @param rs set of file descriptors we want to read (can be NULL) | 1644 | * @param rs set of file descriptors we want to read (can be NULL) |
1629 | * @param ws set of file descriptors we want to write (can be NULL) | 1645 | * @param ws set of file descriptors we want to write (can be NULL) |
1630 | * @param task main function of the task | 1646 | * @param task main function of the task |
@@ -1641,9 +1657,6 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | |||
1641 | void *task_cls) | 1657 | void *task_cls) |
1642 | { | 1658 | { |
1643 | struct GNUNET_SCHEDULER_Task *t; | 1659 | struct GNUNET_SCHEDULER_Task *t; |
1644 | #if EXECINFO | ||
1645 | void *backtrace_array[MAX_TRACE_DEPTH]; | ||
1646 | #endif | ||
1647 | 1660 | ||
1648 | if ( (NULL == rs) && | 1661 | if ( (NULL == rs) && |
1649 | (NULL == ws) ) | 1662 | (NULL == ws) ) |
@@ -1656,11 +1669,6 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | |||
1656 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); | 1669 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1657 | t->callback = task; | 1670 | t->callback = task; |
1658 | t->callback_cls = task_cls; | 1671 | t->callback_cls = task_cls; |
1659 | #if EXECINFO | ||
1660 | t->num_backtrace_strings = backtrace (backtrace_array, MAX_TRACE_DEPTH); | ||
1661 | t->backtrace_strings = | ||
1662 | backtrace_symbols (backtrace_array, t->num_backtrace_strings); | ||
1663 | #endif | ||
1664 | t->read_fd = -1; | 1672 | t->read_fd = -1; |
1665 | t->write_fd = -1; | 1673 | t->write_fd = -1; |
1666 | if (NULL != rs) | 1674 | if (NULL != rs) |
@@ -1689,16 +1697,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | |||
1689 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1697 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1690 | "Adding task %p\n", | 1698 | "Adding task %p\n", |
1691 | t); | 1699 | t); |
1692 | #if EXECINFO | 1700 | init_backtrace (t); |
1693 | int i; | ||
1694 | |||
1695 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
1696 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1697 | "Task p trace %d: %s\n", | ||
1698 | t, | ||
1699 | i, | ||
1700 | t->backtrace_strings[i]); | ||
1701 | #endif | ||
1702 | return t; | 1701 | return t; |
1703 | } | 1702 | } |
1704 | 1703 | ||