GNUnet 0.26.2-16-ge86b66bd5
 
Loading...
Searching...
No Matches
scheduler.c File Reference

main event loop we use for most processes, schedules computations based on time or network events with priorities More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include <inttypes.h>
Include dependency graph for scheduler.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_SCHEDULER_Handle
 Argument to be passed from the driver to GNUNET_SCHEDULER_do_work(). More...
 
struct  GNUNET_SCHEDULER_Task
 Entry in list of pending tasks. More...
 
struct  Scheduled
 A struct representing an event the select driver is waiting for. More...
 
struct  DriverContext
 Driver context used by GNUNET_SCHEDULER_run. More...
 

Macros

#define EXTRA_DEBUG   0
 Add debug logging to scheduler that is usually totally excessive.
 
#define LOG(kind, ...)   GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)
 
#define PROFILE_DELAYS   GNUNET_NO
 Should we figure out which tasks are delayed for a while before they are run? (Consider using in combination with EXECINFO).
 
#define DELAY_THRESHOLD   GNUNET_TIME_UNIT_SECONDS
 Task that were in the queue for longer than this are reported if PROFILE_DELAYS is active.
 

Functions

void GNUNET_SCHEDULER_set_select (GNUNET_SCHEDULER_select new_select, void *new_select_cls)
 Sets the select function to use in the scheduler (scheduler_select).
 
static enum GNUNET_SCHEDULER_Priority check_priority (enum GNUNET_SCHEDULER_Priority p)
 Check that the given priority is legal (and return it).
 
static struct GNUNET_TIME_Absolute get_timeout ()
 chooses the nearest timeout from all pending tasks, to be used to tell the driver the next wakeup time (using its set_wakeup callback)
 
static void remove_pass_end_marker ()
 
static void set_work_priority (enum GNUNET_SCHEDULER_Priority p)
 
static void queue_ready_task (struct GNUNET_SCHEDULER_Task *task)
 Put a task that is ready for execution into the ready queue.
 
void GNUNET_SCHEDULER_shutdown ()
 Request the shutdown of a scheduler.
 
static void dump_backtrace (struct GNUNET_SCHEDULER_Task *t)
 Output stack trace of task t.
 
static void destroy_task (struct GNUNET_SCHEDULER_Task *t)
 Destroy a task (release associated resources)
 
static void sighandler_pipe ()
 Signal handler called for SIGPIPE.
 
static void sighandler_shutdown (void)
 Signal handler called for signals that should cause us to shutdown.
 
static void shutdown_if_no_lifeness (void)
 
static enum GNUNET_GenericReturnValue select_loop (struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
 
void GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Initialize and run scheduler.
 
const struct GNUNET_SCHEDULER_TaskContextGNUNET_SCHEDULER_get_task_context ()
 Obtain the task context, giving the reason why the current task was started.
 
unsigned int GNUNET_SCHEDULER_get_load (enum GNUNET_SCHEDULER_Priority p)
 Get information about the current load of this scheduler.
 
static void init_fd_info (struct GNUNET_SCHEDULER_Task *t, const struct GNUNET_NETWORK_Handle *const *read_nh, unsigned int read_nh_len, const struct GNUNET_NETWORK_Handle *const *write_nh, unsigned int write_nh_len, const struct GNUNET_DISK_FileHandle *const *read_fh, unsigned int read_fh_len, const struct GNUNET_DISK_FileHandle *const *write_fh, unsigned int write_fh_len)
 
static void driver_add_multiple (struct GNUNET_SCHEDULER_Task *t)
 calls the given function func on each FdInfo related to t.
 
static void install_parent_control_handler (void *cls)
 
static void shutdown_pipe_cb (void *cls)
 
void * GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task)
 Cancel the task with the specified identifier.
 
static void init_backtrace (struct GNUNET_SCHEDULER_Task *t)
 Initialize backtrace data for task t.
 
