GNUnet debian-0.24.3-29-g453fda2cf
 
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 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

◆ LOG

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

Definition at line 32 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 34 of file scheduler.c.

82{
88 struct GNUNET_NETWORK_FDSet *rs;
89
95 struct GNUNET_NETWORK_FDSet *ws;
96
100 struct GNUNET_SIGNAL_Context *shc_int;
101
105 struct GNUNET_SIGNAL_Context *shc_term;
106
107#if (SIGTERM != GNUNET_TERM_SIG)
111 struct GNUNET_SIGNAL_Context *shc_gterm;
112#endif
113
117 struct GNUNET_SIGNAL_Context *shc_quit;
118
122 struct GNUNET_SIGNAL_Context *shc_hup;
123
127 struct GNUNET_SIGNAL_Context *shc_pipe;
128};
129
130
135{
140
145
150
154 void *callback_cls;
155
160
167
171 unsigned int fds_len;
172
178 int own_handles;
179
185
186#if PROFILE_DELAYS
191#endif
192
199
204
208 int read_fd;
209
213 int write_fd;
214
219 int lifeness;
220
224 int on_shutdown;
225
229 int in_ready_list;
230
231#if EXECINFO
236 char **backtrace_strings;
237
241 int num_backtrace_strings;
242#endif
243
248};
249
256
257
261struct Scheduled
262{
263 struct Scheduled *prev;
264
265 struct Scheduled *next;
266
271
277
283};
284
285
289struct DriverContext
290{
296
302
308};
309
310
318static const struct GNUNET_SCHEDULER_Driver *scheduler_driver;
319
324
329
334
339
348
357
363
368
372static struct
374
378static struct
380
387
393
397static unsigned int ready_count;
398
404
410
414static int current_lifeness;
415
420
426
430static struct GNUNET_SCHEDULER_TaskContext tc;
431
435static void *scheduler_select_cls;
436
437
445void
447 void *new_select_cls)
448{
449 scheduler_select = new_select;
450 scheduler_select_cls = new_select_cls;
451}
452
453
462{
463 if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
464 return p;
465 GNUNET_assert (0);
466 return 0; /* make compiler happy */
467}
468
469
475static struct GNUNET_TIME_Absolute
477{
478 struct GNUNET_SCHEDULER_Task *pos;
479 struct GNUNET_TIME_Absolute now;
481
485 if (NULL != pos)
486 {
487 if (0 != pos->reason)
488 {
489 return now;
490 }
491 else
492 {
493 timeout = pos->timeout;
494 }
495 }
496 for (pos = pending_head; NULL != pos; pos = pos->next)
497 {
498 if (0 != pos->reason)
499 {
500 return now;
501 }
502 else if ((pos->timeout.abs_value_us !=
503 GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
504 (timeout.abs_value_us > pos->timeout.abs_value_us))
505 {
506 timeout = pos->timeout;
507 }
508 }
509 return timeout;
510}
511
512
513static void
515{
517 {
522 }
523}
524
525
526static void
528{
531 ready_tail[p],
536}
537
538
544static void
546{
548
550 ready_tail[p],
551 task);
552 if (p > work_priority)
555 ready_count++;
556}
557
558
565void
567{
568 struct GNUNET_SCHEDULER_Task *pos;
569
571 "GNUNET_SCHEDULER_shutdown\n");
572 if (NULL != install_parent_control_task)
573 {
576 }
577 if (NULL != shutdown_pipe_task)
578 {
580 shutdown_pipe_task = NULL;
581 }
582 while (NULL != (pos = shutdown_head))
583 {
586 pos);
588 queue_ready_task (pos);
589 }
590}
591
592
598static void
600{
601#if EXECINFO
602 for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
604 "Task %p trace %u: %s\n",
605 t,
606 i,
607 t->backtrace_strings[i]);
608#else
609 (void) t;
610#endif
611}
612
613
619static void
621{
623 "destroying task %p\n",
624 t);
625
626 if (GNUNET_YES == t->own_handles)
627 {
628 for (unsigned int i = 0; i != t->fds_len; ++i)
629 {
630 const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
631 const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
632 if (fd)
633 {
635 (struct GNUNET_NETWORK_Handle *) fd);
636 }
637 if (fh)
638 {
639 // FIXME: on WIN32 this is not enough! A function
640 // GNUNET_DISK_file_free_memory_only would be nice
641 GNUNET_free_nz ((void *) fh);
642 }
643 }
644 }
645 if (t->fds_len > 1)
646 {
648 }
649#if EXECINFO
650 GNUNET_free (t->backtrace_strings);
651#endif
652 GNUNET_free (t);
653}
654
655
660
665static pid_t my_pid;
666
670static void
672{
673 return;
674}
675
676
680static void
682{
683 static char c;
684 int old_errno = errno; /* backup errno */
685
686 if (getpid () != my_pid)
687 _exit (1); /* we have fork'ed since the signal handler was created,
688 * ignore the signal, see https://gnunet.org/vfork discussion */
692 &c, sizeof(c));
693 errno = old_errno;
694}
695
696
697static void
699{
700 struct GNUNET_SCHEDULER_Task *t;
701
702 if (ready_count > 0)
703 return;
704 for (t = pending_head; NULL != t; t = t->next)
705 if (GNUNET_YES == t->lifeness)
706 return;
707 for (t = shutdown_head; NULL != t; t = t->next)
708 if (GNUNET_YES == t->lifeness)
709 return;
710 for (t = pending_timeout_head; NULL != t; t = t->next)
711 if (GNUNET_YES == t->lifeness)
712 return;
713 /* No lifeness! */
715}
716
717
720 struct DriverContext *context);
721
722
723void
725 void *task_cls)
726{
728 struct GNUNET_SCHEDULER_Driver *driver;
729 struct DriverContext context = {
730 .scheduled_head = NULL,
731 .scheduled_tail = NULL,
732 .timeout = GNUNET_TIME_absolute_get ()
733 };
734
736 driver->cls = &context;
739 task_cls,
744 &context));
746 GNUNET_free (driver);
747}
748
749
756const struct GNUNET_SCHEDULER_TaskContext *
758{
759 GNUNET_assert (NULL != active_task);
760 return &tc;
761}
762
763
773unsigned int
775{
776 unsigned int ret;
777
778 GNUNET_assert (NULL != active_task);
780 return ready_count;
783 ret = 0;
784 for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)];
785 NULL != pos;
786 pos = pos->next)
787 ret++;
789 // Don't count the dummy marker
790 ret--;
791 return ret;
792}
793
794
795static void
797 const struct GNUNET_NETWORK_Handle *const *read_nh,
798 unsigned int read_nh_len,
799 const struct GNUNET_NETWORK_Handle *const *write_nh,
800 unsigned int write_nh_len,
801 const struct GNUNET_DISK_FileHandle *const *read_fh,
802 unsigned int read_fh_len,
803 const struct GNUNET_DISK_FileHandle *const *write_fh,
804 unsigned int write_fh_len)
805{
806 // FIXME: if we have exactly two network handles / exactly two file handles
807 // and they are equal, we can make one FdInfo with both
808 // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
809 struct GNUNET_SCHEDULER_FdInfo *fdi;
810
811 t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
812 if (1 == t->fds_len)
813 {
814 fdi = &t->fdx;
815 t->fds = fdi;
816 if (1 == read_nh_len)
817 {
818 GNUNET_assert (NULL != read_nh);
819 GNUNET_assert (NULL != *read_nh);
820 fdi->fd = *read_nh;
822 fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
823 t->read_fd = fdi->sock;
824 t->write_fd = -1;
825 }
826 else if (1 == write_nh_len)
827 {
828 GNUNET_assert (NULL != write_nh);
829 GNUNET_assert (NULL != *write_nh);
830 fdi->fd = *write_nh;
832 fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
833 t->read_fd = -1;
834 t->write_fd = fdi->sock;
835 }
836 else if (1 == read_fh_len)
837 {
838 GNUNET_assert (NULL != read_fh);
839 GNUNET_assert (NULL != *read_fh);
840 fdi->fh = *read_fh;
842 fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
843 t->read_fd = fdi->sock;
844 t->write_fd = -1;
845 }
846 else
847 {
848 GNUNET_assert (NULL != write_fh);
849 GNUNET_assert (NULL != *write_fh);
850 fdi->fh = *write_fh;
852 fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
853 t->read_fd = -1;
854 t->write_fd = fdi->sock;
855 }
856 }
857 else
858 {
860 t->fds = fdi;
861 t->read_fd = -1;
862 t->write_fd = -1;
863 for (int i = 0; i != read_nh_len; ++i)
864 {
865 fdi->fd = read_nh[i];
866 GNUNET_assert (NULL != fdi->fd);
868 fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
869 ++fdi;
870 }
871 for (int i = 0; i != write_nh_len; ++i)
872 {
873 fdi->fd = write_nh[i];
874 GNUNET_assert (NULL != fdi->fd);
876 fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
877 ++fdi;
878 }
879 for (int i = 0; i != read_fh_len; ++i)
880 {
881 fdi->fh = read_fh[i];
882 GNUNET_assert (NULL != fdi->fh);
884 fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
885 ++fdi;
886 }
887 for (int i = 0; i != write_fh_len; ++i)
888 {
889 fdi->fh = write_fh[i];
890 GNUNET_assert (NULL != fdi->fh);
892 fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
893 ++fdi;
894 }
895 }
896}
897
898
912static void
914{
915 struct GNUNET_SCHEDULER_FdInfo *fdi;
916 int success = GNUNET_YES;
917
918 for (unsigned int i = 0; i != t->fds_len; ++i)
919 {
920 fdi = &t->fds[i];
922 t,
923 fdi) && success;
925 }
926 if (GNUNET_YES != success)
927 {
929 "driver could not add task\n");
930 }
931}
932
933
934static void
936{
937 (void) cls;
940}
941
942
943static void
944shutdown_pipe_cb (void *cls)
945{
946 char c;
947 const struct GNUNET_DISK_FileHandle *pr;
948
949 (void) cls;
950 shutdown_pipe_task = NULL;
954 /* consume the signal */
955 GNUNET_DISK_file_read (pr, &c, sizeof(c));
956 /* mark all active tasks as ready due to shutdown */
960 pr,
962 NULL);
963}
964
965
978void *
980{
982 int is_fd_task;
983 void *ret;
984
986 "canceling task %p\n",
987 task);
988
989 /* scheduler must be running */
991 is_fd_task = (NULL != task->fds);
992 if (is_fd_task)
993 {
994 int del_result = scheduler_driver->del (scheduler_driver->cls, task);
995 if (GNUNET_OK != del_result)
996 {
998 "driver could not delete task\n");
999 GNUNET_assert (0);
1000 }
1001 }
1002 if (! task->in_ready_list)
1003 {
1004 if (is_fd_task)
1005 {
1008 task);
1009 }
1010 else if (GNUNET_YES == task->on_shutdown)
1011 {
1014 task);
1015 }
1016 else
1017 {
1020 task);
1021 if (pending_timeout_last == task)
1022 pending_timeout_last = NULL;
1023 }
1024 }
1025 else
1026 {
1027 p = check_priority (task->priority);
1029 ready_tail[p],
1030 task);
1031 ready_count--;
1032 }
1033 ret = task->callback_cls;
1034 destroy_task (task);
1035 return ret;
1036}
1037
1038
1044static void
1046{
1047#if EXECINFO
1048 void *backtrace_array[MAX_TRACE_DEPTH];
1049
1050 t->num_backtrace_strings
1051 = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1052 t->backtrace_strings =
1053 backtrace_symbols (backtrace_array,
1054 t->num_backtrace_strings);
1055 dump_backtrace (t);
1056#else
1057 (void) t;
1058#endif
1059}
1060
1061
1072void
1074 task,
1075 void *task_cls,
1077 reason,
1079 priority)
1080{
1081 struct GNUNET_SCHEDULER_Task *t;
1082
1083 /* scheduler must be running */
1085 GNUNET_assert (NULL != task);
1087 t->read_fd = -1;
1088 t->write_fd = -1;
1089 t->callback = task;
1090 t->callback_cls = task_cls;
1091#if PROFILE_DELAYS
1092 t->start_time = GNUNET_TIME_absolute_get ();
1093#endif
1094 t->reason = reason;
1098 "Adding continuation task %p\n",
1099 t);
1100 init_backtrace (t);
1102}
1103
1104
1116struct GNUNET_SCHEDULER_Task *
1120 void *task_cls)
1121{
1122 struct GNUNET_SCHEDULER_Task *t;
1123 struct GNUNET_SCHEDULER_Task *pos;
1125 struct GNUNET_TIME_Relative left;
1126
1127 /* scheduler must be running */
1129 GNUNET_assert (NULL != task);
1132 t->callback = task;
1133 t->callback_cls = task_cls;
1134 t->read_fd = -1;
1135 t->write_fd = -1;
1136#if PROFILE_DELAYS
1137 t->start_time = GNUNET_TIME_absolute_get ();
1138#endif
1139 t->timeout = at;
1140 t->priority = check_priority (priority);
1142 init_backtrace (t);
1143
1145 if (0 == left.rel_value_us)
1146 {
1148 if (priority > work_priority)
1149 work_priority = priority;
1150 return t;
1151 }
1152
1153 /* try tail first (optimization in case we are
1154 * appending to a long list of tasks with timeouts) */
1155 if ((NULL == pending_timeout_head) ||
1157 {
1160 t);
1161 }
1162 else
1163 {
1164 /* first move from heuristic start backwards to before start time */
1165 prev = pending_timeout_last;
1166 while ((NULL != prev) &&
1168 prev = prev->prev;
1169 /* now, move from heuristic start (or head of list) forward to insertion point */
1170 if (NULL == prev)
1172 else
1173 pos = prev->next;
1174 while ((NULL != pos) && (pos->timeout.abs_value_us <=
1176 {
1177 prev = pos;
1178 pos = pos->next;
1179 }
1182 prev,
1183 t);
1184 }
1185 /* finally, update heuristic insertion point to last insertion... */
1188 "Adding task %p\n",
1189 t);
1190 return t;
1191}
1192
1193
1205struct GNUNET_SCHEDULER_Task *
1208 priority,
1210 void *task_cls)
1211{
1214 priority,
1215 task,
1216 task_cls);
1217}
1218
1219
1229struct GNUNET_SCHEDULER_Task *
1232 void *task_cls)
1233{
1235 prio,
1236 task,
1237 task_cls);
1238}
1239
1240
1252struct GNUNET_SCHEDULER_Task *
1255 void *task_cls)
1256{
1259 task,
1260 task_cls);
1261}
1262
1263
1275struct GNUNET_SCHEDULER_Task *
1278 void *task_cls)
1279{
1282 task,
1283 task_cls);
1284}
1285
1286
1302struct GNUNET_SCHEDULER_Task *
1304 void *task_cls)
1305{
1306 struct GNUNET_SCHEDULER_Task *t;
1307
1310 t->callback = task;
1311 t->callback_cls = task_cls;
1312 t->read_fd = -1;
1313 t->write_fd = -1;
1314#if PROFILE_DELAYS
1315 t->start_time = GNUNET_TIME_absolute_get ();
1316#endif
1322 init_backtrace (t);
1323 return t;
1324}
1325
1326
1337struct GNUNET_SCHEDULER_Task *
1339 void *task_cls)
1340{
1341 struct GNUNET_SCHEDULER_Task *t;
1342
1343 /* scheduler must be running */
1345 GNUNET_assert (NULL != task);
1348 t->callback = task;
1349 t->callback_cls = task_cls;
1350 t->read_fd = -1;
1351 t->write_fd = -1;
1352#if PROFILE_DELAYS
1353 t->start_time = GNUNET_TIME_absolute_get ();
1354#endif
1358 t->lifeness = GNUNET_NO;
1361 t);
1363 "Adding shutdown task %p\n",
1364 t);
1365 init_backtrace (t);
1366 return t;
1367}
1368
1369
1370struct GNUNET_SCHEDULER_Task *
1373 void *task_cls)
1374{
1375 struct GNUNET_SCHEDULER_Task *ret;
1376
1377 ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1378 ret->lifeness = lifeness;
1379 return ret;
1380}
1381
1382
1383#if DEBUG_FDS
1390void
1391check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1392{
1393 if (-1 != raw_fd)
1394 {
1395 int flags = fcntl (raw_fd, F_GETFD);
1396
1397 if ((flags == -1) && (errno == EBADF))
1398 {
1400 "Got invalid file descriptor %d!\n",
1401 raw_fd);
1402 init_backtrace (t);
1403 GNUNET_assert (0);
1404 }
1405 }
1406}
1407
1408
1409#endif
1410
1411
1437static struct GNUNET_SCHEDULER_Task *
1440 const struct GNUNET_NETWORK_Handle *read_nh,
1441 const struct GNUNET_NETWORK_Handle *write_nh,
1442 const struct GNUNET_DISK_FileHandle *read_fh,
1443 const struct GNUNET_DISK_FileHandle *write_fh,
1445 void *task_cls)
1446{
1447 struct GNUNET_SCHEDULER_Task *t;
1448
1449 /* scheduler must be running */
1451 GNUNET_assert (NULL != task);
1454 init_fd_info (t,
1455 &read_nh,
1456 read_nh ? 1 : 0,
1457 &write_nh,
1458 write_nh ? 1 : 0,
1459 &read_fh,
1460 read_fh ? 1 : 0,
1461 &write_fh,
1462 write_fh ? 1 : 0);
1463 t->callback = task;
1464 t->callback_cls = task_cls;
1465#if DEBUG_FDS
1466 check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1467 check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1468 check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1469 check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1470#endif
1471#if PROFILE_DELAYS
1472 t->start_time = GNUNET_TIME_absolute_get ();
1473#endif
1480 t);
1483 t->priority);
1484 init_backtrace (t);
1485 return t;
1486}
1487
1488
1509struct GNUNET_SCHEDULER_Task *
1511 struct GNUNET_NETWORK_Handle *rfd,
1513 void *task_cls)
1514{
1517 rfd, task, task_cls);
1518}
1519
1520
1543struct GNUNET_SCHEDULER_Task *
1546 priority,
1547 struct GNUNET_NETWORK_Handle *rfd,
1549 void *task_cls)
1550{
1552 rfd,
1553 GNUNET_YES,
1554 GNUNET_NO,
1555 task, task_cls);
1556}
1557
1558
1580struct GNUNET_SCHEDULER_Task *
1582 struct GNUNET_NETWORK_Handle *wfd,
1584 void *task_cls)
1585{
1588 wfd,
1590 task, task_cls);
1591}
1592
1593
1617struct GNUNET_SCHEDULER_Task *
1620 struct GNUNET_NETWORK_Handle *fd,
1621 int on_read,
1622 int on_write,
1624 void *task_cls)
1625{
1626 /* scheduler must be running */
1628 GNUNET_assert (on_read || on_write);
1630 return add_without_sets (delay, priority,
1631 on_read ? fd : NULL,
1632 on_write ? fd : NULL,
1633 NULL,
1634 NULL,
1635 task, task_cls);
1636}
1637
1638
1659struct GNUNET_SCHEDULER_Task *
1661 const struct GNUNET_DISK_FileHandle *rfd,
1663 void *task_cls)
1664{
1667 rfd, GNUNET_YES, GNUNET_NO,
1668 task, task_cls);
1669}
1670
1671
1692struct GNUNET_SCHEDULER_Task *
1694 const struct GNUNET_DISK_FileHandle *wfd,
1696 void *task_cls)
1697{
1700 wfd, GNUNET_NO, GNUNET_YES,
1701 task, task_cls);
1702}
1703
1704
1728struct GNUNET_SCHEDULER_Task *
1731 priority,
1732 const struct
1734 int on_read, int on_write,
1736 void *task_cls)
1737{
1738 /* scheduler must be running */
1740 GNUNET_assert (on_read || on_write);
1741 GNUNET_assert (fd->fd >= 0);
1742 return add_without_sets (delay, priority,
1743 NULL,
1744 NULL,
1745 on_read ? fd : NULL,
1746 on_write ? fd : NULL,
1747 task, task_cls);
1748}
1749
1750
1751static void
1752extract_handles (const struct GNUNET_NETWORK_FDSet *fdset,
1753 const struct GNUNET_NETWORK_Handle ***ntarget,
1754 unsigned int *extracted_nhandles,
1755 const struct GNUNET_DISK_FileHandle ***ftarget,
1756 unsigned int *extracted_fhandles)
1757{
1758 // FIXME: this implementation only works for unix, for WIN32 the file handles
1759 // in fdset must be handled separately
1760 const struct GNUNET_NETWORK_Handle **nhandles;
1761 const struct GNUNET_DISK_FileHandle **fhandles;
1762 unsigned int nhandles_len;
1763 unsigned int fhandles_len;
1764
1765 nhandles = NULL;
1766 fhandles = NULL;
1767 nhandles_len = 0;
1768 fhandles_len = 0;
1769 for (int sock = 0; sock != fdset->nsds; ++sock)
1770 {
1771 if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1772 {
1773 struct GNUNET_NETWORK_Handle *nhandle;
1774 struct GNUNET_DISK_FileHandle *fhandle;
1775
1776 nhandle = GNUNET_NETWORK_socket_box_native (sock);
1777 if (NULL != nhandle)
1778 {
1779 GNUNET_array_append (nhandles, nhandles_len, nhandle);
1780 }
1781 else
1782 {
1783 fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1784 if (NULL != fhandle)
1785 {
1786 GNUNET_array_append (fhandles, fhandles_len, fhandle);
1787 }
1788 else
1789 {
1790 GNUNET_assert (0);
1791 }
1792 }
1793 }
1794 }
1795 *ntarget = nhandles_len > 0 ? nhandles : NULL;
1796 *ftarget = fhandles_len > 0 ? fhandles : NULL;
1797 *extracted_nhandles = nhandles_len;
1798 *extracted_fhandles = fhandles_len;
1799}
1800
1801
1833struct GNUNET_SCHEDULER_Task *
1835 struct GNUNET_TIME_Relative delay,
1836 const struct GNUNET_NETWORK_FDSet *rs,
1837 const struct GNUNET_NETWORK_FDSet *ws,
1839 void *task_cls)
1840{
1841 struct GNUNET_SCHEDULER_Task *t;
1842 const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1843 const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1844 const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1845 const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1846 unsigned int read_nhandles_len = 0;
1847 unsigned int write_nhandles_len = 0;
1848 unsigned int read_fhandles_len = 0;
1849 unsigned int write_fhandles_len = 0;
1850 int no_rs = (NULL == rs);
1851 int no_ws = (NULL == ws);
1852 int empty_rs = (NULL != rs) && (0 == rs->nsds);
1853 int empty_ws = (NULL != ws) && (0 == ws->nsds);
1854 int no_fds = (no_rs && no_ws) ||
1855 (empty_rs && empty_ws) ||
1856 (no_rs && empty_ws) ||
1857 (no_ws && empty_rs);
1858 int no_fds_extracted;
1859
1860 /* scheduler must be running */
1862 GNUNET_assert (NULL != task);
1863 if (! no_fds)
1864 {
1865 if (NULL != rs)
1866 {
1867 extract_handles (rs,
1868 &read_nhandles,
1869 &read_nhandles_len,
1870 &read_fhandles,
1871 &read_fhandles_len);
1872 }
1873 if (NULL != ws)
1874 {
1875 extract_handles (ws,
1876 &write_nhandles,
1877 &write_nhandles_len,
1878 &write_fhandles,
1879 &write_fhandles_len);
1880 }
1881 }
1889 no_fds_extracted = (0 == read_nhandles_len) &&
1890 (0 == read_fhandles_len) &&
1891 (0 == write_nhandles_len) &&
1892 (0 == write_fhandles_len);
1893 if (no_fds || no_fds_extracted)
1895 prio,
1896 task,
1897 task_cls);
1900 init_fd_info (t,
1901 read_nhandles,
1902 read_nhandles_len,
1903 write_nhandles,
1904 write_nhandles_len,
1905 read_fhandles,
1906 read_fhandles_len,
1907 write_fhandles,
1908 write_fhandles_len);
1909 t->callback = task;
1910 t->callback_cls = task_cls;
1912 /* free the arrays of pointers to network / file handles, the actual
1913 * handles will be freed in destroy_task */
1914 GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1915 GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1916 GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1917 GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1918#if PROFILE_DELAYS
1919 t->start_time = GNUNET_TIME_absolute_get ();
1920#endif
1922 t->priority =
1923 check_priority ((prio ==
1925 prio);
1929 t);
1932 t->priority);
1934 "Adding task %p\n",
1935 t);
1936 init_backtrace (t);
1937 return t;
1938}
1939
1940
1952void
1954 struct GNUNET_SCHEDULER_FdInfo *fdi)
1955{
1956 enum GNUNET_SCHEDULER_Reason reason;
1957
1958 reason = task->reason;
1959 if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1960 (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1962 if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1963 (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1966 task->reason = reason;
1967 if (GNUNET_NO == task->in_ready_list)
1968 {
1971 task);
1972 queue_ready_task (task);
1973 }
1974}
1975
1976
1997int
1999{
2000 struct GNUNET_SCHEDULER_Task *pos;
2001 struct GNUNET_TIME_Absolute now;
2002
2003 /* check for tasks that reached the timeout! */
2004 now = GNUNET_TIME_absolute_get ();
2006 while (NULL != pos)
2007 {
2008 struct GNUNET_SCHEDULER_Task *next = pos->next;
2009 if (now.abs_value_us >= pos->timeout.abs_value_us)
2011 if (0 == pos->reason)
2012 break;
2015 pos);
2016 if (pending_timeout_last == pos)
2017 pending_timeout_last = NULL;
2018 queue_ready_task (pos);
2019 pos = next;
2020 }
2021 pos = pending_head;
2022 while (NULL != pos)
2023 {
2024 struct GNUNET_SCHEDULER_Task *next = pos->next;
2025 if (now.abs_value_us >= pos->timeout.abs_value_us)
2026 {
2030 pos);
2031 queue_ready_task (pos);
2032 }
2033 pos = next;
2034 }
2035
2036 if (0 == ready_count)
2037 {
2039
2040 if (timeout.abs_value_us > now.abs_value_us)
2041 {
2056 "GNUNET_SCHEDULER_do_work did not find any ready "
2057 "tasks and timeout has not been reached yet.\n");
2058 }
2059 else
2060 {
2065 GNUNET_assert (0);
2066 }
2067 }
2068 else
2069 {
2070 /* find out which task priority level we are going to
2071 process this time */
2074 /* yes, p>0 is correct, 0 is "KEEP" which should
2075 * always be an empty queue (see assertion)! */
2077 work_priority > 0;
2078 work_priority--)
2079 {
2081 if (NULL != pos)
2082 break;
2083 }
2084 GNUNET_assert (NULL != pos); /* ready_count wrong? */
2085
2086 /* process all *existing* tasks at this priority
2087 level, then yield */
2089 while (NULL != (pos = ready_head[work_priority])
2090 && pos != &pass_end_marker)
2091 {
2094 pos);
2095 ready_count--;
2098 active_task = pos;
2099#if PROFILE_DELAYS
2100 if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2101 DELAY_THRESHOLD.rel_value_us)
2102 {
2104 "Task %p took %s to be scheduled\n",
2105 pos,
2107 GNUNET_TIME_absolute_get_duration (pos->start_time),
2108 GNUNET_YES));
2109 }
2110#endif
2111 tc.reason = pos->reason;
2114 // FIXME: do we have to remove FdInfos from fds if they are not ready?
2115 tc.fds_len = pos->fds_len;
2116 tc.fds = pos->fds;
2117 for (unsigned int i = 0; i != pos->fds_len; ++i)
2118 {
2119 struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2120 if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2121 {
2123 fdi->sock);
2124 }
2125 if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2126 {
2128 fdi->sock);
2129 }
2130 }
2131 tc.read_ready = sh->rs;
2132 tc.write_ready = sh->ws;
2134 "Running task %p\n",
2135 pos);
2136 GNUNET_assert (NULL != pos->callback);
2137 {
2138 struct GNUNET_AsyncScopeSave old_scope;
2139 if (pos->scope.have_scope)
2140 GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2141 else
2142 GNUNET_async_scope_get (&old_scope);
2143 pos->callback (pos->callback_cls);
2144 GNUNET_async_scope_restore (&old_scope);
2145 }
2146 if (NULL != pos->fds)
2147 {
2148 int del_result = scheduler_driver->del (scheduler_driver->cls,
2149 pos);
2150 if (GNUNET_OK != del_result)
2151 {
2153 "driver could not delete task %p\n", pos);
2154 GNUNET_assert (0);
2155 }
2156 }
2157 active_task = NULL;
2158 dump_backtrace (pos);
2159 destroy_task (pos);
2160 }
2162 }
2164 if (0 == ready_count)
2165 {
2167 get_timeout ());
2168 return GNUNET_NO;
2169 }
2172 return GNUNET_YES;
2173}
2174
2175
2209{
2211 const struct GNUNET_DISK_FileHandle *pr;
2212
2213 /* scheduler must not be running */
2216 /* general set-up */
2222 my_pid = getpid ();
2223 scheduler_driver = driver;
2224
2225 /* install signal handlers */
2227 "Registering signal handlers\n");
2228 sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2230 sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2232#if (SIGTERM != GNUNET_TERM_SIG)
2235#endif
2236 sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2238 sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2240 sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2242
2243 /* Setup initial tasks */
2246 /* ensure this task runs first, by using a priority level reserved for
2247 the scheduler (not really shutdown, but start-up ;-) */
2251 NULL);
2254 pr,
2256 NULL);
2259 get_timeout ());
2260 /* begin main event loop */
2264 return sh;
2265}
2266
2267
2282void
2284{
2285 GNUNET_break (NULL == pending_head);
2287 GNUNET_break (NULL == shutdown_head);
2288 for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2289 {
2290 GNUNET_break (NULL == ready_head[i]);
2291 }
2294
2295 /* uninstall signal handlers */
2298#if (SIGTERM != GNUNET_TERM_SIG)
2300#endif
2305 shutdown_pipe_handle = NULL;
2306 scheduler_driver = NULL;
2307 GNUNET_free (sh);
2308}
2309
2310
2311static enum GNUNET_GenericReturnValue
2313 struct DriverContext *context)
2314{
2315 struct GNUNET_NETWORK_FDSet *rs;
2316 struct GNUNET_NETWORK_FDSet *ws;
2317 int select_result;
2318
2319 GNUNET_assert (NULL != context);
2322 while ((NULL != context->scheduled_head) ||
2323 (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2324 context->timeout.abs_value_us))
2325 {
2326 struct GNUNET_TIME_Relative time_remaining;
2327
2329 "select timeout = %s\n",
2331
2334
2335 for (struct Scheduled *pos = context->scheduled_head;
2336 NULL != pos;
2337 pos = pos->next)
2338 {
2339 if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2340 {
2341 GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2342 }
2343 if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2344 {
2345 GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2346 }
2347 }
2348 time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2349 if (0 < ready_count)
2350 time_remaining = GNUNET_TIME_UNIT_ZERO;
2351 if (NULL == scheduler_select)
2352 {
2353 select_result = GNUNET_NETWORK_socket_select (rs,
2354 ws,
2355 NULL,
2356 time_remaining);
2357 }
2358 else
2359 {
2360 select_result = scheduler_select (scheduler_select_cls,
2361 rs,
2362 ws,
2363 NULL,
2364 time_remaining);
2365 }
2366 if (select_result == GNUNET_SYSERR)
2367 {
2368 if (errno == EINTR)
2369 continue;
2370
2372 "select");
2373#if USE_LSOF
2374 char lsof[512];
2375
2376 snprintf (lsof,
2377 sizeof(lsof),
2378 "lsof -p %d",
2379 getpid ());
2380 (void) close (1);
2381 (void) dup2 (2, 1);
2382 if (0 != system (lsof))
2384 "system");
2385#endif
2386#if DEBUG_FDS
2387 for (struct Scheduled *s = context->scheduled_head;
2388 NULL != s;
2389 s = s->next)
2390 {
2391 int flags = fcntl (s->fdi->sock,
2392 F_GETFD);
2393
2394 if ((flags == -1) &&
2395 (EBADF == errno))
2396 {
2398 "Got invalid file descriptor %d!\n",
2399 s->fdi->sock);
2400#if EXECINFO
2401 dump_backtrace (s->task);
2402#endif
2403 }
2404 }
2405#endif
2406 GNUNET_assert (0);
2409 return GNUNET_SYSERR;
2410 }
2411 if (select_result > 0)
2412 {
2413 for (struct Scheduled *pos = context->scheduled_head;
2414 NULL != pos;
2415 pos = pos->next)
2416 {
2417 int is_ready = GNUNET_NO;
2418
2419 if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2420 (GNUNET_YES ==
2422 pos->fdi->sock)) )
2423 {
2424 pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2425 is_ready = GNUNET_YES;
2426 }
2427 if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2428 (GNUNET_YES ==
2430 pos->fdi->sock)) )
2431 {
2432 pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2433 is_ready = GNUNET_YES;
2434 }
2435 if (GNUNET_YES == is_ready)
2436 {
2437 GNUNET_SCHEDULER_task_ready (pos->task,
2438 pos->fdi);
2439 }
2440 }
2441 }
2443 {
2445 "scheduler has more tasks ready!\n");
2446 }
2447 }
2450
2451 if ( (NULL == context->scheduled_head) &&
2452 (NULL != pending_timeout_head) &&
2453 (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us ==
2454 context->timeout.abs_value_us) )
2455 {
2456 /* Only remaining task has timeout of 'forever'.
2457 We exit here more as sanity measure, as just
2458 waiting forever isn't exactly useful. Still,
2459 this is indicative of a bug in the client code. */
2460 GNUNET_break (0);
2461 return GNUNET_NO;
2462 }
2463 return GNUNET_OK;
2464}
2465
2466
2467static int
2468select_add (void *cls,
2469 struct GNUNET_SCHEDULER_Task *task,
2470 struct GNUNET_SCHEDULER_FdInfo *fdi)
2471{
2472 struct DriverContext *context = cls;
2473 struct Scheduled *scheduled;
2474
2475 GNUNET_assert (NULL != context);
2476 GNUNET_assert (NULL != task);
2477 GNUNET_assert (NULL != fdi);
2479 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2480
2481 if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2482 {
2483 /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2484 return GNUNET_SYSERR;
2485 }
2486
2487 scheduled = GNUNET_new (struct Scheduled);
2488 scheduled->task = task;
2489 scheduled->fdi = fdi;
2490 scheduled->et = fdi->et;
2491
2492 GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2493 context->scheduled_tail,
2494 scheduled);
2495 return GNUNET_OK;
2496}
2497
2498
2499static int
2500select_del (void *cls,
2502{
2503 struct DriverContext *context;
2504 struct Scheduled *pos;
2505 int ret;
2506
2507 GNUNET_assert (NULL != cls);
2508
2509 context = cls;
2511 pos = context->scheduled_head;
2512 while (NULL != pos)
2513 {
2514 struct Scheduled *next = pos->next;
2515 if (pos->task == task)
2516 {
2517 GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2518 context->scheduled_tail,
2519 pos);
2520 GNUNET_free (pos);
2521 ret = GNUNET_OK;
2522 }
2523 pos = next;
2524 }
2525 return ret;
2526}
2527
2528
2529static void
2530select_set_wakeup (void *cls,
2531 struct GNUNET_TIME_Absolute dt)
2532{
2533 struct DriverContext *context = cls;
2534
2535 GNUNET_assert (NULL != context);
2536 context->timeout = dt;
2537}
2538
2539
2547{
2548 struct GNUNET_SCHEDULER_Driver *select_driver;
2549
2550 select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2551
2552 select_driver->add = &select_add;
2553 select_driver->del = &select_del;
2554 select_driver->set_wakeup = &select_set_wakeup;
2555
2556 return select_driver;
2557}
2558
2559
2572void
2574{
2575 struct GNUNET_AsyncScopeSave dummy_old_scope;
2576
2577 GNUNET_assert (NULL != active_task);
2578 /* Since we're in a task, the context will be automatically
2579 restored by the scheduler. */
2580 GNUNET_async_scope_enter (aid, &dummy_old_scope);
2581}
2582
2583
2584/* 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_OS_Process * p
Helper process we started.
Definition gnunet-uri.c:38
static struct GNUNET_SCHEDULER_Task * t
Main task.
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:1645
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:710
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition disk.c:1468
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition disk.c:1615
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:1354
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:673
@ 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:567
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:1511
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:1372
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition scheduler.c:725
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:1694
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition scheduler.c:2284
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:1545
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:1954
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:1074
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:1661
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:1999
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:1582
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:1835
unsigned int GNUNET_SCHEDULER_get_load(enum GNUNET_SCHEDULER_Priority p)
Get information about the current load of this scheduler.
Definition scheduler.c:775
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:758
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:1730
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:1254
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:1339
struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select()
Obtain the driver for using select() as the event loop.
Definition scheduler.c:2547
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:2574
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
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:447
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:1304
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:1619
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:1277
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:1207
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:1118
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:2209
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:1231
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:599
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:660
#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:672
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition scheduler.c:600
static void driver_add_multiple(struct GNUNET_SCHEDULER_Task *t)
calls the given function func on each FdInfo related to t.
Definition scheduler.c:914
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:393
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition scheduler.c:2531
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition scheduler.c:621
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:462
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:546
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition scheduler.c:2501
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:387
static struct GNUNET_SCHEDULER_Task * active_task
ID of the task that is running right now.
Definition scheduler.c:368
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:379
static enum GNUNET_SCHEDULER_Priority current_priority
Priority of the task running right now.
Definition scheduler.c:404
static struct GNUNET_SCHEDULER_Task * pending_head
Head of list of tasks waiting for an event.
Definition scheduler.c:324
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:477
static void remove_pass_end_marker()
Definition scheduler.c:515
#define DELAY_THRESHOLD
Task that were in the queue for longer than this are reported if PROFILE_DELAYS is active.
Definition scheduler.c:74
static unsigned int ready_count
Number of tasks on the ready list.
Definition scheduler.c:398
static struct GNUNET_DISK_PipeHandle * shutdown_pipe_handle
Pipe used to communicate shutdown via signal.
Definition scheduler.c:660
static const struct GNUNET_SCHEDULER_Driver * scheduler_driver
The driver used for the event loop.
Definition scheduler.c:319
static struct GNUNET_SCHEDULER_Task * pending_timeout_head
List of tasks waiting ONLY for a timeout event.
Definition scheduler.c:348
static void install_parent_control_handler(void *cls)
Definition scheduler.c:936
static int select_add(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Definition scheduler.c:2469
static GNUNET_SCHEDULER_select scheduler_select
Function to use as a select() in the scheduler.
Definition scheduler.c:426
static enum GNUNET_SCHEDULER_Priority work_priority
Priority used currently in GNUNET_SCHEDULER_do_work().
Definition scheduler.c:420
static void shutdown_if_no_lifeness(void)
Definition scheduler.c:699
static void * scheduler_select_cls
Closure for scheduler_select.
Definition scheduler.c:436
static struct GNUNET_SCHEDULER_Task * pending_timeout_tail
List of tasks waiting ONLY for a timeout event.
Definition scheduler.c:357
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:373
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:256
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:1439
static int current_lifeness
Value of the 'lifeness' flag for the current task.
Definition scheduler.c:415
static void set_work_priority(enum GNUNET_SCHEDULER_Priority p)
Definition scheduler.c:528
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition scheduler.c:1046
static enum GNUNET_SCHEDULER_Priority max_priority_added
Priority of the highest task added in the current select iteration.
Definition scheduler.c:410
static struct GNUNET_SCHEDULER_Task * pending_timeout_last
Last inserted task waiting ONLY for a timeout event.
Definition scheduler.c:363
static void sighandler_shutdown(void)
Signal handler called for signals that should cause us to shutdown.
Definition scheduler.c:682
#define LOG(kind,...)
Definition scheduler.c:32
static void shutdown_pipe_cb(void *cls)
Definition scheduler.c:945
#define LOG_STRERROR(kind, syscall)
Definition scheduler.c:34
static enum GNUNET_GenericReturnValue select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition scheduler.c:2313
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:797
static struct GNUNET_SCHEDULER_Task * pending_tail
Tail of list of tasks waiting for an event.
Definition scheduler.c:329
static struct GNUNET_SCHEDULER_Task * shutdown_tail
Tail of list of tasks waiting for shutdown.
Definition scheduler.c:339
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:431
static struct GNUNET_SCHEDULER_Task * shutdown_head
Head of list of tasks waiting for shutdown.
Definition scheduler.c:334
static pid_t my_pid
Process ID of this process at the time we installed the various signal handlers.
Definition scheduler.c:666
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:1753
Driver context used by GNUNET_SCHEDULER_run.
Definition scheduler.c:291
struct Scheduled * scheduled_head
the head of a DLL containing information about the events the select driver is waiting for
Definition scheduler.c:296
struct GNUNET_TIME_Absolute timeout
the time when the select driver will wake up again (after calling select)
Definition scheduler.c:308
struct Scheduled * scheduled_tail
the tail of a DLL containing information about the events the select driver is waiting for
Definition scheduler.c:302
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:83
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:136
enum GNUNET_SCHEDULER_Priority priority
Task priority.
Definition scheduler.c:204
struct GNUNET_SCHEDULER_Task * prev
This is a linked list.
Definition scheduler.c:145
void * callback_cls
Closure for the callback.
Definition scheduler.c:155
int in_ready_list
Is this task in the ready list?
Definition scheduler.c:230
int lifeness
Should the existence of this task in the queue be counted as reason to not shutdown the scheduler?
Definition scheduler.c:220
enum GNUNET_SCHEDULER_Reason reason
Why is the task ready? Set after task is added to ready queue.
Definition scheduler.c:199
int own_handles
Do we own the network and file handles referenced by the FdInfo structs in the fds array.
Definition scheduler.c:179
struct GNUNET_AsyncScopeSave scope
Asynchronous scope of the task that scheduled this scope,.
Definition scheduler.c:248
struct GNUNET_SCHEDULER_Task * next
This is a linked list.
Definition scheduler.c:140
int on_shutdown
Is this task run on shutdown?
Definition scheduler.c:225
struct GNUNET_SCHEDULER_FdInfo * fds
Information about which FDs are ready for this task (and why).
Definition scheduler.c:160
unsigned int fds_len
Size of the fds array.
Definition scheduler.c:172
struct GNUNET_TIME_Absolute timeout
Absolute timeout value for the task, or GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout".
Definition scheduler.c:185
GNUNET_SCHEDULER_TaskCallback callback
Function to run when ready.
Definition scheduler.c:150
int write_fd
Set if we only wait for writing to a single FD, otherwise -1.
Definition scheduler.c:214
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:167
int read_fd
Set if we only wait for reading from a single FD, otherwise -1.
Definition scheduler.c:209
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:263
struct Scheduled * next
Definition scheduler.c:266
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:283
struct Scheduled * prev
Definition scheduler.c:264
struct GNUNET_SCHEDULER_FdInfo * fdi
information about the network socket / file descriptor where the event is expected to occur
Definition scheduler.c:277
struct GNUNET_SCHEDULER_Task * task
the task, the event is related to
Definition scheduler.c:271

◆ 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 68 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 74 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 462 of file scheduler.c.

463{
464 if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
465 return p;
466 GNUNET_assert (0);
467 return 0; /* make compiler happy */
468}

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 477 of file scheduler.c.

