diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-08-02 14:35:29 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-08-02 14:35:29 +0000 |
commit | 8b1ea3124c95c26fb1a7c8a106c7aaf7b817ccc0 (patch) | |
tree | bee84128152805b0460ee937a28bd78fecd949d0 /src/util | |
parent | 21490594534e5ab37d9d0030d5ec5687c1b8c69a (diff) | |
download | gnunet-8b1ea3124c95c26fb1a7c8a106c7aaf7b817ccc0.tar.gz gnunet-8b1ea3124c95c26fb1a7c8a106c7aaf7b817ccc0.zip |
fixing parent_control_handler hack, adding lifeness attribute to tasks
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/os_priority.c | 7 | ||||
-rw-r--r-- | src/util/scheduler.c | 92 |
2 files changed, 85 insertions, 14 deletions
diff --git a/src/util/os_priority.c b/src/util/os_priority.c index c9458212e..f2e3f3c38 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c | |||
@@ -51,7 +51,7 @@ static struct GNUNET_OS_Process current_process; | |||
51 | * @param cls the 'struct GNUNET_DISK_FileHandle' of the control pipe | 51 | * @param cls the 'struct GNUNET_DISK_FileHandle' of the control pipe |
52 | * @param tc scheduler context | 52 | * @param tc scheduler context |
53 | */ | 53 | */ |
54 | void | 54 | static void |
55 | parent_control_handler (void *cls, | 55 | parent_control_handler (void *cls, |
56 | const struct | 56 | const struct |
57 | GNUNET_SCHEDULER_TaskContext * tc) | 57 | GNUNET_SCHEDULER_TaskContext * tc) |
@@ -718,12 +718,12 @@ GNUNET_OS_start_process_va (struct GNUNET_DISK_PipeHandle *pipe_stdin, | |||
718 | cmdlen = 0; | 718 | cmdlen = 0; |
719 | va_copy (ap, va); | 719 | va_copy (ap, va); |
720 | while (NULL != (arg = va_arg (ap, char *))) | 720 | while (NULL != (arg = va_arg (ap, char *))) |
721 | { | 721 | { |
722 | if (cmdlen == 0) | 722 | if (cmdlen == 0) |
723 | cmdlen = cmdlen + strlen (path) + 3; | 723 | cmdlen = cmdlen + strlen (path) + 3; |
724 | else | 724 | else |
725 | cmdlen = cmdlen + strlen (arg) + 3; | 725 | cmdlen = cmdlen + strlen (arg) + 3; |
726 | } | 726 | } |
727 | va_end (ap); | 727 | va_end (ap); |
728 | 728 | ||
729 | cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1)); | 729 | cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1)); |
@@ -1244,6 +1244,7 @@ GNUNET_OS_process_status (struct GNUNET_OS_Process *proc, | |||
1244 | return GNUNET_OK; | 1244 | return GNUNET_OK; |
1245 | } | 1245 | } |
1246 | 1246 | ||
1247 | |||
1247 | /** | 1248 | /** |
1248 | * Wait for a process | 1249 | * Wait for a process |
1249 | * @param proc pointer to process structure | 1250 | * @param proc pointer to process structure |
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index eaf965894..429adafa3 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -149,6 +149,12 @@ struct Task | |||
149 | * Set if we only wait for writing to a single FD, otherwise -1. | 149 | * Set if we only wait for writing to a single FD, otherwise -1. |
150 | */ | 150 | */ |
151 | int write_fd; | 151 | int write_fd; |
152 | |||
153 | /** | ||
154 | * Should the existence of this task in the queue be counted as | ||
155 | * reason to not shutdown the scheduler? | ||
156 | */ | ||
157 | int lifeness; | ||
152 | 158 | ||
153 | #if EXECINFO | 159 | #if EXECINFO |
154 | /** | 160 | /** |
@@ -234,6 +240,10 @@ static enum GNUNET_SCHEDULER_Priority current_priority; | |||
234 | */ | 240 | */ |
235 | static enum GNUNET_SCHEDULER_Priority max_priority_added; | 241 | static enum GNUNET_SCHEDULER_Priority max_priority_added; |
236 | 242 | ||
243 | /** | ||
244 | * Value of the 'lifeness' flag for the current task. | ||
245 | */ | ||
246 | static int current_lifeness; | ||
237 | 247 | ||
238 | /** | 248 | /** |
239 | * Check that the given priority is legal (and return it). | 249 | * Check that the given priority is legal (and return it). |
@@ -614,6 +624,7 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, | |||
614 | (void) GNUNET_OS_set_process_priority (GNUNET_OS_process_current (), | 624 | (void) GNUNET_OS_set_process_priority (GNUNET_OS_process_current (), |
615 | pos->priority); | 625 | pos->priority); |
616 | } | 626 | } |
627 | current_lifeness = pos->lifeness; | ||
617 | active_task = pos; | 628 | active_task = pos; |
618 | #if PROFILE_DELAYS | 629 | #if PROFILE_DELAYS |
619 | if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value > | 630 | if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value > |
@@ -694,6 +705,34 @@ sighandler_shutdown () | |||
694 | 705 | ||
695 | 706 | ||
696 | /** | 707 | /** |
708 | * Check if the system is still life. Trigger shutdown if we | ||
709 | * have tasks, but none of them give us lifeness. | ||
710 | * | ||
711 | * @return GNUNET_OK to continue the main loop, | ||
712 | * GNUNET_NO to exit | ||
713 | */ | ||
714 | static int | ||
715 | check_lifeness() | ||
716 | { | ||
717 | struct Task *t; | ||
718 | if (ready_count > 0) | ||
719 | return GNUNET_OK; | ||
720 | for (t = pending; NULL != t; t = t->next) | ||
721 | if (t->lifeness == GNUNET_YES) | ||
722 | return GNUNET_OK; | ||
723 | for (t = pending_timeout; NULL != t; t = t->next) | ||
724 | if (t->lifeness == GNUNET_YES) | ||
725 | return GNUNET_OK; | ||
726 | if ( (NULL != pending) || (NULL != pending_timeout) ) | ||
727 | { | ||
728 | GNUNET_SCHEDULER_shutdown (); | ||
729 | return GNUNET_OK; | ||
730 | } | ||
731 | return GNUNET_NO; | ||
732 | } | ||
733 | |||
734 | |||
735 | /** | ||
697 | * Initialize and run scheduler. This function will return when all | 736 | * Initialize and run scheduler. This function will return when all |
698 | * tasks have completed. On systems with signals, receiving a SIGTERM | 737 | * tasks have completed. On systems with signals, receiving a SIGTERM |
699 | * (and other similar signals) will cause "GNUNET_SCHEDULER_shutdown" | 738 | * (and other similar signals) will cause "GNUNET_SCHEDULER_shutdown" |
@@ -742,22 +781,18 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) | |||
742 | shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown); | 781 | shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown); |
743 | #endif | 782 | #endif |
744 | current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; | 783 | current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; |
784 | current_lifeness = GNUNET_YES; | ||
745 | GNUNET_SCHEDULER_add_continuation (task, | 785 | GNUNET_SCHEDULER_add_continuation (task, |
746 | task_cls, | 786 | task_cls, |
747 | GNUNET_SCHEDULER_REASON_STARTUP); | 787 | GNUNET_SCHEDULER_REASON_STARTUP); |
748 | #if ENABLE_WINDOWS_WORKAROUNDS | 788 | #if ENABLE_WINDOWS_WORKAROUNDS |
749 | GNUNET_SCHEDULER_add_continuation (&GNUNET_OS_install_parent_control_handler, | 789 | GNUNET_SCHEDULER_add_now_with_lifeness (GNUNET_NO, |
750 | NULL, GNUNET_SCHEDULER_REASON_STARTUP); | 790 | &GNUNET_OS_install_parent_control_handler, |
791 | NULL, GNUNET_SCHEDULER_REASON_STARTUP); | ||
751 | #endif | 792 | #endif |
752 | last_tr = 0; | 793 | last_tr = 0; |
753 | busy_wait_warning = 0; | 794 | busy_wait_warning = 0; |
754 | while ((pending != NULL | 795 | while (GNUNET_OK == check_lifeness ()) |
755 | #if ENABLE_WINDOWS_WORKAROUNDS | ||
756 | && (pending->callback != parent_control_handler || pending->next != NULL) | ||
757 | #endif | ||
758 | ) || | ||
759 | (pending_timeout != NULL) || | ||
760 | (ready_count > 0)) | ||
761 | { | 796 | { |
762 | GNUNET_NETWORK_fdset_zero (rs); | 797 | GNUNET_NETWORK_fdset_zero (rs); |
763 | GNUNET_NETWORK_fdset_zero (ws); | 798 | GNUNET_NETWORK_fdset_zero (ws); |
@@ -1008,6 +1043,7 @@ GNUNET_SCHEDULER_add_continuation (GNUNET_SCHEDULER_Task task, | |||
1008 | #endif | 1043 | #endif |
1009 | t->reason = reason; | 1044 | t->reason = reason; |
1010 | t->priority = current_priority; | 1045 | t->priority = current_priority; |
1046 | t->lifeness = current_lifeness; | ||
1011 | #if DEBUG_TASKS | 1047 | #if DEBUG_TASKS |
1012 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1048 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1013 | "Adding continuation task: %llu / %p\n", | 1049 | "Adding continuation task: %llu / %p\n", |
@@ -1109,6 +1145,7 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, | |||
1109 | #endif | 1145 | #endif |
1110 | t->timeout = GNUNET_TIME_relative_to_absolute (delay); | 1146 | t->timeout = GNUNET_TIME_relative_to_absolute (delay); |
1111 | t->priority = current_priority; | 1147 | t->priority = current_priority; |
1148 | t->lifeness = current_lifeness; | ||
1112 | /* try tail first (optimization in case we are | 1149 | /* try tail first (optimization in case we are |
1113 | appending to a long list of tasks with timeouts) */ | 1150 | appending to a long list of tasks with timeouts) */ |
1114 | prev = pending_timeout_last; | 1151 | prev = pending_timeout_last; |
@@ -1176,7 +1213,7 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, | |||
1176 | */ | 1213 | */ |
1177 | GNUNET_SCHEDULER_TaskIdentifier | 1214 | GNUNET_SCHEDULER_TaskIdentifier |
1178 | GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, | 1215 | GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, |
1179 | void *task_cls) | 1216 | void *task_cls) |
1180 | { | 1217 | { |
1181 | return GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_KEEP, | 1218 | return GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_KEEP, |
1182 | GNUNET_SCHEDULER_NO_TASK, | 1219 | GNUNET_SCHEDULER_NO_TASK, |
@@ -1185,6 +1222,37 @@ GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, | |||
1185 | } | 1222 | } |
1186 | 1223 | ||
1187 | 1224 | ||
1225 | /** | ||
1226 | * Schedule a new task to be run as soon as possible with the | ||
1227 | * (transitive) ignore-shutdown flag either explicitly set or | ||
1228 | * explicitly enabled. This task (and all tasks created from it, | ||
1229 | * other than by another call to this function) will either count or | ||
1230 | * not count for the 'lifeness' of the process. This API is only | ||
1231 | * useful in a few special cases. | ||
1232 | * | ||
1233 | * @param lifeness GNUNET_YES if the task counts for lifeness, GNUNET_NO if not. | ||
1234 | * @param task main function of the task | ||
1235 | * @param task_cls closure of task | ||
1236 | * @return unique task identifier for the job | ||
1237 | * only valid until "task" is started! | ||
1238 | */ | ||
1239 | GNUNET_SCHEDULER_TaskIdentifier | ||
1240 | GNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, | ||
1241 | GNUNET_SCHEDULER_Task task, | ||
1242 | void *task_cls) | ||
1243 | { | ||
1244 | GNUNET_SCHEDULER_TaskIdentifier ret; | ||
1245 | |||
1246 | ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_KEEP, | ||
1247 | GNUNET_SCHEDULER_NO_TASK, | ||
1248 | GNUNET_TIME_UNIT_ZERO, | ||
1249 | NULL, NULL, task, task_cls); | ||
1250 | GNUNET_assert (pending->id == ret); | ||
1251 | pending->lifeness = lifeness; | ||
1252 | return ret; | ||
1253 | } | ||
1254 | |||
1255 | |||
1188 | 1256 | ||
1189 | 1257 | ||
1190 | /** | 1258 | /** |
@@ -1280,6 +1348,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1280 | t->prereq_id = GNUNET_SCHEDULER_NO_TASK; | 1348 | t->prereq_id = GNUNET_SCHEDULER_NO_TASK; |
1281 | t->timeout = GNUNET_TIME_relative_to_absolute (delay); | 1349 | t->timeout = GNUNET_TIME_relative_to_absolute (delay); |
1282 | t->priority = check_priority (current_priority); | 1350 | t->priority = check_priority (current_priority); |
1351 | t->lifeness = current_lifeness; | ||
1283 | t->next = pending; | 1352 | t->next = pending; |
1284 | pending = t; | 1353 | pending = t; |
1285 | max_priority_added = GNUNET_MAX (max_priority_added, | 1354 | max_priority_added = GNUNET_MAX (max_priority_added, |
@@ -1564,10 +1633,11 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | |||
1564 | check_priority ((prio == | 1633 | check_priority ((prio == |
1565 | GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority | 1634 | GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority |
1566 | : prio); | 1635 | : prio); |
1636 | t->lifeness = current_lifeness; | ||
1567 | t->next = pending; | 1637 | t->next = pending; |
1568 | pending = t; | 1638 | pending = t; |
1569 | max_priority_added = GNUNET_MAX (max_priority_added, | 1639 | max_priority_added = GNUNET_MAX (max_priority_added, |
1570 | t->priority); | 1640 | t->priority); |
1571 | #if DEBUG_TASKS | 1641 | #if DEBUG_TASKS |
1572 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1642 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1573 | "Adding task: %llu / %p\n", t->id, t->callback_cls); | 1643 | "Adding task: %llu / %p\n", t->id, t->callback_cls); |