void GNUNET_SCHEDULER_add_with_reason_and_priority (GNUNET_SCHEDULER_TaskCallback task, void *task_cls, enum GNUNET_SCHEDULER_Reason reason, enum GNUNET_SCHEDULER_Priority priority)
 Continue the current execution with the given function.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_at_with_priority (struct GNUNET_TIME_Absolute at, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run at the specified time.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_delayed_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_with_priority (enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified priority.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_at (struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run at the specified time.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_delayed (struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_now (GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run as soon as possible.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_shutdown (GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_now_with_lifeness (int lifeness, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run as soon as possible with the (transitive) ignore-shutdown flag either explicitly set or explicitly enabled.
 
static struct GNUNET_SCHEDULER_Taskadd_without_sets (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_NETWORK_Handle *read_nh, const struct GNUNET_NETWORK_Handle *write_nh, const struct GNUNET_DISK_FileHandle *read_fh, const struct GNUNET_DISK_FileHandle *write_fh, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay or when any of the specified file descriptor sets is ready.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_read_net (struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay or when the specified file descriptor is ready for reading.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_read_net_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified priority and to be run after the specified delay or when the specified file descriptor is ready for reading.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_write_net (struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay or when the specified file descriptor is ready for writing.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_net_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay or when the specified file descriptor is ready.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_read_file (struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay or when the specified file descriptor is ready for reading.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_write_file (struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay or when the specified file descriptor is ready for writing.
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_file_with_priority (struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_DISK_FileHandle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay or when the specified file descriptor is ready.
 
static void extract_handles (const struct GNUNET_NETWORK_FDSet *fdset, const struct GNUNET_NETWORK_Handle ***ntarget, unsigned int *extracted_nhandles, const struct GNUNET_DISK_FileHandle ***ftarget, unsigned int *extracted_fhandles)
 
struct GNUNET_SCHEDULER_TaskGNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
 Schedule a new task to be run with a specified delay or when any of the specified file descriptor sets is ready.
 
void GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
 Function used by event-loop implementations to signal the scheduler that a particular task is ready due to an event specified in the et field of fdi.
 
int GNUNET_SCHEDULER_do_work (struct GNUNET_SCHEDULER_Handle *sh)
 Function called by external event loop implementations to tell the scheduler to run some of the tasks that are ready.
 
struct GNUNET_SCHEDULER_HandleGNUNET_SCHEDULER_driver_init (const struct GNUNET_SCHEDULER_Driver *driver)
 Function called by external event loop implementations to initialize the scheduler.
 
void GNUNET_SCHEDULER_driver_done (struct GNUNET_SCHEDULER_Handle *sh)
 Counter-part of GNUNET_SCHEDULER_driver_init.
 
static int select_add (void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
 
static int select_del (void *cls, struct GNUNET_SCHEDULER_Task *task)
 
static void select_set_wakeup (void *cls, struct GNUNET_TIME_Absolute dt)
 
struct GNUNET_SCHEDULER_DriverGNUNET_SCHEDULER_driver_select ()
 Obtain the driver for using select() as the event loop.
 
void GNUNET_SCHEDULER_begin_async_scope (struct GNUNET_AsyncScopeId *aid)
 Change the async scope for the currently executing task and (transitively) for all tasks scheduled by the current task after calling this function.
 

Variables

static struct GNUNET_SCHEDULER_Task pass_end_marker
 Placed at the end of a ready queue to indicate where a scheduler run pass ends.
 
static const struct GNUNET_SCHEDULER_Driverscheduler_driver
 The driver used for the event loop.
 
static struct GNUNET_SCHEDULER_Taskpending_head
 Head of list of tasks waiting for an event.
 
static struct GNUNET_SCHEDULER_Taskpending_tail
 Tail of list of tasks waiting for an event.
 
static struct GNUNET_SCHEDULER_Taskshutdown_head
 Head of list of tasks waiting for shutdown.
 
static struct GNUNET_SCHEDULER_Taskshutdown_tail
 Tail of list of tasks waiting for shutdown.
 
static struct GNUNET_SCHEDULER_Taskpending_timeout_head
 List of tasks waiting ONLY for a timeout event.
 
static struct GNUNET_SCHEDULER_Taskpending_timeout_tail
 List of tasks waiting ONLY for a timeout event.
 
static struct GNUNET_SCHEDULER_Taskpending_timeout_last
 Last inserted task waiting ONLY for a timeout event.
 
static struct GNUNET_SCHEDULER_Taskactive_task
 ID of the task that is running right now.
 
static struct GNUNET_SCHEDULER_Taskready_head [GNUNET_SCHEDULER_PRIORITY_COUNT]
 Head of list of tasks ready to run right now, grouped by importance.
 
static struct GNUNET_SCHEDULER_Taskready_tail [GNUNET_SCHEDULER_PRIORITY_COUNT]
 Tail of list of tasks ready to run right now, grouped by importance.
 
static struct GNUNET_SCHEDULER_Taskinstall_parent_control_task
 Task for installing parent control handlers (it might happen that the scheduler is shutdown before this task is executed, so GNUNET_SCHEDULER_shutdown must cancel it in that case)
 
static struct GNUNET_SCHEDULER_Taskshutdown_pipe_task
 Task for reading from a pipe that signal handlers will use to initiate shutdown.
 
static unsigned int ready_count
 Number of tasks on the ready list.
 
static enum GNUNET_SCHEDULER_Priority current_priority
 Priority of the task running right now.
 
static enum GNUNET_SCHEDULER_Priority max_priority_added
 Priority of the highest task added in the current select iteration.
 
static int current_lifeness
 Value of the 'lifeness' flag for the current task.
 
static enum GNUNET_SCHEDULER_Priority work_priority
 Priority used currently in GNUNET_SCHEDULER_do_work().
 
static GNUNET_SCHEDULER_select scheduler_select
 Function to use as a select() in the scheduler.
 
static struct GNUNET_SCHEDULER_TaskContext tc
 Task context of the current task.
 
static void * scheduler_select_cls
 Closure for scheduler_select.
 
static struct GNUNET_DISK_PipeHandleshutdown_pipe_handle
 Pipe used to communicate shutdown via signal.
 
static pid_t my_pid
 Process ID of this process at the time we installed the various signal handlers.
 

Detailed Description

main event loop we use for most processes, schedules computations based on time or network events with priorities

Author
Christian Grothoff

Definition in file scheduler.c.

Macro Definition Documentation

◆ EXTRA_DEBUG

#define EXTRA_DEBUG   0

Add debug logging to scheduler that is usually totally excessive.

Definition at line 35 of file scheduler.c.

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__)

Definition at line 37 of file scheduler.c.

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)
Value:
"util-scheduler", \
syscall)
#define GNUNET_log_from_strerror(level, component, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...

Definition at line 39 of file scheduler.c.

87{
93 struct GNUNET_NETWORK_FDSet *rs;
94
100 struct GNUNET_NETWORK_FDSet *ws;
101
105 struct GNUNET_SIGNAL_Context *shc_int;
106
110 struct GNUNET_SIGNAL_Context *shc_term;
111
112#if (SIGTERM != GNUNET_TERM_SIG)
116 struct GNUNET_SIGNAL_Context *shc_gterm;
117#endif
118
122 struct GNUNET_SIGNAL_Context *shc_quit;
123
127 struct GNUNET_SIGNAL_Context *shc_hup;
128
132 struct GNUNET_SIGNAL_Context *shc_pipe;
133};
134
135
140{
145
150
155
159 void *callback_cls;
160
165
172
176 unsigned int fds_len;
177
183 int own_handles;
184
190
191#if PROFILE_DELAYS
196#endif
197
204
209
213 int read_fd;
214
218 int write_fd;
219
224 int lifeness;
225
229 int on_shutdown;
230
234 int in_ready_list;
235
236#if EXECINFO
241 char **backtrace_strings;
242
246 int num_backtrace_strings;
247#endif
248
253};
254
261
262
266struct Scheduled
267{
268 struct Scheduled *prev;
269
270 struct Scheduled *next;
271
276
282
288};
289
290
294struct DriverContext
295{
301
307
313};
314
315
323static const struct GNUNET_SCHEDULER_Driver *scheduler_driver;
324
329
334
339
344
353
362
368
373
377static struct
379
383static struct
385
392
398
402static unsigned int ready_count;
403
409
415
419static int current_lifeness;
420
425
431
435static struct GNUNET_SCHEDULER_TaskContext tc;
436
440static void *scheduler_select_cls;
441
442
450void
452 void *new_select_cls)
453{
454 scheduler_select = new_select;
455 scheduler_select_cls = new_select_cls;
456}
457
458
467{
468 if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
469 return p;
470 GNUNET_assert (0);
471 return 0; /* make compiler happy */
472}
473
474
480static struct GNUNET_TIME_Absolute
482{
483 struct GNUNET_SCHEDULER_Task *pos;
484 struct GNUNET_TIME_Absolute now;
486
490 if (NULL != pos)
491 {
492 if (0 != pos->reason)
493 {
494 return now;
495 }
496 else
497 {
498 timeout = pos->timeout;
499 }
500 }
501 for (pos = pending_head; NULL != pos; pos = pos->next)
502 {
503 if (0 != pos->reason)
504 {
505 return now;
506 }
507 else if ((pos->timeout.abs_value_us !=
508 GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
509 (timeout.abs_value_us > pos->timeout.abs_value_us))
510 {
511 timeout = pos->timeout;
512 }
513 }
514 return timeout;
515}
516
517
518static void
520{
522 {
527 }
528}
529
530
531static void
533{
536 ready_tail[p],
541}
542
543
549static void
551{
553
555 ready_tail[p],
556 task);
557 if (p > work_priority)
560 ready_count++;
561}
562
563
570void
572{
573 struct GNUNET_SCHEDULER_Task *pos;
574
576 "GNUNET_SCHEDULER_shutdown\n");
577 if (NULL != install_parent_control_task)
578 {
581 }
582 if (NULL != shutdown_pipe_task)
583 {
585 shutdown_pipe_task = NULL;
586 }
587 while (NULL != (pos = shutdown_head))
588 {
591 pos);
593 queue_ready_task (pos);
594 }
595}
596
597
603static void
605{
606#if EXECINFO
607 for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
609 "Task %p trace %u: %s\n",
610 t,
611 i,
612 t->backtrace_strings[i]);
613#else
614 (void) t;
615#endif
616}
617
618
624static void
626{
627#if EXTRA_DEBUG
629 "destroying task %p\n",
630 t);
631#endif
632 if (GNUNET_YES == t->own_handles)
633 {
634 for (unsigned int i = 0; i != t->fds_len; ++i)
635 {
636 const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
637 const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
638 if (fd)
639 {
641 (struct GNUNET_NETWORK_Handle *) fd);
642 }
643 if (fh)
644 {
645 // FIXME: on WIN32 this is not enough! A function
646 // GNUNET_DISK_file_free_memory_only would be nice
647 GNUNET_free_nz ((void *) fh);
648 }
649 }
650 }
651 if (t->fds_len > 1)
652 {
654 }
655#if EXECINFO
656 GNUNET_free (t->backtrace_strings);
657#endif
658 GNUNET_free (t);
659}
660
661
666
671static pid_t my_pid;
672
676static void
678{
679 return;
680}
681
682
686static void
688{
689 static char c;
690 int old_errno = errno; /* backup errno */
691
692 if (getpid () != my_pid)
693 _exit (1); /* we have fork'ed since the signal handler was created,
694 * ignore the signal, see https://gnunet.org/vfork discussion */
698 &c, sizeof(c));
699 errno = old_errno;
700}
701
702
703static void
705{
706 struct GNUNET_SCHEDULER_Task *t;
707
708 if (ready_count > 0)
709 return;
710 for (t = pending_head; NULL != t; t = t->next)
711 if (GNUNET_YES == t->lifeness)
712 return;
713 for (t = shutdown_head; NULL != t; t = t->next)
714 if (GNUNET_YES == t->lifeness)
715 return;
716 for (t = pending_timeout_head; NULL != t; t = t->next)
717 if (GNUNET_YES == t->lifeness)
718 return;
719 /* No lifeness! */
721}
722
723
726 struct DriverContext *context);
727
728
729void
731 void *task_cls)
732{
734 struct GNUNET_SCHEDULER_Driver *driver;
735 struct DriverContext context = {
736 .scheduled_head = NULL,
737 .scheduled_tail = NULL,
738 .timeout = GNUNET_TIME_absolute_get ()
739 };
740
742 driver->cls = &context;
745 task_cls,
750 &context));
752 GNUNET_free (driver);
753}
754
755
762const struct GNUNET_SCHEDULER_TaskContext *
764{
765 GNUNET_assert (NULL != active_task);
766 return &tc;
767}
768
769
779unsigned int
781{
782 unsigned int ret;
783
784 GNUNET_assert (NULL != active_task);
786 return ready_count;
789 ret = 0;
790 for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)];
791 NULL != pos;
792 pos = pos->next)
793 ret++;
795 // Don't count the dummy marker
796 ret--;
797 return ret;
798}
799
800
801static void
803 const struct GNUNET_NETWORK_Handle *const *read_nh,
804 unsigned int read_nh_len,
805 const struct GNUNET_NETWORK_Handle *const *write_nh,
806 unsigned int write_nh_len,
807 const struct GNUNET_DISK_FileHandle *const *read_fh,
808 unsigned int read_fh_len,
809 const struct GNUNET_DISK_FileHandle *const *write_fh,
810 unsigned int write_fh_len)
811{
812 // FIXME: if we have exactly two network handles / exactly two file handles
813 // and they are equal, we can make one FdInfo with both
814 // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
815 struct GNUNET_SCHEDULER_FdInfo *fdi;
816
817 t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
818 if (1 == t->fds_len)
819 {
820 fdi = &t->fdx;
821 t->fds = fdi;
822 if (1 == read_nh_len)
823 {
824 GNUNET_assert (NULL != read_nh);
825 GNUNET_assert (NULL != *read_nh);
826 fdi->fd = *read_nh;
828 fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
829 t->read_fd = fdi->sock;
830 t->write_fd = -1;
831 }
832 else if (1 == write_nh_len)
833 {
834 GNUNET_assert (NULL != write_nh);
835 GNUNET_assert (NULL != *write_nh);
836 fdi->fd = *write_nh;
838 fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
839 t->read_fd = -1;
840 t->write_fd = fdi->sock;
841 }
842 else if (1 == read_fh_len)
843 {
844 GNUNET_assert (NULL != read_fh);
845 GNUNET_assert (NULL != *read_fh);
846 fdi->fh = *read_fh;
848 fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
849 t->read_fd = fdi->sock;
850 t->write_fd = -1;
851 }
852 else
853 {
854 GNUNET_assert (NULL != write_fh);
855 GNUNET_assert (NULL != *write_fh);
856 fdi->fh = *write_fh;
858 fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
859 t->read_fd = -1;
860 t->write_fd = fdi->sock;
861 }
862 }
863 else
864 {
866 t->fds = fdi;
867 t->read_fd = -1;
868 t->write_fd = -1;
869 for (int i = 0; i != read_nh_len; ++i)
870 {
871 fdi->fd = read_nh[i];
872 GNUNET_assert (NULL != fdi->fd);
874 fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
875 ++fdi;
876 }
877 for (int i = 0; i != write_nh_len; ++i)
878 {
879 fdi->fd = write_nh[i];
880 GNUNET_assert (NULL != fdi->fd);
882 fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
883 ++fdi;
884 }
885 for (int i = 0; i != read_fh_len; ++i)
886 {
887 fdi->fh = read_fh[i];
888 GNUNET_assert (NULL != fdi->fh);
890 fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
891 ++fdi;
892 }
893 for (int i = 0; i != write_fh_len; ++i)
894 {
895 fdi->fh = write_fh[i];
896 GNUNET_assert (NULL != fdi->fh);
898 fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
899 ++fdi;
900 }
901 }
902}
903
904
918static void
920{
921 struct GNUNET_SCHEDULER_FdInfo *fdi;
922 int success = GNUNET_YES;
923
924 for (unsigned int i = 0; i != t->fds_len; ++i)
925 {
926 fdi = &t->fds[i];
928 t,
929 fdi) && success;
931 }
932 if (GNUNET_YES != success)
933 {
935 "driver could not add task\n");
936 }
937}
938
939
940static void
942{
943 (void) cls;
946}
947
948
949static void
950shutdown_pipe_cb (void *cls)
951{
952 char c;
953 const struct GNUNET_DISK_FileHandle *pr;
954
955 (void) cls;
956 shutdown_pipe_task = NULL;
960 /* consume the signal */
961 GNUNET_DISK_file_read (pr, &c, sizeof(c));
962 /* mark all active tasks as ready due to shutdown */
966 pr,
968 NULL);
969}
970
971
984void *
986{
988 int is_fd_task;
989 void *ret;
990
992 "canceling task %p\n",
993 task);
994
995 /* scheduler must be running */
997 is_fd_task = (NULL != task->fds);
998 if (is_fd_task)
999 {
1000 int del_result = scheduler_driver->del (scheduler_driver->cls, task);
1001 if (GNUNET_OK != del_result)
1002 {
1004 "driver could not delete task\n");
1005 GNUNET_assert (0);
1006 }
1007 }
1008 if (! task->in_ready_list)
1009 {
1010 if (is_fd_task)
1011 {
1014 task);
1015 }
1016 else if (GNUNET_YES == task->on_shutdown)
1017 {
1020 task);
1021 }
1022 else
1023 {
1026 task);
1027 if (pending_timeout_last == task)
1028 pending_timeout_last = NULL;
1029 }
1030 }
1031 else
1032 {
1033 p = check_priority (task->priority);
1035 ready_tail[p],
1036 task);
1037 ready_count--;
1038 }
1039 ret = task->callback_cls;
1040 destroy_task (task);
1041 return ret;
1042}
1043
1044
1050static void
1052{
1053#if EXECINFO
1054 void *backtrace_array[MAX_TRACE_DEPTH];
1055
1056 t->num_backtrace_strings
1057 = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1058 t->backtrace_strings =
1059 backtrace_symbols (backtrace_array,
1060 t->num_backtrace_strings);
1061 dump_backtrace (t);
1062#else
1063 (void) t;
1064#endif
1065}
1066
1067
1078void
1080 task,
1081 void *task_cls,
1083 reason,
1085 priority)
1086{
1087 struct GNUNET_SCHEDULER_Task *t;
1088
1089 /* scheduler must be running */
1091 GNUNET_assert (NULL != task);
1093 t->read_fd = -1;
1094 t->write_fd = -1;
1095 t->callback = task;
1096 t->callback_cls = task_cls;
1097#if PROFILE_DELAYS
1098 t->start_time = GNUNET_TIME_absolute_get ();
1099#endif
1100 t->reason = reason;
1104 "Adding continuation task %p\n",
1105 t);
1106 init_backtrace (t);
1108}
1109
1110
1122struct GNUNET_SCHEDULER_Task *
1126 void *task_cls)
1127{
1128 struct GNUNET_SCHEDULER_Task *t;
1129 struct GNUNET_SCHEDULER_Task *pos;
1131 struct GNUNET_TIME_Relative left;
1132
1133 /* scheduler must be running */
1135 GNUNET_assert (NULL != task);
1138 t->callback = task;
1139 t->callback_cls = task_cls;
1140 t->read_fd = -1;
1141 t->write_fd = -1;
1142#if PROFILE_DELAYS
1143 t->start_time = GNUNET_TIME_absolute_get ();
1144#endif
1145 t->timeout = at;
1146 t->priority = check_priority (priority);
1148 init_backtrace (t);
1149
1151 if (0 == left.rel_value_us)
1152 {
1154 if (priority > work_priority)
1155 work_priority = priority;
1156 return t;
1157 }
1158
1159 /* try tail first (optimization in case we are
1160 * appending to a long list of tasks with timeouts) */
1161 if ((NULL == pending_timeout_head) ||
1163 {
1166 t);
1167 }
1168 else
1169 {
1170 /* first move from heuristic start backwards to before start time */
1171 prev = pending_timeout_last;
1172 while ((NULL != prev) &&
1174 prev = prev->prev;
1175 /* now, move from heuristic start (or head of list) forward to insertion point */
1176 if (NULL == prev)
1178 else
1179 pos = prev->next;
1180 while ((NULL != pos) && (pos->timeout.abs_value_us <=
1182 {
1183 prev = pos;
1184 pos = pos->next;
1185 }
1188 prev,
1189 t);
1190 }
1191 /* finally, update heuristic insertion point to last insertion... */
1194 "Adding task %p\n",
1195 t);
1196 return t;
1197}
1198
1199
1211struct GNUNET_SCHEDULER_Task *
1214 priority,
1216 void *task_cls)
1217{
1220 priority,
1221 task,
1222 task_cls);
1223}
1224
1225
1235struct GNUNET_SCHEDULER_Task *
1238 void *task_cls)
1239{
1241 prio,
1242 task,
1243 task_cls);
1244}
1245
1246
1258struct GNUNET_SCHEDULER_Task *
1261 void *task_cls)
1262{
1265 task,
1266 task_cls);
1267}
1268
1269
1281struct GNUNET_SCHEDULER_Task *
1284 void *task_cls)
1285{
1288 task,
1289 task_cls);
1290}
1291
1292
1308struct GNUNET_SCHEDULER_Task *
1310 void *task_cls)
1311{
1312 struct GNUNET_SCHEDULER_Task *t;
1313
1316 t->callback = task;
1317 t->callback_cls = task_cls;
1318 t->read_fd = -1;
1319 t->write_fd = -1;
1320#if PROFILE_DELAYS
1321 t->start_time = GNUNET_TIME_absolute_get ();
1322#endif
1328 init_backtrace (t);
1329 return t;
1330}
1331
1332
1343struct GNUNET_SCHEDULER_Task *
1345 void *task_cls)
1346{
1347 struct GNUNET_SCHEDULER_Task *t;
1348
1349 /* scheduler must be running */
1351 GNUNET_assert (NULL != task);
1354 t->callback = task;
1355 t->callback_cls = task_cls;
1356 t->read_fd = -1;
1357 t->write_fd = -1;
1358#if PROFILE_DELAYS
1359 t->start_time = GNUNET_TIME_absolute_get ();
1360#endif
1364 t->lifeness = GNUNET_NO;
1367 t);
1369 "Adding shutdown task %p\n",
1370 t);
1371 init_backtrace (t);
1372 return t;
1373}
1374
1375
1376struct GNUNET_SCHEDULER_Task *
1379 void *task_cls)
1380{
1381 struct GNUNET_SCHEDULER_Task *ret;
1382
1383 ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1384 ret->lifeness = lifeness;
1385 return ret;
1386}
1387
1388
1389#if DEBUG_FDS
1396void
1397check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1398{
1399 if (-1 != raw_fd)
1400 {
1401 int flags = fcntl (raw_fd, F_GETFD);
1402
1403 if ((flags == -1) && (errno == EBADF))
1404 {
1406 "Got invalid file descriptor %d!\n",
1407 raw_fd);
1408 init_backtrace (t);
1409 GNUNET_assert (0);
1410 }
1411 }
1412}
1413
1414
1415#endif
1416
1417
1443static struct GNUNET_SCHEDULER_Task *
1446 const struct GNUNET_NETWORK_Handle *read_nh,
1447 const struct GNUNET_NETWORK_Handle *write_nh,
1448 const struct GNUNET_DISK_FileHandle *read_fh,
1449 const struct GNUNET_DISK_FileHandle *write_fh,
1451 void *task_cls)
1452{
1453 struct GNUNET_SCHEDULER_Task *t;
1454
1455 /* scheduler must be running */
1457 GNUNET_assert (NULL != task);
1460 init_fd_info (t,
1461 &read_nh,
1462 read_nh ? 1 : 0,
1463 &write_nh,
1464 write_nh ? 1 : 0,
1465 &read_fh,
1466 read_fh ? 1 : 0,
1467 &write_fh,
1468 write_fh ? 1 : 0);
1469 t->callback = task;
1470 t->callback_cls = task_cls;
1471#if DEBUG_FDS
1472 check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1473 check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1474 check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1475 check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1476#endif
1477#if PROFILE_DELAYS
1478 t->start_time = GNUNET_TIME_absolute_get ();
1479#endif
1486 t);
1489 t->priority);
1490 init_backtrace (t);
1491 return t;
1492}
1493
1494
1515struct GNUNET_SCHEDULER_Task *
1517 struct GNUNET_NETWORK_Handle *rfd,
1519 void *task_cls)
1520{
1523 rfd, task, task_cls);
1524}
1525
1526
1549struct GNUNET_SCHEDULER_Task *
1552 priority,
1553 struct GNUNET_NETWORK_Handle *rfd,
1555 void *task_cls)
1556{
1558 rfd,
1559 GNUNET_YES,
1560 GNUNET_NO,
1561 task, task_cls);
1562}
1563
1564
1586struct GNUNET_SCHEDULER_Task *
1588 struct GNUNET_NETWORK_Handle *wfd,
1590 void *task_cls)
1591{
1594 wfd,
1596 task, task_cls);
1597}
1598
1599
1623struct GNUNET_SCHEDULER_Task *
1626 struct GNUNET_NETWORK_Handle *fd,
1627 int on_read,
1628 int on_write,
1630 void *task_cls)
1631{
1632 /* scheduler must be running */
1634 GNUNET_assert (on_read || on_write);
1636 return add_without_sets (delay, priority,
1637 on_read ? fd : NULL,
1638 on_write ? fd : NULL,
1639 NULL,
1640 NULL,
1641 task, task_cls);
1642}
1643
1644
1665struct GNUNET_SCHEDULER_Task *
1667 const struct GNUNET_DISK_FileHandle *rfd,
1669 void *task_cls)
1670{
1673 rfd, GNUNET_YES, GNUNET_NO,
1674 task, task_cls);
1675}
1676
1677
1698struct GNUNET_SCHEDULER_Task *
1700 const struct GNUNET_DISK_FileHandle *wfd,
1702 void *task_cls)
1703{
1706 wfd, GNUNET_NO, GNUNET_YES,
1707 task, task_cls);
1708}
1709
1710
1734struct GNUNET_SCHEDULER_Task *
1737 priority,
1738 const struct
1740 int on_read, int on_write,
1742 void *task_cls)
1743{
1744 /* scheduler must be running */
1746 GNUNET_assert (on_read || on_write);
1747 GNUNET_assert (fd->fd >= 0);
1748 return add_without_sets (delay, priority,
1749 NULL,
1750 NULL,
1751 on_read ? fd : NULL,
1752 on_write ? fd : NULL,
1753 task, task_cls);
1754}
1755
1756
1757static void
1758extract_handles (const struct GNUNET_NETWORK_FDSet *fdset,
1759 const struct GNUNET_NETWORK_Handle ***ntarget,
1760 unsigned int *extracted_nhandles,
1761 const struct GNUNET_DISK_FileHandle ***ftarget,
1762 unsigned int *extracted_fhandles)
1763{
1764 // FIXME: this implementation only works for unix, for WIN32 the file handles
1765 // in fdset must be handled separately
1766 const struct GNUNET_NETWORK_Handle **nhandles;
1767 const struct GNUNET_DISK_FileHandle **fhandles;
1768 unsigned int nhandles_len;
1769 unsigned int fhandles_len;
1770
1771 nhandles = NULL;
1772 fhandles = NULL;
1773 nhandles_len = 0;
1774 fhandles_len = 0;
1775 for (int sock = 0; sock != fdset->nsds; ++sock)
1776 {
1777 if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1778 {
1779 struct GNUNET_NETWORK_Handle *nhandle;
1780 struct GNUNET_DISK_FileHandle *fhandle;
1781
1782 nhandle = GNUNET_NETWORK_socket_box_native (sock);
1783 if (NULL != nhandle)
1784 {
1785 GNUNET_array_append (nhandles, nhandles_len, nhandle);
1786 }
1787 else
1788 {
1789 fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1790 if (NULL != fhandle)
1791 {
1792 GNUNET_array_append (fhandles, fhandles_len, fhandle);
1793 }
1794 else
1795 {
1796 GNUNET_assert (0);
1797 }
1798 }
1799 }
1800 }
1801 *ntarget = nhandles_len > 0 ? nhandles : NULL;
1802 *ftarget = fhandles_len > 0 ? fhandles : NULL;
1803 *extracted_nhandles = nhandles_len;
1804 *extracted_fhandles = fhandles_len;
1805}
1806
1807
1839struct GNUNET_SCHEDULER_Task *
1841 struct GNUNET_TIME_Relative delay,
1842 const struct GNUNET_NETWORK_FDSet *rs,
1843 const struct GNUNET_NETWORK_FDSet *ws,
1845 void *task_cls)
1846{
1847 struct GNUNET_SCHEDULER_Task *t;
1848 const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1849 const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1850 const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1851 const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1852 unsigned int read_nhandles_len = 0;
1853 unsigned int write_nhandles_len = 0;
1854 unsigned int read_fhandles_len = 0;
1855 unsigned int write_fhandles_len = 0;
1856 int no_rs = (NULL == rs);
1857 int no_ws = (NULL == ws);
1858 int empty_rs = (NULL != rs) && (0 == rs->nsds);
1859 int empty_ws = (NULL != ws) && (0 == ws->nsds);
1860 int no_fds = (no_rs && no_ws) ||
1861 (empty_rs && empty_ws) ||
1862 (no_rs && empty_ws) ||
1863 (no_ws && empty_rs);
1864 int no_fds_extracted;
1865
1866 /* scheduler must be running */
1868 GNUNET_assert (NULL != task);
1869 if (! no_fds)
1870 {
1871 if (NULL != rs)
1872 {
1873 extract_handles (rs,
1874 &read_nhandles,
1875 &read_nhandles_len,
1876 &read_fhandles,
1877 &read_fhandles_len);
1878 }
1879 if (NULL != ws)
1880 {
1881 extract_handles (ws,
1882 &write_nhandles,
1883 &write_nhandles_len,
1884 &write_fhandles,
1885 &write_fhandles_len);
1886 }
1887 }
1895 no_fds_extracted = (0 == read_nhandles_len) &&
1896 (0 == read_fhandles_len) &&
1897 (0 == write_nhandles_len) &&
1898 (0 == write_fhandles_len);
1899 if (no_fds || no_fds_extracted)
1901 prio,
1902 task,
1903 task_cls);
1906 init_fd_info (t,
1907 read_nhandles,
1908 read_nhandles_len,
1909 write_nhandles,
1910 write_nhandles_len,
1911 read_fhandles,
1912 read_fhandles_len,
1913 write_fhandles,
1914 write_fhandles_len);
1915 t->callback = task;
1916 t->callback_cls = task_cls;
1918 /* free the arrays of pointers to network / file handles, the actual
1919 * handles will be freed in destroy_task */
1920 GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1921 GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1922 GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1923 GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1924#if PROFILE_DELAYS
1925 t->start_time = GNUNET_TIME_absolute_get ();
1926#endif
1928 t->priority =
1929 check_priority ((prio ==
1931 prio);
1935 t);
1938 t->priority);
1940 "Adding task %p\n",
1941 t);
1942 init_backtrace (t);
1943 return t;
1944}
1945
1946
1958void
1960 struct GNUNET_SCHEDULER_FdInfo *fdi)
1961{
1962 enum GNUNET_SCHEDULER_Reason reason;
1963
1964 reason = task->reason;
1965 if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1966 (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1968 if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1969 (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1972 task->reason = reason;
1973 if (GNUNET_NO == task->in_ready_list)
1974 {
1977 task);
1978 queue_ready_task (task);
1979 }
1980}
1981
1982
2003int
2005{
2006 struct GNUNET_SCHEDULER_Task *pos;
2007 struct GNUNET_TIME_Absolute now;
2008
2009 /* check for tasks that reached the timeout! */
2010 now = GNUNET_TIME_absolute_get ();
2012 while (NULL != pos)
2013 {
2014 struct GNUNET_SCHEDULER_Task *next = pos->next;
2015 if (now.abs_value_us >= pos->timeout.abs_value_us)
2017 if (0 == pos->reason)
2018 break;
2021 pos);
2022 if (pending_timeout_last == pos)
2023 pending_timeout_last = NULL;
2024 queue_ready_task (pos);
2025 pos = next;
2026 }
2027 pos = pending_head;
2028 while (NULL != pos)
2029 {
2030 struct GNUNET_SCHEDULER_Task *next = pos->next;
2031 if (now.abs_value_us >= pos->timeout.abs_value_us)
2032 {
2036 pos);
2037 queue_ready_task (pos);
2038 }
2039 pos = next;
2040 }
2041
2042 if (0 == ready_count)
2043 {
2045
2046 if (timeout.abs_value_us > now.abs_value_us)
2047 {
2062 "GNUNET_SCHEDULER_do_work did not find any ready "
2063 "tasks and timeout has not been reached yet.\n");
2064 }
2065 else
2066 {
2071 GNUNET_assert (0);
2072 }
2073 }
2074 else
2075 {
2076 /* find out which task priority level we are going to
2077 process this time */
2080 /* yes, p>0 is correct, 0 is "KEEP" which should
2081 * always be an empty queue (see assertion)! */
2083 work_priority > 0;
2084 work_priority--)
2085 {
2087 if (NULL != pos)
2088 break;
2089 }
2090 GNUNET_assert (NULL != pos); /* ready_count wrong? */
2091
2092 /* process all *existing* tasks at this priority
2093 level, then yield */
2095 while (NULL != (pos = ready_head[work_priority])
2096 && pos != &pass_end_marker)
2097 {
2100 pos);
2101 ready_count--;
2104 active_task = pos;
2105#if PROFILE_DELAYS
2106 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2107 DELAY_THRESHOLD.rel_value_us)
2108 {
2110 "Task %p took %s to be scheduled\n",
2111 pos,
2113 GNUNET_TIME_absolute_get_duration (pos->start_time),
2114 GNUNET_YES));
2115 }
2116#endif
2117 tc.reason = pos->reason;
2120 // FIXME: do we have to remove FdInfos from fds if they are not ready?
2121 tc.fds_len = pos->fds_len;
2122 tc.fds = pos->fds;
2123 for (unsigned int i = 0; i != pos->fds_len; ++i)
2124 {
2125 struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2126 if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2127 {
2129 fdi->sock);
2130 }
2131 if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2132 {
2134 fdi->sock);
2135 }
2136 }
2137 tc.read_ready = sh->rs;
2138 tc.write_ready = sh->ws;
2139#if EXTRA_DEBUG
2141 "Running task %p\n",
2142 pos);
2143#endif
2144 GNUNET_assert (NULL != pos->callback);
2145 {
2146 struct GNUNET_AsyncScopeSave old_scope;
2147 if (pos->scope.have_scope)
2148 GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2149 else
2150 GNUNET_async_scope_get (&old_scope);
2151 pos->callback (pos->callback_cls);
2152 GNUNET_async_scope_restore (&old_scope);
2153 }
2154 if (NULL != pos->fds)
2155 {
2156 int del_result = scheduler_driver->del (scheduler_driver->cls,
2157 pos);
2158 if (GNUNET_OK != del_result)
2159 {
2161 "driver could not delete task %p\n", pos);
2162 GNUNET_assert (0);
2163 }
2164 }
2165 active_task = NULL;
2166 dump_backtrace (pos);
2167 destroy_task (pos);
2168 }
2170 }
2172 if (0 == ready_count)
2173 {
2175 get_timeout ());
2176 return GNUNET_NO;
2177 }
2180 return GNUNET_YES;
2181}
2182
2183
2217{
2219 const struct GNUNET_DISK_FileHandle *pr;
2220
2221 /* scheduler must not be running */
2224 /* general set-up */
2230 my_pid = getpid ();
2231 scheduler_driver = driver;
2232
2233 /* install signal handlers */
2235 "Registering signal handlers\n");
2236 sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2238 sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2240#if (SIGTERM != GNUNET_TERM_SIG)
2243#endif
2244 sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2246 sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2248 sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2250
2251 /* Setup initial tasks */
2254 /* ensure this task runs first, by using a priority level reserved for
2255 the scheduler (not really shutdown, but start-up ;-) */
2259 NULL);
2262 pr,
2264 NULL);
2267 get_timeout ());
2268 /* begin main event loop */
2272 return sh;
2273}
2274
2275
2290void
2292{
2293 GNUNET_break (NULL == pending_head);
2295 GNUNET_break (NULL == shutdown_head);
2296 for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2297 {
2298 GNUNET_break (NULL == ready_head[i]);
2299 }
2302
2303 /* uninstall signal handlers */
2306#if (SIGTERM != GNUNET_TERM_SIG)
2308#endif
2313 shutdown_pipe_handle = NULL;
2314 scheduler_driver = NULL;
2315 GNUNET_free (sh);
2316}
2317
2318
2319static enum GNUNET_GenericReturnValue
2321 struct DriverContext *context)
2322{
2323 struct GNUNET_NETWORK_FDSet *rs;
2324 struct GNUNET_NETWORK_FDSet *ws;
2325 int select_result;
2326
2327 GNUNET_assert (NULL != context);
2330 while ((NULL != context->scheduled_head) ||
2331 (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2332 context->timeout.abs_value_us))
2333 {
2334 struct GNUNET_TIME_Relative time_remaining;
2335
2336#if EXTRA_DEBUG
2338 "select timeout = %s\n",
2340#endif
2343
2344 for (struct Scheduled *pos = context->scheduled_head;
2345 NULL != pos;
2346 pos = pos->next)
2347 {
2348 if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2349 {
2350 GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2351 }
2352 if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2353 {
2354 GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2355 }
2356 }
2357 time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2358 if (0 < ready_count)
2359 time_remaining = GNUNET_TIME_UNIT_ZERO;
2360 if (NULL == scheduler_select)
2361 {
2362 select_result = GNUNET_NETWORK_socket_select (rs,
2363 ws,
2364 NULL,
2365 time_remaining);
2366 }
2367 else
2368 {
2369 select_result = scheduler_select (scheduler_select_cls,
2370 rs,
2371 ws,
2372 NULL,
2373 time_remaining);
2374 }
2375 if (select_result == GNUNET_SYSERR)
2376 {
2377 if (errno == EINTR)
2378 continue;
2379
2381 "select");
2382#if USE_LSOF
2383 char lsof[512];
2384
2385 snprintf (lsof,
2386 sizeof(lsof),
2387 "lsof -p %d",
2388 getpid ());
2389 (void) close (1);
2390 (void) dup2 (2, 1);
2391 if (0 != system (lsof))
2393 "system");
2394#endif
2395#if DEBUG_FDS
2396 for (struct Scheduled *s = context->scheduled_head;
2397 NULL != s;
2398 s = s->next)
2399 {
2400 int flags = fcntl (s->fdi->sock,
2401 F_GETFD);
2402
2403 if ((flags == -1) &&
2404 (EBADF == errno))
2405 {
2407 "Got invalid file descriptor %d!\n",
2408 s->fdi->sock);
2409#if EXECINFO
2410 dump_backtrace (s->task);
2411#endif
2412 }
2413 }
2414#endif
2415 GNUNET_assert (0);
2418 return GNUNET_SYSERR;
2419 }
2420 if (select_result > 0)
2421 {
2422 for (struct Scheduled *pos = context->scheduled_head;
2423 NULL != pos;
2424 pos = pos->next)
2425 {
2426 int is_ready = GNUNET_NO;
2427
2428 if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2429 (GNUNET_YES ==
2431 pos->fdi->sock)) )
2432 {
2433 pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2434 is_ready = GNUNET_YES;
2435 }
2436 if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2437 (GNUNET_YES ==
2439 pos->fdi->sock)) )
2440 {
2441 pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2442 is_ready = GNUNET_YES;
2443 }
2444 if (GNUNET_YES == is_ready)
2445 {
2446 GNUNET_SCHEDULER_task_ready (pos->task,
2447 pos->fdi);
2448 }
2449 }
2450 }
2452 {
2453#if EXTRA_DEBUG
2455 "scheduler has more tasks ready!\n");
2456#endif
2457 }
2458 }
2461
2462 if ( (NULL == context->scheduled_head) &&
2463 (NULL != pending_timeout_head) &&
2464 (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us ==
2465 context->timeout.abs_value_us) )
2466 {
2467 /* Only remaining task has timeout of 'forever'.
2468 We exit here more as sanity measure, as just
2469 waiting forever isn't exactly useful. Still,
2470 this is indicative of a bug in the client code. */
2471 GNUNET_break (0);
2472 return GNUNET_NO;
2473 }
2474 return GNUNET_OK;
2475}
2476
2477
2478static int
2479select_add (void *cls,
2480 struct GNUNET_SCHEDULER_Task *task,
2481 struct GNUNET_SCHEDULER_FdInfo *fdi)
2482{
2483 struct DriverContext *context = cls;
2484 struct Scheduled *scheduled;
2485
2486 GNUNET_assert (NULL != context);
2487 GNUNET_assert (NULL != task);
2488 GNUNET_assert (NULL != fdi);
2490 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2491
2492 if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2493 {
2494 /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2495 return GNUNET_SYSERR;
2496 }
2497
2498 scheduled = GNUNET_new (struct Scheduled);
2499 scheduled->task = task;
2500 scheduled->fdi = fdi;
2501 scheduled->et = fdi->et;
2502
2503 GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2504 context->scheduled_tail,
2505 scheduled);
2506 return GNUNET_OK;
2507}
2508
2509
2510static int
2511select_del (void *cls,
2513{
2514 struct DriverContext *context;
2515 struct Scheduled *pos;
2516 int ret;
2517
2518 GNUNET_assert (NULL != cls);
2519
2520 context = cls;
2522 pos = context->scheduled_head;
2523 while (NULL != pos)
2524 {
2525 struct Scheduled *next = pos->next;
2526 if (pos->task == task)
2527 {
2528 GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2529 context->scheduled_tail,
2530 pos);
2531 GNUNET_free (pos);
2532 ret = GNUNET_OK;
2533 }
2534 pos = next;
2535 }
2536 return ret;
2537}
2538
2539
2540static void
2541select_set_wakeup (void *cls,
2542 struct GNUNET_TIME_Absolute dt)
2543{
2544 struct DriverContext *context = cls;
2545
2546 GNUNET_assert (NULL != context);
2547 context->timeout = dt;
2548}
2549
2550
2558{
2559 struct GNUNET_SCHEDULER_Driver *select_driver;
2560
2561 select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2562
2563 select_driver->add = &select_add;
2564 select_driver->del = &select_del;
2565 select_driver->set_wakeup = &select_set_wakeup;
2566
2567 return select_driver;
2568}
2569
2570
2583void
2585{
2586 struct GNUNET_AsyncScopeSave dummy_old_scope;
2587
2588 GNUNET_assert (NULL != active_task);
2589 /* Since we're in a task, the context will be automatically
2590 restored by the scheduler. */
2591 GNUNET_async_scope_enter (aid, &dummy_old_scope);
2592}
2593
2594
2595/* end of scheduler.c */
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition gnunet-arm.c:118
static struct GNUNET_TIME_Absolute start_time
Start time of the current round; used to determine how long one iteration takes (which influences how...
static pa_context * context
Pulseaudio context.
static struct GNUNET_IDENTITY_Handle * sh
Handle to IDENTITY service.
static struct GNUNET_SCHEDULER_Task * t
Main task.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition gnunet-uri.c:38
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition disk.c:1702
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition disk.c:745
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition disk.c:1523
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition disk.c:1670
enum GNUNET_GenericReturnValue GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition disk.c:199
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition disk.c:1409
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition disk.c:704
@ GNUNET_DISK_PF_NONE
No special options, use non-blocking read/write operations.
@ GNUNET_DISK_PIPE_END_WRITE
The writing-end of a pipe.
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_MAX(a, b)
GNUNET_SCHEDULER_Priority
Valid task priorities.
void GNUNET_async_scope_enter(const struct GNUNET_AsyncScopeId *aid, struct GNUNET_AsyncScopeSave *old_scope)
Set the async scope for the current thread.
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
void GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
Get the current async scope.
void GNUNET_async_scope_restore(struct GNUNET_AsyncScopeSave *old_scope)
Clear the current thread's async scope.
GNUNET_GenericReturnValue
Named constants for return values.
struct GNUNET_AsyncScopeId scope_id
Saved scope.
@ GNUNET_SCHEDULER_PRIORITY_COUNT
Number of priorities (must be the last priority).
@ GNUNET_SCHEDULER_PRIORITY_KEEP
Run with the same priority as the current job.
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
@ GNUNET_SCHEDULER_PRIORITY_SHUTDOWN
This is an internal priority level that is only used for tasks that are being triggered due to shutdo...
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_free_nz(ptr)
Wrapper around free.
void GNUNET_NETWORK_fdset_zero(struct GNUNET_NETWORK_FDSet *fds)
Reset FD set (clears all file descriptors).
Definition network.c:918
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition network.c:1185
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition network.c:1001
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition network.c:1169
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native(int fd)
Box a native socket (and check that it is a socket).
Definition network.c:580
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition network.c:1058
int GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to, int nfd)
Test native fd in a set.
Definition network.c:1076
void GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
Only free memory of a socket, keep the file descriptor untouched.
Definition network.c:566
int GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, struct GNUNET_TIME_Relative timeout)
Check if sockets meet certain conditions.
Definition network.c:1259
void GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_DISK_FileHandle *h)
Add a file handle to the fd set.
Definition network.c:1092
void GNUNET_OS_install_parent_control_handler(void *cls)
Connects this process to its parent via pipe; essentially, the parent control handler will read signa...
void GNUNET_SCHEDULER_shutdown()
Request the shutdown of a scheduler.
Definition scheduler.c:572
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1517
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now_with_lifeness(int lifeness, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible with the (transitive) ignore-shutdown flag either e...
Definition scheduler.c:1378
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition scheduler.c:731
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1700
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition scheduler.c:2292
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority and to be run after the specified delay or wh...
Definition scheduler.c:1551
void GNUNET_SCHEDULER_task_ready(struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Function used by event-loop implementations to signal the scheduler that a particular task is ready d...
Definition scheduler.c:1960
void GNUNET_SCHEDULER_add_with_reason_and_priority(GNUNET_SCHEDULER_TaskCallback task, void *task_cls, enum GNUNET_SCHEDULER_Reason reason, enum GNUNET_SCHEDULER_Priority priority)
Continue the current execution with the given function.
Definition scheduler.c:1080
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1667
int GNUNET_SCHEDULER_do_work(struct GNUNET_SCHEDULER_Handle *sh)
Function called by external event loop implementations to tell the scheduler to run some of the tasks...
Definition scheduler.c:2005
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1588
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition scheduler.c:1841
unsigned int GNUNET_SCHEDULER_get_load(enum GNUNET_SCHEDULER_Priority p)
Get information about the current load of this scheduler.
Definition scheduler.c:781
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context()
Obtain the task context, giving the reason why the current task was started.
Definition scheduler.c:764
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_file_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_DISK_FileHandle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready.
Definition scheduler.c:1736
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1260
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition scheduler.c:1345
struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select()
Obtain the driver for using select() as the event loop.
Definition scheduler.c:2558
void GNUNET_SCHEDULER_begin_async_scope(struct GNUNET_AsyncScopeId *aid)
Change the async scope for the currently executing task and (transitively) for all tasks scheduled by...
Definition scheduler.c:2585
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
void GNUNET_SCHEDULER_set_select(GNUNET_SCHEDULER_select new_select, void *new_select_cls)
Sets the select function to use in the scheduler (scheduler_select).
Definition scheduler.c:452
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1310
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_net_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready.
Definition scheduler.c:1625
GNUNET_SCHEDULER_Reason
Reasons why the schedule may have triggered the task now.
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1213
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at_with_priority(struct GNUNET_TIME_Absolute at, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition scheduler.c:1124
struct GNUNET_SCHEDULER_Handle * GNUNET_SCHEDULER_driver_init(const struct GNUNET_SCHEDULER_Driver *driver)
Function called by external event loop implementations to initialize the scheduler.
Definition scheduler.c:2217
GNUNET_SCHEDULER_EventType
Possible events on FDs, used as a bitmask.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition scheduler.c:1237
int(* GNUNET_SCHEDULER_select)(void *cls, struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, struct GNUNET_TIME_Relative timeout)
Signature of the select function used by the scheduler.
@ GNUNET_SCHEDULER_REASON_TIMEOUT
The specified timeout has expired.
@ GNUNET_SCHEDULER_REASON_READ_READY
The reading socket is ready.
@ GNUNET_SCHEDULER_REASON_SHUTDOWN
We are shutting down and are running all shutdown-related tasks.
@ GNUNET_SCHEDULER_REASON_STARTUP
This is the very first task run during startup.
@ GNUNET_SCHEDULER_REASON_WRITE_READY
The writing socket is ready.
@ GNUNET_SCHEDULER_REASON_PREREQ_DONE
The prerequisite task is done.
@ GNUNET_SCHEDULER_ET_OUT
Buffer available for writing.
@ GNUNET_SCHEDULER_ET_NONE
No event (useful for timeout).
@ GNUNET_SCHEDULER_ET_IN
Data available for reading.
struct GNUNET_SIGNAL_Context * GNUNET_SIGNAL_handler_install(int signal, GNUNET_SIGNAL_Handler handler)
Install a signal handler that will be run if the given signal is received.
Definition signal.c:52
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal handler.
Definition signal.c:78
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition time.c:438
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:604
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition strings.c:665
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TERM_SIG
The termination signal.
Definition platform.h:235
static void sighandler_pipe()
Signal handler called for SIGPIPE.
Definition scheduler.c:678
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition scheduler.c:605
static void driver_add_multiple(struct GNUNET_SCHEDULER_Task *t)
calls the given function func on each FdInfo related to t.
Definition scheduler.c:920
static struct GNUNET_SCHEDULER_Task * shutdown_pipe_task
Task for reading from a pipe that signal handlers will use to initiate shutdown.
Definition scheduler.c:398
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition scheduler.c:2542
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition scheduler.c:626
static enum GNUNET_SCHEDULER_Priority check_priority(enum GNUNET_SCHEDULER_Priority p)
Check that the given priority is legal (and return it).
Definition scheduler.c:467
static void queue_ready_task(struct GNUNET_SCHEDULER_Task *task)
Put a task that is ready for execution into the ready queue.
Definition scheduler.c:551
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition scheduler.c:2512
static struct GNUNET_SCHEDULER_Task * install_parent_control_task
Task for installing parent control handlers (it might happen that the scheduler is shutdown before th...
Definition scheduler.c:392
static struct GNUNET_SCHEDULER_Task * active_task
ID of the task that is running right now.
Definition scheduler.c:373
static struct GNUNET_SCHEDULER_Task * ready_tail[GNUNET_SCHEDULER_PRIORITY_COUNT]
Tail of list of tasks ready to run right now, grouped by importance.
Definition scheduler.c:384
static enum GNUNET_SCHEDULER_Priority current_priority
Priority of the task running right now.
Definition scheduler.c:409
static struct GNUNET_SCHEDULER_Task * pending_head
Head of list of tasks waiting for an event.
Definition scheduler.c:329
static struct GNUNET_TIME_Absolute get_timeout()
chooses the nearest timeout from all pending tasks, to be used to tell the driver the next wakeup tim...
Definition scheduler.c:482
static void remove_pass_end_marker()
Definition scheduler.c:520
#define DELAY_THRESHOLD
Task that were in the queue for longer than this are reported if PROFILE_DELAYS is active.
Definition scheduler.c:79
static unsigned int ready_count
Number of tasks on the ready list.
Definition scheduler.c:403
static struct GNUNET_DISK_PipeHandle * shutdown_pipe_handle
Pipe used to communicate shutdown via signal.
Definition scheduler.c:666
static const struct GNUNET_SCHEDULER_Driver * scheduler_driver
The driver used for the event loop.
Definition scheduler.c:324
static struct GNUNET_SCHEDULER_Task * pending_timeout_head
List of tasks waiting ONLY for a timeout event.
Definition scheduler.c:353
static void install_parent_control_handler(void *cls)
Definition scheduler.c:942
static int select_add(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Definition scheduler.c:2480
static GNUNET_SCHEDULER_select scheduler_select
Function to use as a select() in the scheduler.
Definition scheduler.c:431
static enum GNUNET_SCHEDULER_Priority work_priority
Priority used currently in GNUNET_SCHEDULER_do_work().
Definition scheduler.c:425
static void shutdown_if_no_lifeness(void)
Definition scheduler.c:705
static void * scheduler_select_cls
Closure for scheduler_select.
Definition scheduler.c:441
static struct GNUNET_SCHEDULER_Task * pending_timeout_tail
List of tasks waiting ONLY for a timeout event.
Definition scheduler.c:362
static struct GNUNET_SCHEDULER_Task * ready_head[GNUNET_SCHEDULER_PRIORITY_COUNT]
Head of list of tasks ready to run right now, grouped by importance.
Definition scheduler.c:378
static struct GNUNET_SCHEDULER_Task pass_end_marker
Placed at the end of a ready queue to indicate where a scheduler run pass ends.
Definition scheduler.c:261
static struct GNUNET_SCHEDULER_Task * add_without_sets(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_NETWORK_Handle *read_nh, const struct GNUNET_NETWORK_Handle *write_nh, const struct GNUNET_DISK_FileHandle *read_fh, const struct GNUNET_DISK_FileHandle *write_fh, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition scheduler.c:1445
static int current_lifeness
Value of the 'lifeness' flag for the current task.
Definition scheduler.c:420
static void set_work_priority(enum GNUNET_SCHEDULER_Priority p)
Definition scheduler.c:533
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition scheduler.c:1052
static enum GNUNET_SCHEDULER_Priority max_priority_added
Priority of the highest task added in the current select iteration.
Definition scheduler.c:415
static struct GNUNET_SCHEDULER_Task * pending_timeout_last
Last inserted task waiting ONLY for a timeout event.
Definition scheduler.c:368
static void sighandler_shutdown(void)
Signal handler called for signals that should cause us to shutdown.
Definition scheduler.c:688
#define LOG(kind,...)
Definition scheduler.c:37
static void shutdown_pipe_cb(void *cls)
Definition scheduler.c:951
#define LOG_STRERROR(kind, syscall)
Definition scheduler.c:39
static enum GNUNET_GenericReturnValue select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition scheduler.c:2321
static void init_fd_info(struct GNUNET_SCHEDULER_Task *t, const struct GNUNET_NETWORK_Handle *const *read_nh, unsigned int read_nh_len, const struct GNUNET_NETWORK_Handle *const *write_nh, unsigned int write_nh_len, const struct GNUNET_DISK_FileHandle *const *read_fh, unsigned int read_fh_len, const struct GNUNET_DISK_FileHandle *const *write_fh, unsigned int write_fh_len)
Definition scheduler.c:803
static struct GNUNET_SCHEDULER_Task * pending_tail
Tail of list of tasks waiting for an event.
Definition scheduler.c:334
static struct GNUNET_SCHEDULER_Task * shutdown_tail
Tail of list of tasks waiting for shutdown.
Definition scheduler.c:344
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:436
static struct GNUNET_SCHEDULER_Task * shutdown_head
Head of list of tasks waiting for shutdown.
Definition scheduler.c:339
static pid_t my_pid
Process ID of this process at the time we installed the various signal handlers.
Definition scheduler.c:672
static void extract_handles(const struct GNUNET_NETWORK_FDSet *fdset, const struct GNUNET_NETWORK_Handle ***ntarget, unsigned int *extracted_nhandles, const struct GNUNET_DISK_FileHandle ***ftarget, unsigned int *extracted_fhandles)
Definition scheduler.c:1759
Driver context used by GNUNET_SCHEDULER_run.
Definition scheduler.c:296
struct Scheduled * scheduled_head
the head of a DLL containing information about the events the select driver is waiting for
Definition scheduler.c:301
struct GNUNET_TIME_Absolute timeout
the time when the select driver will wake up again (after calling select)
Definition scheduler.c:313
struct Scheduled * scheduled_tail
the tail of a DLL containing information about the events the select driver is waiting for
Definition scheduler.c:307
Identifier for an asynchronous execution context.
Saved async scope identifier or root scope.
Handle used to access files (and pipes).
int fd
File handle on Unix-like systems.
Handle used to manage a pipe.
Definition disk.c:69
collection of IO descriptors
int nsds
Maximum number of any socket descriptor in the set (plus one)
handle to a socket
Definition network.c:53
API an external event loop has to implement for GNUNET_SCHEDULER_driver_init.
void * cls
Closure to pass to the functions in this struct.
int(* add)(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Add a task to be run if the conditions specified in the et field of the given fdi are satisfied.
void(* set_wakeup)(void *cls, struct GNUNET_TIME_Absolute dt)
Set time at which we definitively want to get a wakeup call.
int(* del)(void *cls, struct GNUNET_SCHEDULER_Task *task)
Delete a task from the set of tasks to be run.
Information about an event relating to a file descriptor/socket.
int sock
Underlying OS handle the event was about.
enum GNUNET_SCHEDULER_EventType et
Type of the event that was generated related to sock.
const struct GNUNET_DISK_FileHandle * fh
GNUnet file handle the event is about, matches sock, NULL if this is about a network socket or if no ...
const struct GNUNET_NETWORK_Handle * fd
GNUnet network socket the event is about, matches sock, NULL if this is about a file handle or if no ...
Argument to be passed from the driver to GNUNET_SCHEDULER_do_work().
Definition scheduler.c:88
Context information passed to each scheduler task.
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
unsigned int fds_len
Length of the following array.
const struct GNUNET_SCHEDULER_FdInfo * fds
Array of length fds_len with information about ready FDs.
const struct GNUNET_NETWORK_FDSet * write_ready
Set of file descriptors ready for writing; note that additional bits may be set that were not in the ...
Entry in list of pending tasks.
Definition scheduler.c:141
enum GNUNET_SCHEDULER_Priority priority
Task priority.
Definition scheduler.c:209
struct GNUNET_SCHEDULER_Task * prev
This is a linked list.
Definition scheduler.c:150
void * callback_cls
Closure for the callback.
Definition scheduler.c:160
int in_ready_list
Is this task in the ready list?
Definition scheduler.c:235
int lifeness
Should the existence of this task in the queue be counted as reason to not shutdown the scheduler?
Definition scheduler.c:225
enum GNUNET_SCHEDULER_Reason reason
Why is the task ready? Set after task is added to ready queue.
Definition scheduler.c:204
int own_handles
Do we own the network and file handles referenced by the FdInfo structs in the fds array.
Definition scheduler.c:184
struct GNUNET_AsyncScopeSave scope
Asynchronous scope of the task that scheduled this scope,.
Definition scheduler.c:253
struct GNUNET_SCHEDULER_Task * next
This is a linked list.
Definition scheduler.c:145
int on_shutdown
Is this task run on shutdown?
Definition scheduler.c:230
struct GNUNET_SCHEDULER_FdInfo * fds
Information about which FDs are ready for this task (and why).
Definition scheduler.c:165
unsigned int fds_len
Size of the fds array.
Definition scheduler.c:177
struct GNUNET_TIME_Absolute timeout
Absolute timeout value for the task, or GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout".
Definition scheduler.c:190
GNUNET_SCHEDULER_TaskCallback callback
Function to run when ready.
Definition scheduler.c:155
int write_fd
Set if we only wait for writing to a single FD, otherwise -1.
Definition scheduler.c:219
struct GNUNET_SCHEDULER_FdInfo fdx
Storage location used for fds if we want to avoid a separate malloc() call in the common case that th...
Definition scheduler.c:172
int read_fd
Set if we only wait for reading from a single FD, otherwise -1.
Definition scheduler.c:214
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
A struct representing an event the select driver is waiting for.
Definition scheduler.c:268
struct Scheduled * next
Definition scheduler.c:271
enum GNUNET_SCHEDULER_EventType et
the event types (multiple event types can be ORed) the select driver is expected to wait for
Definition scheduler.c:288
struct Scheduled * prev
Definition scheduler.c:269
struct GNUNET_SCHEDULER_FdInfo * fdi
information about the network socket / file descriptor where the event is expected to occur
Definition scheduler.c:282
struct GNUNET_SCHEDULER_Task * task
the task, the event is related to
Definition scheduler.c:276

◆ PROFILE_DELAYS

#define PROFILE_DELAYS   GNUNET_NO

Should we figure out which tasks are delayed for a while before they are run? (Consider using in combination with EXECINFO).

Definition at line 73 of file scheduler.c.

◆ DELAY_THRESHOLD

#define DELAY_THRESHOLD   GNUNET_TIME_UNIT_SECONDS

Task that were in the queue for longer than this are reported if PROFILE_DELAYS is active.

Definition at line 79 of file scheduler.c.

Function Documentation

◆ check_priority()

static enum GNUNET_SCHEDULER_Priority check_priority ( enum GNUNET_SCHEDULER_Priority  p)
static

Check that the given priority is legal (and return it).

Parameters
ppriority value to check
Returns
p on success, 0 on error

Definition at line 467 of file scheduler.c.

468{
469 if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
470 return p;
471 GNUNET_assert (0);
472 return 0; /* make compiler happy */
473}

References GNUNET_assert, GNUNET_SCHEDULER_PRIORITY_COUNT, and p.

Referenced by add_without_sets(), GNUNET_SCHEDULER_add_at_with_priority(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_add_with_reason_and_priority(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_get_load(), and queue_ready_task().

Here is the caller graph for this function:

◆ get_timeout()

static struct GNUNET_TIME_Absolute get_timeout ( )
static

chooses the nearest timeout from all pending tasks, to be used to tell the driver the next wakeup time (using its set_wakeup callback)

Definition at line 482 of file scheduler.c.

483{
484 struct GNUNET_SCHEDULER_Task *pos;
485 struct GNUNET_TIME_Absolute now;
487
491 if (NULL != pos)
492 {
493 if (0 != pos->reason)
494 {
495 return now;
496 }
497 else
498 {
499 timeout = pos->timeout;
500 }
501 }
502 for (pos = pending_head; NULL != pos; pos = pos->next)
503 {
504 if (0 != pos->reason)
505 {
506 return now;
507 }
508 else if ((pos->timeout.abs_value_us !=
509 GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
510 (timeout.abs_value_us > pos->timeout.abs_value_us))
511 {
512 timeout = pos->timeout;
513 }
514 }
515 return timeout;
516}

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_TIME_absolute_get(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_SCHEDULER_Task::next, pending_head, pending_timeout_head, GNUNET_SCHEDULER_Task::reason, timeout, and GNUNET_SCHEDULER_Task::timeout.

Referenced by GNUNET_SCHEDULER_do_work(), and GNUNET_SCHEDULER_driver_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove_pass_end_marker()

static void remove_pass_end_marker ( )
static

Definition at line 520 of file scheduler.c.

References GNUNET_CONTAINER_DLL_remove, GNUNET_NO, GNUNET_SCHEDULER_Task::in_ready_list, pass_end_marker, GNUNET_SCHEDULER_Task::priority, ready_head, and ready_tail.

Referenced by GNUNET_SCHEDULER_do_work(), and set_work_priority().

Here is the caller graph for this function:

◆ set_work_priority()

static void set_work_priority ( enum GNUNET_SCHEDULER_Priority  p)
static

Definition at line 533 of file scheduler.c.

References GNUNET_CONTAINER_DLL_insert_tail, GNUNET_YES, GNUNET_SCHEDULER_Task::in_ready_list, p, pass_end_marker, GNUNET_SCHEDULER_Task::priority, ready_head, ready_tail, remove_pass_end_marker(), and work_priority.

Referenced by GNUNET_SCHEDULER_do_work(), and queue_ready_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ queue_ready_task()

static void queue_ready_task ( struct GNUNET_SCHEDULER_Task task)
static

Put a task that is ready for execution into the ready queue.

Parameters
tasktask ready for execution

Definition at line 551 of file scheduler.c.

552{
554
556 ready_tail[p],
557 task);
558 if (p > work_priority)
561 ready_count++;
562}

References check_priority(), GNUNET_CONTAINER_DLL_insert_tail, GNUNET_YES, GNUNET_SCHEDULER_Task::in_ready_list, p, GNUNET_SCHEDULER_Task::priority, ready_count, ready_head, ready_tail, set_work_priority(), and work_priority.

Referenced by GNUNET_SCHEDULER_add_at_with_priority(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_with_reason_and_priority(), GNUNET_SCHEDULER_do_work(), GNUNET_SCHEDULER_shutdown(), and GNUNET_SCHEDULER_task_ready().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dump_backtrace()

static void dump_backtrace ( struct GNUNET_SCHEDULER_Task t)
static

Output stack trace of task t.

Parameters
ttask to dump stack trace of

Definition at line 605 of file scheduler.c.

606{
607#if EXECINFO
608 for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
610 "Task %p trace %u: %s\n",
611 t,
612 i,
613 t->backtrace_strings[i]);
614#else
615 (void) t;
616#endif
617}

References GNUNET_ERROR_TYPE_WARNING, LOG, and t.

Referenced by GNUNET_SCHEDULER_do_work(), init_backtrace(), and select_loop().

Here is the caller graph for this function:

◆ destroy_task()

static void destroy_task ( struct GNUNET_SCHEDULER_Task t)
static

Destroy a task (release associated resources)

Parameters
ttask to destroy

Definition at line 626 of file scheduler.c.

627{
628#if EXTRA_DEBUG
630 "destroying task %p\n",
631 t);
632#endif
633 if (GNUNET_YES == t->own_handles)
634 {
635 for (unsigned int i = 0; i != t->fds_len; ++i)
636 {
637 const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
638 const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
639 if (fd)
640 {
642 (struct GNUNET_NETWORK_Handle *) fd);
643 }
644 if (fh)
645 {
646 // FIXME: on WIN32 this is not enough! A function
647 // GNUNET_DISK_file_free_memory_only would be nice
648 GNUNET_free_nz ((void *) fh);
649 }
650 }
651 }
652 if (t->fds_len > 1)
653 {
655 }
656#if EXECINFO
657 GNUNET_free (t->backtrace_strings);
658#endif
659 GNUNET_free (t);
660}

References GNUNET_DISK_FileHandle::fd, GNUNET_SCHEDULER_FdInfo::fd, GNUNET_NETWORK_Handle::fd, GNUNET_SCHEDULER_Task::fds, GNUNET_SCHEDULER_Task::fds_len, GNUNET_SCHEDULER_FdInfo::fh, GNUNET_array_grow, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_free_nz, GNUNET_NETWORK_socket_free_memory_only_(), GNUNET_YES, LOG, GNUNET_SCHEDULER_Task::own_handles, and t.

Referenced by GNUNET_SCHEDULER_cancel(), and GNUNET_SCHEDULER_do_work().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sighandler_pipe()

static void sighandler_pipe ( )
static

Signal handler called for SIGPIPE.

Definition at line 678 of file scheduler.c.

679{
680 return;
681}

Referenced by GNUNET_SCHEDULER_driver_init().

Here is the caller graph for this function:

◆ sighandler_shutdown()

static void sighandler_shutdown ( void  )
static

Signal handler called for signals that should cause us to shutdown.

Definition at line 688 of file scheduler.c.

689{
690 static char c;
691 int old_errno = errno; /* backup errno */
692
693 if (getpid () != my_pid)
694 _exit (1); /* we have fork'ed since the signal handler was created,
695 * ignore the signal, see https://gnunet.org/vfork discussion */
699 &c, sizeof(c));
700 errno = old_errno;
701}

References GNUNET_DISK_file_write(), GNUNET_DISK_PIPE_END_WRITE, GNUNET_DISK_pipe_handle(), my_pid, and shutdown_pipe_handle.

Referenced by GNUNET_SCHEDULER_driver_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdown_if_no_lifeness()

static void shutdown_if_no_lifeness ( void  )
static

Definition at line 705 of file scheduler.c.

706{
707 struct GNUNET_SCHEDULER_Task *t;
708
709 if (ready_count > 0)
710 return;
711 for (t = pending_head; NULL != t; t = t->next)
712 if (GNUNET_YES == t->lifeness)
713 return;
714 for (t = shutdown_head; NULL != t; t = t->next)
715 if (GNUNET_YES == t->lifeness)
716 return;
717 for (t = pending_timeout_head; NULL != t; t = t->next)
718 if (GNUNET_YES == t->lifeness)
719 return;
720 /* No lifeness! */
722}

References GNUNET_SCHEDULER_shutdown(), GNUNET_YES, GNUNET_SCHEDULER_Task::lifeness, GNUNET_SCHEDULER_Task::next, pending_head, pending_timeout_head, ready_count, shutdown_head, and t.

Referenced by GNUNET_SCHEDULER_do_work().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_loop()

static enum GNUNET_GenericReturnValue select_loop ( struct GNUNET_SCHEDULER_Handle sh,
struct DriverContext context 
)
static

Definition at line 2321 of file scheduler.c.

2323{
2324 struct GNUNET_NETWORK_FDSet *rs;
2325 struct GNUNET_NETWORK_FDSet *ws;
2326 int select_result;
2327
2328 GNUNET_assert (NULL != context);
2331 while ((NULL != context->scheduled_head) ||
2332 (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2333 context->timeout.abs_value_us))
2334 {
2335 struct GNUNET_TIME_Relative time_remaining;
2336
2337#if EXTRA_DEBUG
2339 "select timeout = %s\n",
2341#endif
2344
2345 for (struct Scheduled *pos = context->scheduled_head;
2346 NULL != pos;
2347 pos = pos->next)
2348 {
2349 if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2350 {
2351 GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2352 }
2353 if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2354 {
2355 GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2356 }
2357 }
2358 time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2359 if (0 < ready_count)
2360 time_remaining = GNUNET_TIME_UNIT_ZERO;
2361 if (NULL == scheduler_select)
2362 {
2363 select_result = GNUNET_NETWORK_socket_select (rs,
2364 ws,
2365 NULL,
2366 time_remaining);
2367 }
2368 else
2369 {
2370 select_result = scheduler_select (scheduler_select_cls,
2371 rs,
2372 ws,
2373 NULL,
2374 time_remaining);
2375 }
2376 if (select_result == GNUNET_SYSERR)
2377 {
2378 if (errno == EINTR)
2379 continue;
2380
2382 "select");
2383#if USE_LSOF
2384 char lsof[512];
2385
2386 snprintf (lsof,
2387 sizeof(lsof),
2388 "lsof -p %d",
2389 getpid ());
2390 (void) close (1);
2391 (void) dup2 (2, 1);
2392 if (0 != system (lsof))
2394 "system");
2395#endif
2396#if DEBUG_FDS
2397 for (struct Scheduled *s = context->scheduled_head;
2398 NULL != s;
2399 s = s->next)
2400 {
2401 int flags = fcntl (s->fdi->sock,
2402 F_GETFD);
2403
2404 if ((flags == -1) &&
2405 (EBADF == errno))
2406 {
2408 "Got invalid file descriptor %d!\n",
2409 s->fdi->sock);
2410#if EXECINFO
2411 dump_backtrace (s->task);
2412#endif
2413 }
2414 }
2415#endif
2416 GNUNET_assert (0);
2419 return GNUNET_SYSERR;
2420 }
2421 if (select_result > 0)
2422 {
2423 for (struct Scheduled *pos = context->scheduled_head;
2424 NULL != pos;
2425 pos = pos->next)
2426 {
2427 int is_ready = GNUNET_NO;
2428
2429 if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2430 (GNUNET_YES ==
2432 pos->fdi->sock)) )
2433 {
2434 pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2435 is_ready = GNUNET_YES;
2436 }
2437 if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2438 (GNUNET_YES ==
2440 pos->fdi->sock)) )
2441 {
2442 pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2443 is_ready = GNUNET_YES;
2444 }
2445 if (GNUNET_YES == is_ready)
2446 {
2447 GNUNET_SCHEDULER_task_ready (pos->task,
2448 pos->fdi);
2449 }
2450 }
2451 }
2453 {
2454#if EXTRA_DEBUG
2456 "scheduler has more tasks ready!\n");
2457#endif
2458 }
2459 }
2462
2463 if ( (NULL == context->scheduled_head) &&
2464 (NULL != pending_timeout_head) &&
2465 (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us ==
2466 context->timeout.abs_value_us) )
2467 {
2468 /* Only remaining task has timeout of 'forever'.
2469 We exit here more as sanity measure, as just
2470 waiting forever isn't exactly useful. Still,
2471 this is indicative of a bug in the client code. */
2472 GNUNET_break (0);
2473 return GNUNET_NO;
2474 }
2475 return GNUNET_OK;
2476}

