*/
#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_NO
+#define MAX_TRACE_DEPTH 50
+#endif
#define DEBUG_TASKS GNUNET_NO
struct GNUNET_NETWORK_FDSet *read_set;
/**
- * Set of file descriptors this task is waiting
- * for for writing. Once ready, this is updated
- * to reflect the set of file descriptors ready
- * for operation.
+ * Set of file descriptors this task is waiting for for writing.
+ * Once ready, this is updated to reflect the set of file
+ * descriptors ready for operation.
*/
struct GNUNET_NETWORK_FDSet *write_set;
*/
enum GNUNET_SCHEDULER_Priority priority;
+#if EXECINFO
+ /**
+ * Array of strings which make up a backtrace from the point when this
+ * task was scheduled (essentially, who scheduled the task?)
+ */
+ char **backtrace_strings;
+
+ /**
+ * Size of the backtrace_strings array
+ */
+ int num_backtrace_strings;
+#endif
+
};
*/
enum GNUNET_SCHEDULER_Priority current_priority;
+ /**
+ * How 'nice' are we right now?
+ */
+ int nice_level;
+
};
static void
queue_ready_task (struct GNUNET_SCHEDULER_Handle *handle, struct Task *task)
{
- task->next = handle->ready[check_priority (task->priority)];
- handle->ready[check_priority (task->priority)] = task;
+ enum GNUNET_SCHEDULER_Priority p = task->priority;
+ if (0 != (task->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ p = GNUNET_SCHEDULER_PRIORITY_SHUTDOWN;
+ task->next = handle->ready[check_priority (p)];
+ handle->ready[check_priority (p)] = task;
handle->ready_count++;
}
GNUNET_NETWORK_fdset_destroy (t->read_set);
if (NULL != t->write_set)
GNUNET_NETWORK_fdset_destroy (t->write_set);
+#if EXECINFO
+ GNUNET_free (t->backtrace_strings);
+#endif
GNUNET_free (t);
}
GNUNET_assert (pos != NULL); /* ready_count wrong? */
sched->ready[p] = pos->next;
sched->ready_count--;
- sched->current_priority = p;
- GNUNET_assert (pos->priority == p);
+ if (sched->current_priority != pos->priority)
+ {
+ sched->current_priority = pos->priority;
+ (void) GNUNET_OS_set_process_priority (0, pos->priority);
+ }
sched->active_task = pos;
tc.sched = sched;
tc.reason = pos->reason;
if (errno == EINTR)
continue;
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
- break;
+ abort ();
+ break;
}
if (GNUNET_NETWORK_fdset_handle_isset (rs, pr))
{
enum GNUNET_SCHEDULER_Reason reason)
{
struct Task *t;
-
+#if EXECINFO
+ void *backtrace_array[50];
+#endif
t = GNUNET_malloc (sizeof (struct Task));
+#if EXECINFO
+ t->num_backtrace_strings = backtrace(backtrace_array, 50);
+ t->backtrace_strings = backtrace_symbols(backtrace_array, t->num_backtrace_strings);
+#endif
t->callback = task;
t->callback_cls = task_cls;
t->id = ++sched->last_id;
GNUNET_SCHEDULER_Task task, void *task_cls)
{
struct Task *t;
+#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;
+#if EXECINFO
+ t->num_backtrace_strings = backtrace(backtrace_array, MAX_TRACE_DEPTH);
+ t->backtrace_strings = backtrace_symbols(backtrace_array, t->num_backtrace_strings);
+#endif
if (rs != NULL)
{
t->read_set = GNUNET_NETWORK_fdset_create ();