};
+/**
+ * A struct representing an event the select driver is waiting for
+ */
struct Scheduled
{
struct Scheduled *prev;
struct Scheduled *next;
+ /**
+ * the task, the event is related to
+ */
struct GNUNET_SCHEDULER_Task *task;
+ /**
+ * information about the network socket / file descriptor where
+ * the event is expected to occur
+ */
struct GNUNET_SCHEDULER_FdInfo *fdi;
+ /**
+ * the event types (multiple event types can be ORed) the select
+ * driver is expected to wait for
+ */
enum GNUNET_SCHEDULER_EventType et;
-
- int is_ready;
};
*/
struct DriverContext
{
+ /**
+ * the head of a DLL containing information about the events the
+ * select driver is waiting for
+ */
struct Scheduled *scheduled_head;
+ /**
+ * the tail of a DLL containing information about the events the
+ * select driver is waiting for
+ */
struct Scheduled *scheduled_tail;
+ /**
+ * the time until the select driver will wake up again (after
+ * calling select)
+ */
struct GNUNET_TIME_Relative timeout;
};
{
unsigned int i;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "destroying task %p\n",
+ t);
+
if (GNUNET_YES == t->own_handlers)
{
for (i = 0; i != t->fds_len; ++i)
* @param et the event type to be set in each FdInfo after calling
* @a driver_func on it, or -1 if no updating not desired.
*/
-void scheduler_multi_function_call (struct GNUNET_SCHEDULER_Task *t,
- int (*driver_func)(),
- int if_not_ready,
- enum GNUNET_SCHEDULER_EventType et)
+void driver_add_multiple (struct GNUNET_SCHEDULER_Task *t,
+ enum GNUNET_SCHEDULER_EventType et)
{
struct GNUNET_SCHEDULER_FdInfo *fdi;
int success = GNUNET_YES;
for (int i = 0; i != t->fds_len; ++i)
{
fdi = &t->fds[i];
- if ((GNUNET_NO == if_not_ready) || (GNUNET_SCHEDULER_ET_NONE == fdi->et))
+ success = scheduler_driver->add (scheduler_driver->cls, t, fdi) && success;
+ if (et != -1)
{
- success = driver_func (scheduler_driver->cls, t, fdi) && success;
- if (et != -1)
- {
- fdi->et = et;
- }
+ fdi->et = et;
}
}
if (GNUNET_YES != success)
{
LOG (GNUNET_ERROR_TYPE_ERROR,
- "driver call not successful");
+ "driver could not add task\n");
}
}
GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task)
{
enum GNUNET_SCHEDULER_Priority p;
+ int is_fd_task;
void *ret;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "canceling task %p\n",
+ task);
+
/* scheduler must be running */
GNUNET_assert (NULL != scheduler_driver);
GNUNET_assert ( (NULL != active_task) ||
(GNUNET_NO == task->lifeness) );
- if (! task->in_ready_list)
+ is_fd_task = (NULL != task->fds);
+ if (is_fd_task)
{
- if (NULL == task->fds)
+ int del_result = scheduler_driver->del (scheduler_driver->cls, task);
+ if (GNUNET_OK != del_result)
{
- if (GNUNET_YES == task->on_shutdown)
- GNUNET_CONTAINER_DLL_remove (shutdown_head,
- shutdown_tail,
- task);
- else
- {
- GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
- pending_timeout_tail,
- task);
- if (pending_timeout_last == task)
- pending_timeout_last = NULL;
- }
- //TODO check if this is redundant
- if (task == pending_timeout_last)
- pending_timeout_last = NULL;
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "driver could not delete task\n");
+ GNUNET_assert (0);
}
- else
+ }
+ if (! task->in_ready_list)
+ {
+ if (is_fd_task)
{
GNUNET_CONTAINER_DLL_remove (pending_head,
pending_tail,
task);
- scheduler_multi_function_call(task, scheduler_driver->del, GNUNET_NO, -1);
+ }
+ else if (GNUNET_YES == task->on_shutdown)
+ {
+ GNUNET_CONTAINER_DLL_remove (shutdown_head,
+ shutdown_tail,
+ task);
+ }
+ else
+ {
+ GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
+ pending_timeout_tail,
+ task);
+ if (pending_timeout_last == task)
+ pending_timeout_last = NULL;
}
}
else
GNUNET_CONTAINER_DLL_insert (pending_head,
pending_tail,
t);
- scheduler_multi_function_call (t, scheduler_driver->add, GNUNET_NO, GNUNET_SCHEDULER_ET_NONE);
+ driver_add_multiple (t, GNUNET_SCHEDULER_ET_NONE);
max_priority_added = GNUNET_MAX (max_priority_added,
t->priority);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Adding task %p\n",
- t);
init_backtrace (t);
return t;
}
GNUNET_CONTAINER_DLL_insert (pending_head,
pending_tail,
t);
- scheduler_multi_function_call (t, scheduler_driver->add, GNUNET_NO, GNUNET_SCHEDULER_ET_NONE);
+ driver_add_multiple (t, GNUNET_SCHEDULER_ET_NONE);
max_priority_added = GNUNET_MAX (max_priority_added,
t->priority);
LOG (GNUNET_ERROR_TYPE_DEBUG,
if (0 == ready_count)
{
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "no tasks run!\n");
return GNUNET_NO;
}
"Running task %p\n",
pos);
pos->callback (pos->callback_cls);
- scheduler_multi_function_call (pos, scheduler_driver->del, GNUNET_YES, -1);
+ if (NULL != pos->fds)
+ {
+ int del_result = scheduler_driver->del (scheduler_driver->cls, pos);
+ if (GNUNET_OK != del_result)
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "driver could not delete task\n");
+ GNUNET_assert (0);
+ }
+ }
active_task = NULL;
dump_backtrace (pos);
destroy_task (pos);
int
select_del (void *cls,
- struct GNUNET_SCHEDULER_Task *task,
- struct GNUNET_SCHEDULER_FdInfo *fdi)
+ struct GNUNET_SCHEDULER_Task *task)
{
struct DriverContext *context;
struct Scheduled *pos;
context = cls;
ret = GNUNET_SYSERR;
- for (pos = context->scheduled_head; NULL != pos; pos = pos->next)
+ pos = context->scheduled_head;
+ while (NULL != pos)
{
- if (pos->task == task && pos->fdi == fdi)
+ struct Scheduled *next = pos->next;
+ if (pos->task == task)
{
GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
context->scheduled_tail,
pos);
+ GNUNET_free (pos);
ret = GNUNET_OK;
- break;
}
+ pos = next;
}
return ret;
}
busy_wait_warning = 0;
while (NULL != context->scheduled_head || GNUNET_YES == tasks_ready)
{
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "[%p] timeout = %s\n",
- sh,
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "select timeout = %s\n",
GNUNET_STRINGS_relative_time_to_string (context->timeout, GNUNET_NO));
GNUNET_NETWORK_fdset_zero (rs);
}
if (select_result == GNUNET_SYSERR)
{
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "select_result = GNUNET_SYSERR\n");
if (errno == EINTR)
continue;
}
if (GNUNET_YES == is_ready)
{
- GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
- context->scheduled_tail,
- pos);
+ //GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
+ // context->scheduled_tail,
+ // pos);
GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi);
}
}
tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh);
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "[%p] tasks_ready: %d\n",
- sh,
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "tasks_ready: %d\n",
tasks_ready);
// FIXME: tasks_run is a driver-internal variable! Instead we should increment
// a local variable tasks_ready_count everytime we're calling GNUNET_SCHEDULER_task_ready.
if (last_tr == tasks_run)
{
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "[%p] no tasks run\n",
- sh);
short_wait (1);
busy_wait_warning++;
}