References context, dump_backtrace(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_NETWORK_fdset_create(), GNUNET_NETWORK_fdset_destroy(), GNUNET_NETWORK_fdset_set_native(), GNUNET_NETWORK_fdset_test_native(), GNUNET_NETWORK_fdset_zero(), GNUNET_NETWORK_socket_select(), GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_do_work(), GNUNET_SCHEDULER_ET_IN, GNUNET_SCHEDULER_ET_OUT, GNUNET_SCHEDULER_task_ready(), GNUNET_STRINGS_absolute_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_ZERO, GNUNET_YES, LOG, LOG_STRERROR, pending_timeout_head, ready_count, scheduler_select, scheduler_select_cls, and sh.

Referenced by GNUNET_SCHEDULER_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_fd_info()

static void init_fd_info ( struct GNUNET_SCHEDULER_Task t,
const struct GNUNET_NETWORK_Handle *const *  read_nh,
unsigned int  read_nh_len,
const struct GNUNET_NETWORK_Handle *const *  write_nh,
unsigned int  write_nh_len,
const struct GNUNET_DISK_FileHandle *const *  read_fh,
unsigned int  read_fh_len,
const struct GNUNET_DISK_FileHandle *const *  write_fh,
unsigned int  write_fh_len 
)
static

Definition at line 803 of file scheduler.c.

812{
813 // FIXME: if we have exactly two network handles / exactly two file handles
814 // and they are equal, we can make one FdInfo with both
815 // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
816 struct GNUNET_SCHEDULER_FdInfo *fdi;
817
818 t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
819 if (1 == t->fds_len)
820 {
821 fdi = &t->fdx;
822 t->fds = fdi;
823 if (1 == read_nh_len)
824 {
825 GNUNET_assert (NULL != read_nh);
826 GNUNET_assert (NULL != *read_nh);
827 fdi->fd = *read_nh;
829 fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
830 t->read_fd = fdi->sock;
831 t->write_fd = -1;
832 }
833 else if (1 == write_nh_len)
834 {
835 GNUNET_assert (NULL != write_nh);
836 GNUNET_assert (NULL != *write_nh);
837 fdi->fd = *write_nh;
839 fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
840 t->read_fd = -1;
841 t->write_fd = fdi->sock;
842 }
843 else if (1 == read_fh_len)
844 {
845 GNUNET_assert (NULL != read_fh);
846 GNUNET_assert (NULL != *read_fh);
847 fdi->fh = *read_fh;
849 fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
850 t->read_fd = fdi->sock;
851 t->write_fd = -1;
852 }
853 else
854 {
855 GNUNET_assert (NULL != write_fh);
856 GNUNET_assert (NULL != *write_fh);
857 fdi->fh = *write_fh;
859 fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
860 t->read_fd = -1;
861 t->write_fd = fdi->sock;
862 }
863 }
864 else
865 {
867 t->fds = fdi;
868 t->read_fd = -1;
869 t->write_fd = -1;
870 for (int i = 0; i != read_nh_len; ++i)
871 {
872 fdi->fd = read_nh[i];
873 GNUNET_assert (NULL != fdi->fd);
875 fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
876 ++fdi;
877 }
878 for (int i = 0; i != write_nh_len; ++i)
879 {
880 fdi->fd = write_nh[i];
881 GNUNET_assert (NULL != fdi->fd);
883 fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
884 ++fdi;
885 }
886 for (int i = 0; i != read_fh_len; ++i)
887 {
888 fdi->fh = read_fh[i];
889 GNUNET_assert (NULL != fdi->fh);
891 fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
892 ++fdi;
893 }
894 for (int i = 0; i != write_fh_len; ++i)
895 {
896 fdi->fh = write_fh[i];
897 GNUNET_assert (NULL != fdi->fh);
899 fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
900 ++fdi;
901 }
902 }
903}

References GNUNET_SCHEDULER_FdInfo::et, GNUNET_SCHEDULER_FdInfo::fd, GNUNET_SCHEDULER_Task::fds, GNUNET_SCHEDULER_Task::fds_len, GNUNET_SCHEDULER_Task::fdx, GNUNET_SCHEDULER_FdInfo::fh, GNUNET_assert, GNUNET_NETWORK_get_fd(), GNUNET_new_array, GNUNET_SCHEDULER_ET_IN, GNUNET_SCHEDULER_ET_OUT, GNUNET_SCHEDULER_Task::read_fd, GNUNET_SCHEDULER_FdInfo::sock, t, and GNUNET_SCHEDULER_Task::write_fd.

Referenced by add_without_sets(), and GNUNET_SCHEDULER_add_select().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ driver_add_multiple()

static void driver_add_multiple ( struct GNUNET_SCHEDULER_Task t)
static

calls the given function func on each FdInfo related to t.

Optionally updates the event type field in each FdInfo after calling func.

Parameters
tthe task
driver_functhe function to call with each FdInfo contained in in t
if_not_readyonly call driver_func on FdInfos that are not ready
etthe event type to be set in each FdInfo after calling driver_func on it, or -1 if no updating not desired.

Definition at line 920 of file scheduler.c.

921{
922 struct GNUNET_SCHEDULER_FdInfo *fdi;
923 int success = GNUNET_YES;
924
925 for (unsigned int i = 0; i != t->fds_len; ++i)
926 {
927 fdi = &t->fds[i];
929 t,
930 fdi) && success;
932 }
933 if (GNUNET_YES != success)
934 {
936 "driver could not add task\n");
937 }
938}