478{
479 struct GNUNET_SCHEDULER_Task *pos;
480 struct GNUNET_TIME_Absolute now;
482
486 if (NULL != pos)
487 {
488 if (0 != pos->reason)
489 {
490 return now;
491 }
492 else
493 {
494 timeout = pos->timeout;
495 }
496 }
497 for (pos = pending_head; NULL != pos; pos = pos->next)
498 {
499 if (0 != pos->reason)
500 {
501 return now;
502 }
503 else if ((pos->timeout.abs_value_us !=
504 GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
505 (timeout.abs_value_us > pos->timeout.abs_value_us))
506 {
507 timeout = pos->timeout;
508 }
509 }
510 return timeout;
511}

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 515 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 528 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 546 of file scheduler.c.

547{
549
551 ready_tail[p],
552 task);
553 if (p > work_priority)
556 ready_count++;
557}

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 600 of file scheduler.c.

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

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 621 of file scheduler.c.

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

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 672 of file scheduler.c.

673{
674 return;
675}

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 682 of file scheduler.c.

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

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 699 of file scheduler.c.

700{
701 struct GNUNET_SCHEDULER_Task *t;
702
703 if (ready_count > 0)
704 return;
705 for (t = pending_head; NULL != t; t = t->next)
706 if (GNUNET_YES == t->lifeness)
707 return;
708 for (t = shutdown_head; NULL != t; t = t->next)
709 if (GNUNET_YES == t->lifeness)
710 return;
711 for (t = pending_timeout_head; NULL != t; t = t->next)
712 if (GNUNET_YES == t->lifeness)
713 return;
714 /* No lifeness! */
716}

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 2313 of file scheduler.c.

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

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 797 of file scheduler.c.

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

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 914 of file scheduler.c.

