*/
#include "platform.h"
#include "gnunet_common.h"
+#include "gnunet_os_lib.h"
#include "gnunet_scheduler_lib.h"
#include "gnunet_signal_lib.h"
#include "gnunet_time_lib.h"
#ifdef LINUX
#include "execinfo.h"
-#define EXECINFO GNUNET_YES
+/**
+ * Obtain trace information for all scheduler calls that schedule tasks.
+ */
+#define EXECINFO GNUNET_NO
+
+/**
+ * Depth of the traces collected via EXECINFO.
+ */
#define MAX_TRACE_DEPTH 50
#endif
#define DEBUG_TASKS GNUNET_NO
+/**
+ * Should we figure out which tasks are delayed for a while
+ * before they are run? (Consider using in combination with EXECINFO).
+ */
+#define PROFILE_DELAYS GNUNET_NO
+
+/**
+ * Task that were in the queue for longer than this are reported if
+ * PROFILE_DELAYS is active.
+ */
+#define DELAY_THRESHOLD GNUNET_TIME_UNIT_SECONDS
+
/**
* Linked list of pending tasks.
*/
*/
struct GNUNET_TIME_Absolute timeout;
+#if PROFILE_DELAYS
+ /**
+ * When was the task scheduled?
+ */
+ struct GNUNET_TIME_Absolute start_time;
+#endif
+
/**
* Why is the task ready? Set after task is added to ready queue.
* Initially set to zero. All reasons that have already been
*/
enum GNUNET_SCHEDULER_Priority current_priority;
+ /**
+ * How 'nice' are we right now?
+ */
+ int nice_level;
+
};
GNUNET_assert (pos != NULL); /* ready_count wrong? */
sched->ready[p] = pos->next;
sched->ready_count--;
- sched->current_priority = pos->priority;
+ if (sched->current_priority != pos->priority)
+ {
+ sched->current_priority = pos->priority;
+ (void) GNUNET_OS_set_process_priority (0, pos->priority);
+ }
sched->active_task = pos;
+#if PROFILE_DELAYS
+ if (GNUNET_TIME_absolute_get_duration (pos->start_time).value >
+ DELAY_THRESHOLD.value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Task %u took %llums to be scheduled\n",
+ pos->id,
+ (unsigned long long) GNUNET_TIME_absolute_get_duration (pos->start_time).value);
+#if EXECINFO
+ int i;
+ for (i=0;i<pos->num_backtrace_strings;i++)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Task %u trace %d: %s\n",
+ pos->id,
+ i,
+ pos->backtrace_strings[i]);
+#endif
+ }
+#endif
tc.sched = sched;
tc.reason = pos->reason;
tc.read_ready = pos->read_set;
if (errno == EINTR)
continue;
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
- break;
+ abort ();
+ break;
}
if (GNUNET_NETWORK_fdset_handle_isset (rs, pr))
{
t->callback = task;
t->callback_cls = task_cls;
t->id = ++sched->last_id;
+#if PROFILE_DELAYS
+ t->start_time = GNUNET_TIME_absolute_get ();
+#endif
t->reason = reason;
t->priority = sched->current_priority;
#if DEBUG_TASKS
#if EXECINFO
void *backtrace_array[MAX_TRACE_DEPTH];
#endif
+
+ GNUNET_assert (NULL != task);
t = GNUNET_malloc (sizeof (struct Task));
t->callback = task;
t->callback_cls = task_cls;
GNUNET_NETWORK_fdset_copy (t->write_set, ws);
}
t->id = ++sched->last_id;
+#if PROFILE_DELAYS
+ t->start_time = GNUNET_TIME_absolute_get ();
+#endif
t->prereq_id = prerequisite_task;
t->timeout = GNUNET_TIME_relative_to_absolute (delay);
t->priority =