References GNUNET_SCHEDULER_Driver::add, GNUNET_SCHEDULER_Driver::cls, GNUNET_SCHEDULER_FdInfo::et, GNUNET_SCHEDULER_Task::fds, GNUNET_SCHEDULER_Task::fds_len, GNUNET_ERROR_TYPE_ERROR, GNUNET_SCHEDULER_ET_NONE, GNUNET_YES, LOG, scheduler_driver, and t.

Referenced by add_without_sets(), and GNUNET_SCHEDULER_add_select().

Here is the caller graph for this function:

◆ install_parent_control_handler()

static void install_parent_control_handler ( void *  cls)
static

Definition at line 942 of file scheduler.c.

943{
944 (void) cls;
947}

References GNUNET_OS_install_parent_control_handler(), and install_parent_control_task.

Referenced by GNUNET_SCHEDULER_driver_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ shutdown_pipe_cb()

static void shutdown_pipe_cb ( void *  cls)
static

Definition at line 951 of file scheduler.c.

952{
953 char c;
954 const struct GNUNET_DISK_FileHandle *pr;
955
956 (void) cls;
957 shutdown_pipe_task = NULL;
961 /* consume the signal */
962 GNUNET_DISK_file_read (pr, &c, sizeof(c));
963 /* mark all active tasks as ready due to shutdown */
967 pr,
969 NULL);
970}