915{
916 struct GNUNET_SCHEDULER_FdInfo *fdi;
917 int success = GNUNET_YES;
918
919 for (unsigned int i = 0; i != t->fds_len; ++i)
920 {
921 fdi = &t->fds[i];
923 t,
924 fdi) && success;
926 }
927 if (GNUNET_YES != success)
928 {
930 "driver could not add task\n");
931 }
932}

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 936 of file scheduler.c.

937{
938 (void) cls;
941}

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 945 of file scheduler.c.

946{
947 char c;
948 const struct GNUNET_DISK_FileHandle *pr;
949
950 (void) cls;
951 shutdown_pipe_task = NULL;
955 /* consume the signal */
956 GNUNET_DISK_file_read (pr, &c, sizeof(c));
957 /* mark all active tasks as ready due to shutdown */
961 pr,
963 NULL);
964}

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 1046 of file scheduler.c.

1047{
1048#if EXECINFO
1049 void *backtrace_array[MAX_TRACE_DEPTH];
1050
1051 t->num_backtrace_strings
1052 = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1053 t->backtrace_strings =
1054 backtrace_symbols (backtrace_array,
1055 t->num_backtrace_strings);
1056 dump_backtrace (t);
1057#else
1058 (void) t;
1059#endif
1060}

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 1439 of file scheduler.c.

