aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-08-02 14:35:29 +0000
committerChristian Grothoff <christian@grothoff.org>2011-08-02 14:35:29 +0000
commit8b1ea3124c95c26fb1a7c8a106c7aaf7b817ccc0 (patch)
treebee84128152805b0460ee937a28bd78fecd949d0 /src/util
parent21490594534e5ab37d9d0030d5ec5687c1b8c69a (diff)
downloadgnunet-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.c7
-rw-r--r--src/util/scheduler.c92
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 */
54void 54static void
55parent_control_handler (void *cls, 55parent_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 */
235static enum GNUNET_SCHEDULER_Priority max_priority_added; 241static enum GNUNET_SCHEDULER_Priority max_priority_added;
236 242
243/**
244 * Value of the 'lifeness' flag for the current task.
245 */
246static 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 */
714static int
715check_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 */
1177GNUNET_SCHEDULER_TaskIdentifier 1214GNUNET_SCHEDULER_TaskIdentifier
1178GNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_Task task, 1215GNUNET_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 */
1239GNUNET_SCHEDULER_TaskIdentifier
1240GNUNET_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);