References GNUNET_assert, GNUNET_DISK_file_read(), GNUNET_DISK_handle_invalid(), GNUNET_DISK_PIPE_END_READ, GNUNET_DISK_pipe_handle(), GNUNET_SCHEDULER_add_read_file(), GNUNET_SCHEDULER_shutdown(), GNUNET_TIME_UNIT_FOREVER_REL, shutdown_pipe_cb(), shutdown_pipe_handle, and shutdown_pipe_task.

Referenced by GNUNET_SCHEDULER_driver_init(), and shutdown_pipe_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init_backtrace()

static void init_backtrace ( struct GNUNET_SCHEDULER_Task t)
static

Initialize backtrace data for task t.

Parameters
ttask to initialize

Definition at line 1052 of file scheduler.c.

1053{
1054#if EXECINFO
1055 void *backtrace_array[MAX_TRACE_DEPTH];
1056
1057 t->num_backtrace_strings
1058 = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1059 t->backtrace_strings =
1060 backtrace_symbols (backtrace_array,
1061 t->num_backtrace_strings);
1062 dump_backtrace (t);
1063#else
1064 (void) t;
1065#endif
1066}

References dump_backtrace(), and t.

Referenced by add_without_sets(), GNUNET_SCHEDULER_add_at_with_priority(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_add_shutdown(), and GNUNET_SCHEDULER_add_with_reason_and_priority().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_without_sets()

static struct GNUNET_SCHEDULER_Task * add_without_sets ( struct GNUNET_TIME_Relative  delay,
enum GNUNET_SCHEDULER_Priority  priority,
const struct GNUNET_NETWORK_Handle read_nh,
const struct GNUNET_NETWORK_Handle write_nh,
const struct GNUNET_DISK_FileHandle read_fh,
const struct GNUNET_DISK_FileHandle write_fh,
GNUNET_SCHEDULER_TaskCallback  task,
void *  task_cls 
)
static

Schedule a new task to be run with a specified delay or when any of the specified file descriptor sets is ready.

The delay can be used as a timeout on the socket(s) being ready. The task will be scheduled for execution once either the delay has expired or any of the socket operations is ready. This is the most general function of the "add" family. Note that the "prerequisite_task" must be satisfied in addition to any of the other conditions. In other words, the task will be started when (prerequisite-run) && (delay-ready || any-rs-ready || any-ws-ready)

Parameters
delayhow long should we wait?
prioritypriority to use
rfdfile descriptor we want to read (can be -1)
wfdfile descriptors we want to write (can be -1)
taskmain function of the task
task_clsclosure of task
Returns
unique task identifier for the job only valid until task is started!

Definition at line 1445 of file scheduler.c.

1453{
1454 struct GNUNET_SCHEDULER_Task *t;
1455
1456 /* scheduler must be running */
1458 GNUNET_assert (NULL != task);
1461 init_fd_info (t,
1462 &read_nh,
1463 read_nh ? 1 : 0,
1464 &write_nh,
1465 write_nh ? 1 : 0,
1466 &read_fh,
1467 read_fh ? 1 : 0,
1468 &write_fh,
1469 write_fh ? 1 : 0);
1470 t->callback = task;
1471 t->callback_cls = task_cls;
1472#if DEBUG_FDS
1473 check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1474 check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1475 check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1476 check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1477#endif
1478#if PROFILE_DELAYS
1479 t->start_time = GNUNET_TIME_absolute_get ();
1480#endif
1487 t);
1490 t->priority);
1491 init_backtrace (t);
1492 return t;
1493}