1447{
1448 struct GNUNET_SCHEDULER_Task *t;
1449
1450 /* scheduler must be running */
1452 GNUNET_assert (NULL != task);
1455 init_fd_info (t,
1456 &read_nh,
1457 read_nh ? 1 : 0,
1458 &write_nh,
1459 write_nh ? 1 : 0,
1460 &read_fh,
1461 read_fh ? 1 : 0,
1462 &write_fh,
1463 write_fh ? 1 : 0);
1464 t->callback = task;
1465 t->callback_cls = task_cls;
1466#if DEBUG_FDS
1467 check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1468 check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1469 check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1470 check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1471#endif
1472#if PROFILE_DELAYS
1473 t->start_time = GNUNET_TIME_absolute_get ();
1474#endif
1481 t);
1484 t->priority);
1485 init_backtrace (t);
1486 return t;
1487}

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 1753 of file scheduler.c.

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

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 2469 of file scheduler.c.

2472{
2473 struct DriverContext *context = cls;
2474 struct Scheduled *scheduled;
2475
2476 GNUNET_assert (NULL != context);
2477 GNUNET_assert (NULL != task);
2478 GNUNET_assert (NULL != fdi);
2480 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2481
2482 if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2483 {
2484 /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2485 return GNUNET_SYSERR;
2486 }
2487
2488 scheduled = GNUNET_new (struct Scheduled);
2489 scheduled->task = task;
2490 scheduled->fdi = fdi;
2491 scheduled->et = fdi->et;
2492
2493 GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2494 context->scheduled_tail,
2495 scheduled);
2496 return GNUNET_OK;
2497}

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 2501 of file scheduler.c.

2503{
2504 struct DriverContext *context;
2505 struct Scheduled *pos;
2506 int ret;
2507
2508 GNUNET_assert (NULL != cls);
2509
2510 context = cls;
2512 pos = context->scheduled_head;
2513 while (NULL != pos)
2514 {
2515 struct Scheduled *next = pos->next;
2516 if (pos->task == task)
2517 {
2518 GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2519 context->scheduled_tail,
2520 pos);
2521 GNUNET_free (pos);
2522 ret = GNUNET_OK;
2523 }
2524 pos = next;
2525 }
2526 return ret;
2527}

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 2531 of file scheduler.c.

2533{
2534 struct DriverContext *context = cls;
2535
2536 GNUNET_assert (NULL != context);
2537 context->timeout = dt;
2538}

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 256 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 329 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 334 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 339 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 348 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 357 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 363 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 368 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 374 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 380 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 387 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 393 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 404 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 410 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 426 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 431 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 436 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 660 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 666 of file scheduler.c.

Referenced by GNUNET_SCHEDULER_driver_init(), and sighandler_shutdown().