References GNUNET_SCHEDULER_Task::callback, GNUNET_SCHEDULER_Task::callback_cls, check_priority(), current_lifeness, current_priority, driver_add_multiple(), GNUNET_DISK_FileHandle::fd, GNUNET_assert, GNUNET_async_scope_get(), GNUNET_CONTAINER_DLL_insert, GNUNET_MAX, GNUNET_NETWORK_get_fd(), GNUNET_new, GNUNET_SCHEDULER_PRIORITY_KEEP, GNUNET_TIME_absolute_get(), GNUNET_TIME_relative_to_absolute(), init_backtrace(), init_fd_info(), GNUNET_SCHEDULER_Task::lifeness, max_priority_added, pending_head, pending_tail, GNUNET_SCHEDULER_Task::priority, scheduler_driver, GNUNET_SCHEDULER_Task::scope, t, and GNUNET_SCHEDULER_Task::timeout.

Referenced by GNUNET_SCHEDULER_add_file_with_priority(), and GNUNET_SCHEDULER_add_net_with_priority().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ extract_handles()

static void extract_handles ( const struct GNUNET_NETWORK_FDSet fdset,
const struct GNUNET_NETWORK_Handle ***  ntarget,
unsigned int *  extracted_nhandles,
const struct GNUNET_DISK_FileHandle ***  ftarget,
unsigned int *  extracted_fhandles 
)
static

Definition at line 1759 of file scheduler.c.

1764{
1765 // FIXME: this implementation only works for unix, for WIN32 the file handles
1766 // in fdset must be handled separately
1767 const struct GNUNET_NETWORK_Handle **nhandles;
1768 const struct GNUNET_DISK_FileHandle **fhandles;
1769 unsigned int nhandles_len;
1770 unsigned int fhandles_len;
1771
1772 nhandles = NULL;
1773 fhandles = NULL;
1774 nhandles_len = 0;
1775 fhandles_len = 0;
1776 for (int sock = 0; sock != fdset->nsds; ++sock)
1777 {
1778 if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1779 {
1780 struct GNUNET_NETWORK_Handle *nhandle;
1781 struct GNUNET_DISK_FileHandle *fhandle;
1782
1783 nhandle = GNUNET_NETWORK_socket_box_native (sock);
1784 if (NULL != nhandle)
1785 {
1786 GNUNET_array_append (nhandles, nhandles_len, nhandle);
1787 }
1788 else
1789 {
1790 fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1791 if (NULL != fhandle)
1792 {
1793 GNUNET_array_append (fhandles, fhandles_len, fhandle);
1794 }
1795 else
1796 {
1797 GNUNET_assert (0);
1798 }
1799 }
1800 }
1801 }
1802 *ntarget = nhandles_len > 0 ? nhandles : NULL;
1803 *ftarget = fhandles_len > 0 ? fhandles : NULL;
1804 *extracted_nhandles = nhandles_len;
1805 *extracted_fhandles = fhandles_len;
1806}

References GNUNET_array_append, GNUNET_assert, GNUNET_DISK_get_handle_from_int_fd(), GNUNET_NETWORK_fdset_test_native(), GNUNET_NETWORK_socket_box_native(), GNUNET_YES, and GNUNET_NETWORK_FDSet::nsds.

Referenced by GNUNET_SCHEDULER_add_select().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_add()

static int select_add ( void *  cls,
struct GNUNET_SCHEDULER_Task task,
struct GNUNET_SCHEDULER_FdInfo fdi 
)
static

Definition at line 2480 of file scheduler.c.

2483{
2484 struct DriverContext *context = cls;
2485 struct Scheduled *scheduled;
2486
2487 GNUNET_assert (NULL != context);
2488 GNUNET_assert (NULL != task);
2489 GNUNET_assert (NULL != fdi);
2491 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2492
2493 if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2494 {
2495 /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2496 return GNUNET_SYSERR;
2497 }
2498
2499 scheduled = GNUNET_new (struct Scheduled);
2500 scheduled->task = task;
2501 scheduled->fdi = fdi;
2502 scheduled->et = fdi->et;
2503
2504 GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2505 context->scheduled_tail,
2506 scheduled);
2507 return GNUNET_OK;
2508}

References context, GNUNET_SCHEDULER_FdInfo::et, Scheduled::et, GNUNET_SCHEDULER_FdInfo::fd, Scheduled::fdi, GNUNET_SCHEDULER_FdInfo::fh, GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_ET_IN, GNUNET_SCHEDULER_ET_OUT, GNUNET_SYSERR, GNUNET_SCHEDULER_FdInfo::sock, and Scheduled::task.

Referenced by GNUNET_SCHEDULER_driver_select().

Here is the caller graph for this function:

◆ select_del()

static int select_del ( void *  cls,
struct GNUNET_SCHEDULER_Task task 
)
static

Definition at line 2512 of file scheduler.c.

2514{
2515 struct DriverContext *context;
2516 struct Scheduled *pos;
2517 int ret;
2518
2519 GNUNET_assert (NULL != cls);
2520
2521 context = cls;
2523 pos = context->scheduled_head;
2524 while (NULL != pos)
2525 {
2526 struct Scheduled *next = pos->next;
2527 if (pos->task == task)
2528 {
2529 GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2530 context->scheduled_tail,
2531 pos);
2532 GNUNET_free (pos);
2533 ret = GNUNET_OK;
2534 }
2535 pos = next;
2536 }
2537 return ret;
2538}

References context, GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_OK, GNUNET_SYSERR, Scheduled::next, ret, and Scheduled::task.

Referenced by GNUNET_SCHEDULER_driver_select().

Here is the caller graph for this function:

◆ select_set_wakeup()

static void select_set_wakeup ( void *  cls,
struct GNUNET_TIME_Absolute  dt 
)
static

Definition at line 2542 of file scheduler.c.

2544{
2545 struct DriverContext *context = cls;
2546
2547 GNUNET_assert (NULL != context);
2548 context->timeout = dt;
2549}

References context, and GNUNET_assert.

Referenced by GNUNET_SCHEDULER_driver_select().

Here is the caller graph for this function:

Variable Documentation

◆ pass_end_marker

struct GNUNET_SCHEDULER_Task pass_end_marker
static

Placed at the end of a ready queue to indicate where a scheduler run pass ends.

The next, prev, in_ready_list and priority fields are the only ones that should be used.

Definition at line 261 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_do_work(), GNUNET_SCHEDULER_get_load(), remove_pass_end_marker(), and set_work_priority().

◆ scheduler_driver

◆ pending_head

◆ pending_tail

struct GNUNET_SCHEDULER_Task* pending_tail
static

Tail of list of tasks waiting for an event.

Definition at line 334 of file scheduler.c.

Referenced by add_without_sets(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_do_work(), and GNUNET_SCHEDULER_task_ready().

◆ shutdown_head

struct GNUNET_SCHEDULER_Task* shutdown_head
static

Head of list of tasks waiting for shutdown.

Definition at line 339 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_driver_done(), GNUNET_SCHEDULER_shutdown(), and shutdown_if_no_lifeness().

◆ shutdown_tail

struct GNUNET_SCHEDULER_Task* shutdown_tail
static

Tail of list of tasks waiting for shutdown.

Definition at line 344 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_cancel(), and GNUNET_SCHEDULER_shutdown().

◆ pending_timeout_head

struct GNUNET_SCHEDULER_Task* pending_timeout_head
static

List of tasks waiting ONLY for a timeout event.

Sorted by timeout (earliest first). Used so that we do not traverse the list of these tasks when building select sets (we just look at the head to determine the respective timeout ONCE).

Definition at line 353 of file scheduler.c.

Referenced by get_timeout(), GNUNET_SCHEDULER_add_at_with_priority(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_do_work(), GNUNET_SCHEDULER_driver_done(), select_loop(), and shutdown_if_no_lifeness().

◆ pending_timeout_tail

struct GNUNET_SCHEDULER_Task* pending_timeout_tail
static

List of tasks waiting ONLY for a timeout event.

Sorted by timeout (earliest first). Used so that we do not traverse the list of these tasks when building select sets (we just look at the head to determine the respective timeout ONCE).

Definition at line 362 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_add_at_with_priority(), GNUNET_SCHEDULER_cancel(), and GNUNET_SCHEDULER_do_work().

◆ pending_timeout_last

struct GNUNET_SCHEDULER_Task* pending_timeout_last
static

Last inserted task waiting ONLY for a timeout event.

Used to (heuristically) speed up insertion.

Definition at line 368 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_add_at_with_priority(), GNUNET_SCHEDULER_cancel(), and GNUNET_SCHEDULER_do_work().

◆ active_task

struct GNUNET_SCHEDULER_Task* active_task
static

ID of the task that is running right now.

Definition at line 373 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_begin_async_scope(), GNUNET_SCHEDULER_do_work(), GNUNET_SCHEDULER_get_load(), and GNUNET_SCHEDULER_get_task_context().

◆ ready_head

Head of list of tasks ready to run right now, grouped by importance.

Definition at line 379 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_do_work(), GNUNET_SCHEDULER_driver_done(), GNUNET_SCHEDULER_get_load(), queue_ready_task(), remove_pass_end_marker(), and set_work_priority().

◆ ready_tail

Tail of list of tasks ready to run right now, grouped by importance.

Definition at line 385 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_do_work(), queue_ready_task(), remove_pass_end_marker(), and set_work_priority().

◆ install_parent_control_task

struct GNUNET_SCHEDULER_Task* install_parent_control_task
static

Task for installing parent control handlers (it might happen that the scheduler is shutdown before this task is executed, so GNUNET_SCHEDULER_shutdown must cancel it in that case)

Definition at line 392 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_driver_init(), GNUNET_SCHEDULER_shutdown(), and install_parent_control_handler().

◆ shutdown_pipe_task

struct GNUNET_SCHEDULER_Task* shutdown_pipe_task
static

Task for reading from a pipe that signal handlers will use to initiate shutdown.

Definition at line 398 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_driver_init(), GNUNET_SCHEDULER_shutdown(), and shutdown_pipe_cb().

◆ ready_count

unsigned int ready_count
static

◆ current_priority

enum GNUNET_SCHEDULER_Priority current_priority
static

Priority of the task running right now.

Only valid while a task is running.

Definition at line 409 of file scheduler.c.

Referenced by add_without_sets(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_select(), GNUNET_SCHEDULER_do_work(), GNUNET_SCHEDULER_driver_init(), and GNUNET_SCHEDULER_get_load().

◆ max_priority_added

enum GNUNET_SCHEDULER_Priority max_priority_added
static

Priority of the highest task added in the current select iteration.

Definition at line 415 of file scheduler.c.

Referenced by add_without_sets(), GNUNET_SCHEDULER_add_select(), and GNUNET_SCHEDULER_do_work().

◆ current_lifeness

◆ work_priority

enum GNUNET_SCHEDULER_Priority work_priority
static

◆ scheduler_select

GNUNET_SCHEDULER_select scheduler_select
static

Function to use as a select() in the scheduler.

If NULL, we use GNUNET_NETWORK_socket_select().

Definition at line 431 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_set_select(), and select_loop().

◆ tc

struct GNUNET_SCHEDULER_TaskContext tc
static

Task context of the current task.

Definition at line 436 of file scheduler.c.

Referenced by check_add_address(), check_add_queue_message(), check_client_send(), check_communicator_available(), check_incoming_msg(), client_connect_cb(), client_disconnect_cb(), client_send_response(), cmd_read(), connect_probe_continuation(), core_send_connect_info(), cores_send_connect_info(), cores_send_disconnect_info(), create_address_entry(), decrypt_and_check_tc(), decrypt_and_check_tc(), do_read(), do_read(), do_s5r_read(), do_udp_read(), do_udp_read(), do_udp_read(), finish_handling_raw_message(), free_address_list_entry(), free_pending_message(), free_queue(), free_queue_entry(), free_timedout_queue_entry(), GNUNET_FS_share_tree_trim(), GNUNET_SCHEDULER_do_work(), GNUNET_SCHEDULER_get_task_context(), handle_add_address(), handle_add_queue_message(), handle_backchannel_encapsulation(), handle_client_recv_ok(), handle_client_send(), handle_client_send(), handle_client_start(), handle_communicator_available(), handle_communicator_backchannel(), handle_del_address(), handle_del_queue_message(), handle_incoming_msg(), handle_monitor_start(), handle_queue_create_fail(), handle_queue_create_ok(), handle_request_hello_validation(), handle_send_message_ack(), handle_suggest(), handle_suggest_cancel(), handle_update_queue_message(), lookup_communicator(), maint_child_death(), migrate_and_drop_keywords(), migrate_and_drop_metadata(), notify_client_connect_info(), notify_client_queues(), notify_monitor(), notify_monitors(), proto_read_kx(), proto_read_kx(), queue_read_kx(), queue_read_kx(), queue_send_msg(), read_dns4(), read_dns6(), read_response(), remove_high_frequency_keywords(), share_tree_trim(), shutdown_task(), start_burst(), stop_peer_request(), suggest_to_connect(), tcp_send(), tokenized_cb(), transmit_kx(), and transmit_kx().

◆ scheduler_select_cls

void* scheduler_select_cls
static

Closure for scheduler_select.

Definition at line 441 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_set_select(), and select_loop().

◆ shutdown_pipe_handle

struct GNUNET_DISK_PipeHandle* shutdown_pipe_handle
static

Pipe used to communicate shutdown via signal.

Definition at line 666 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_driver_done(), GNUNET_SCHEDULER_driver_init(), shutdown_pipe_cb(), and sighandler_shutdown().

◆ my_pid

pid_t my_pid
static

Process ID of this process at the time we installed the various signal handlers.

Definition at line 672 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_driver_init(), and sighandler_shutdown().