GNUnet  0.11.x
scheduler.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2009-2017 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "disk.h"
28 // DEBUG
29 #include <inttypes.h>
30 
31 #define LOG(kind, ...) GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__)
32 
33 #define LOG_STRERROR(kind, syscall) GNUNET_log_from_strerror (kind, \
34  "util-scheduler", \
35  syscall)
36 
37 
38 #if HAVE_EXECINFO_H
39 #include "execinfo.h"
40 
45 #define USE_LSOF GNUNET_NO
46 
50 #define EXECINFO GNUNET_NO
51 
55 #define DEBUG_FDS GNUNET_NO
56 
60 #define MAX_TRACE_DEPTH 50
61 #endif
62 
67 #define PROFILE_DELAYS GNUNET_NO
68 
73 #define DELAY_THRESHOLD GNUNET_TIME_UNIT_SECONDS
74 
75 
82 {
89 
96 
101 
106 
107 #if (SIGTERM != GNUNET_TERM_SIG)
108 
111  struct GNUNET_SIGNAL_Context *shc_gterm;
112 #endif
113 
118 
123 
128 };
129 
130 
135 {
140 
145 
150 
155 
160 
167 
171  unsigned int fds_len;
172 
179 
185 
186 #if PROFILE_DELAYS
187 
191 #endif
192 
199 
204 
208  int read_fd;
209 
213  int write_fd;
214 
219  int lifeness;
220 
225 
230 
231 #if EXECINFO
232 
236  char **backtrace_strings;
237 
241  int num_backtrace_strings;
242 #endif
243 
248 };
249 
250 
254 struct Scheduled
255 {
256  struct Scheduled *prev;
257 
258  struct Scheduled *next;
259 
264 
270 
276 };
277 
278 
283 {
289 
295 
301 };
302 
303 
312 
317 
322 
327 
332 
341 
350 
356 
361 
365 static struct
367 
371 static struct
373 
380 
386 
390 static unsigned int ready_count;
391 
397 
403 
407 static int current_lifeness;
408 
413 
419 
424 
428 static void *scheduler_select_cls;
429 
430 
438 void
440  void *new_select_cls)
441 {
442  scheduler_select = new_select;
443  scheduler_select_cls = new_select_cls;
444 }
445 
446 
453 static enum GNUNET_SCHEDULER_Priority
455 {
456  if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
457  return p;
458  GNUNET_assert (0);
459  return 0; /* make compiler happy */
460 }
461 
462 
470 {
471  struct GNUNET_SCHEDULER_Task *pos;
472  struct GNUNET_TIME_Absolute now;
473  struct GNUNET_TIME_Absolute timeout;
474 
475  pos = pending_timeout_head;
476  now = GNUNET_TIME_absolute_get ();
478  if (NULL != pos)
479  {
480  if (0 != pos->reason)
481  {
482  return now;
483  }
484  else
485  {
486  timeout = pos->timeout;
487  }
488  }
489  for (pos = pending_head; NULL != pos; pos = pos->next)
490  {
491  if (0 != pos->reason)
492  {
493  return now;
494  }
495  else if ((pos->timeout.abs_value_us !=
496  GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
497  (timeout.abs_value_us > pos->timeout.abs_value_us))
498  {
499  timeout = pos->timeout;
500  }
501  }
502  return timeout;
503 }
504 
505 
511 static void
513 {
515 
516  GNUNET_CONTAINER_DLL_insert_tail (ready_head[p],
517  ready_tail[p],
518  task);
519  task->in_ready_list = GNUNET_YES;
520  ready_count++;
521 }
522 
523 
530 void
532 {
533  struct GNUNET_SCHEDULER_Task *pos;
534 
536  "GNUNET_SCHEDULER_shutdown\n");
537  if (NULL != install_parent_control_task)
538  {
539  GNUNET_SCHEDULER_cancel (install_parent_control_task);
540  install_parent_control_task = NULL;
541  }
542  if (NULL != shutdown_pipe_task)
543  {
544  GNUNET_SCHEDULER_cancel (shutdown_pipe_task);
545  shutdown_pipe_task = NULL;
546  }
547  while (NULL != (pos = shutdown_head))
548  {
549  GNUNET_CONTAINER_DLL_remove (shutdown_head,
550  shutdown_tail,
551  pos);
553  queue_ready_task (pos);
554  }
555 }
556 
557 
563 static void
565 {
566 #if EXECINFO
567  for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
569  "Task %p trace %u: %s\n",
570  t,
571  i,
572  t->backtrace_strings[i]);
573 #else
574  (void) t;
575 #endif
576 }
577 
578 
584 static void
586 {
588  "destroying task %p\n",
589  t);
590 
591  if (GNUNET_YES == t->own_handles)
592  {
593  for (unsigned int i = 0; i != t->fds_len; ++i)
594  {
595  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
596  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
597  if (fd)
598  {
600  (struct GNUNET_NETWORK_Handle *) fd);
601  }
602  if (fh)
603  {
604  // FIXME: on WIN32 this is not enough! A function
605  // GNUNET_DISK_file_free_memory_only would be nice
606  GNUNET_free_nz ((void *) fh);
607  }
608  }
609  }
610  if (t->fds_len > 1)
611  {
612  GNUNET_array_grow (t->fds, t->fds_len, 0);
613  }
614 #if EXECINFO
615  GNUNET_free (t->backtrace_strings);
616 #endif
617  GNUNET_free (t);
618 }
619 
620 
625 
630 static pid_t my_pid;
631 
635 static void
637 {
638  return;
639 }
640 
641 
643 // * Wait for a short time.
644 // * Sleeps for @a ms ms (as that should be long enough for virtually all
645 // * modern systems to context switch and allow another process to do
646 // * some 'real' work).
647 // *
648 // * @param ms how many ms to wait
649 // */
650 // static void
651 // short_wait (unsigned int ms)
652 // {
653 // struct GNUNET_TIME_Relative timeout;
654 //
655 // timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms);
656 // (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
657 // }
658 
659 
663 static void
665 {
666  static char c;
667  int old_errno = errno; /* backup errno */
668 
669  if (getpid () != my_pid)
670  _exit (1); /* we have fork'ed since the signal handler was created,
671  * ignore the signal, see https://gnunet.org/vfork discussion */
673  (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE),
674  &c, sizeof(c));
675  errno = old_errno;
676 }
677 
678 
679 static void
681 {
682  struct GNUNET_SCHEDULER_Task *t;
683 
684  if (ready_count > 0)
685  return;
686  for (t = pending_head; NULL != t; t = t->next)
687  if (GNUNET_YES == t->lifeness)
688  return;
689  for (t = shutdown_head; NULL != t; t = t->next)
690  if (GNUNET_YES == t->lifeness)
691  return;
692  for (t = pending_timeout_head; NULL != t; t = t->next)
693  if (GNUNET_YES == t->lifeness)
694  return;
695  /* No lifeness! */
697 }
698 
699 
700 static int
702  struct DriverContext *context);
703 
704 
719 void
721  void *task_cls)
722 {
723  struct GNUNET_SCHEDULER_Handle *sh;
724  struct GNUNET_SCHEDULER_Driver *driver;
725  struct DriverContext context = {
726  .scheduled_head = NULL,
727  .scheduled_tail = NULL,
728  .timeout = GNUNET_TIME_absolute_get ()
729  };
730 
731  driver = GNUNET_SCHEDULER_driver_select ();
732  driver->cls = &context;
733  sh = GNUNET_SCHEDULER_driver_init (driver);
735  task_cls,
738  select_loop (sh,
739  &context);
741  GNUNET_free (driver);
742 }
743 
744 
751 const struct GNUNET_SCHEDULER_TaskContext *
753 {
754  GNUNET_assert (NULL != active_task);
755  return &tc;
756 }
757 
758 
768 unsigned int
770 {
771  unsigned int ret;
772 
773  GNUNET_assert (NULL != active_task);
775  return ready_count;
777  p = current_priority;
778  ret = 0;
779  for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)];
780  NULL != pos;
781  pos = pos->next)
782  ret++;
783  return ret;
784 }
785 
786 
787 void
789  const struct GNUNET_NETWORK_Handle *const *read_nh,
790  unsigned int read_nh_len,
791  const struct GNUNET_NETWORK_Handle *const *write_nh,
792  unsigned int write_nh_len,
793  const struct GNUNET_DISK_FileHandle *const *read_fh,
794  unsigned int read_fh_len,
795  const struct GNUNET_DISK_FileHandle *const *write_fh,
796  unsigned int write_fh_len)
797 {
798  // FIXME: if we have exactly two network handles / exactly two file handles
799  // and they are equal, we can make one FdInfo with both
800  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
801  struct GNUNET_SCHEDULER_FdInfo *fdi;
802 
803  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
804  if (1 == t->fds_len)
805  {
806  fdi = &t->fdx;
807  t->fds = fdi;
808  if (1 == read_nh_len)
809  {
810  GNUNET_assert (NULL != read_nh);
811  GNUNET_assert (NULL != *read_nh);
812  fdi->fd = *read_nh;
813  fdi->et = GNUNET_SCHEDULER_ET_IN;
814  fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
815  t->read_fd = fdi->sock;
816  t->write_fd = -1;
817  }
818  else if (1 == write_nh_len)
819  {
820  GNUNET_assert (NULL != write_nh);
821  GNUNET_assert (NULL != *write_nh);
822  fdi->fd = *write_nh;
824  fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
825  t->read_fd = -1;
826  t->write_fd = fdi->sock;
827  }
828  else if (1 == read_fh_len)
829  {
830  GNUNET_assert (NULL != read_fh);
831  GNUNET_assert (NULL != *read_fh);
832  fdi->fh = *read_fh;
833  fdi->et = GNUNET_SCHEDULER_ET_IN;
834  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
835  t->read_fd = fdi->sock;
836  t->write_fd = -1;
837  }
838  else
839  {
840  GNUNET_assert (NULL != write_fh);
841  GNUNET_assert (NULL != *write_fh);
842  fdi->fh = *write_fh;
844  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
845  t->read_fd = -1;
846  t->write_fd = fdi->sock;
847  }
848  }
849  else
850  {
852  t->fds = fdi;
853  t->read_fd = -1;
854  t->write_fd = -1;
855  unsigned int i;
856  for (i = 0; i != read_nh_len; ++i)
857  {
858  fdi->fd = read_nh[i];
859  GNUNET_assert (NULL != fdi->fd);
860  fdi->et = GNUNET_SCHEDULER_ET_IN;
861  fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
862  ++fdi;
863  }
864  for (i = 0; i != write_nh_len; ++i)
865  {
866  fdi->fd = write_nh[i];
867  GNUNET_assert (NULL != fdi->fd);
869  fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
870  ++fdi;
871  }
872  for (i = 0; i != read_fh_len; ++i)
873  {
874  fdi->fh = read_fh[i];
875  GNUNET_assert (NULL != fdi->fh);
876  fdi->et = GNUNET_SCHEDULER_ET_IN;
877  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
878  ++fdi;
879  }
880  for (i = 0; i != write_fh_len; ++i)
881  {
882  fdi->fh = write_fh[i];
883  GNUNET_assert (NULL != fdi->fh);
885  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
886  ++fdi;
887  }
888  }
889 }
890 
891 
905 static void
907 {
908  struct GNUNET_SCHEDULER_FdInfo *fdi;
909  int success = GNUNET_YES;
910 
911  for (unsigned int i = 0; i != t->fds_len; ++i)
912  {
913  fdi = &t->fds[i];
914  success = scheduler_driver->add (scheduler_driver->cls,
915  t,
916  fdi) && success;
918  }
919  if (GNUNET_YES != success)
920  {
922  "driver could not add task\n");
923  }
924 }
925 
926 
927 static void
929 {
930  (void) cls;
931  install_parent_control_task = NULL;
933 }
934 
935 
936 static void
937 shutdown_pipe_cb (void *cls)
938 {
939  char c;
940  const struct GNUNET_DISK_FileHandle *pr;
941 
942  (void) cls;
943  shutdown_pipe_task = NULL;
944  pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
947  /* consume the signal */
948  GNUNET_DISK_file_read (pr, &c, sizeof(c));
949  /* mark all active tasks as ready due to shutdown */
951  shutdown_pipe_task =
953  pr,
955  NULL);
956 }
957 
958 
971 void *
973 {
975  int is_fd_task;
976  void *ret;
977 
979  "canceling task %p\n",
980  task);
981 
982  /* scheduler must be running */
983  GNUNET_assert (NULL != scheduler_driver);
984  is_fd_task = (NULL != task->fds);
985  if (is_fd_task)
986  {
987  int del_result = scheduler_driver->del (scheduler_driver->cls, task);
988  if (GNUNET_OK != del_result)
989  {
991  "driver could not delete task\n");
992  GNUNET_assert (0);
993  }
994  }
995  if (! task->in_ready_list)
996  {
997  if (is_fd_task)
998  {
999  GNUNET_CONTAINER_DLL_remove (pending_head,
1000  pending_tail,
1001  task);
1002  }
1003  else if (GNUNET_YES == task->on_shutdown)
1004  {
1005  GNUNET_CONTAINER_DLL_remove (shutdown_head,
1006  shutdown_tail,
1007  task);
1008  }
1009  else
1010  {
1011  GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
1012  pending_timeout_tail,
1013  task);
1014  if (pending_timeout_last == task)
1015  pending_timeout_last = NULL;
1016  }
1017  }
1018  else
1019  {
1020  p = check_priority (task->priority);
1021  GNUNET_CONTAINER_DLL_remove (ready_head[p],
1022  ready_tail[p],
1023  task);
1024  ready_count--;
1025  }
1026  ret = task->callback_cls;
1027  destroy_task (task);
1028  return ret;
1029 }
1030 
1031 
1037 static void
1039 {
1040 #if EXECINFO
1041  void *backtrace_array[MAX_TRACE_DEPTH];
1042 
1043  t->num_backtrace_strings
1044  = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1045  t->backtrace_strings =
1046  backtrace_symbols (backtrace_array,
1047  t->num_backtrace_strings);
1048  dump_backtrace (t);
1049 #else
1050  (void) t;
1051 #endif
1052 }
1053 
1054 
1065 void
1067  task,
1068  void *task_cls,
1070  reason,
1072  priority)
1073 {
1074  struct GNUNET_SCHEDULER_Task *t;
1075 
1076  /* scheduler must be running */
1077  GNUNET_assert (NULL != scheduler_driver);
1078  GNUNET_assert (NULL != task);
1079  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1080  t->read_fd = -1;
1081  t->write_fd = -1;
1082  t->callback = task;
1083  t->callback_cls = task_cls;
1084 #if PROFILE_DELAYS
1085  t->start_time = GNUNET_TIME_absolute_get ();
1086 #endif
1087  t->reason = reason;
1088  t->priority = check_priority (priority);
1091  "Adding continuation task %p\n",
1092  t);
1093  init_backtrace (t);
1094  queue_ready_task (t);
1095 }
1096 
1097 
1109 struct GNUNET_SCHEDULER_Task *
1113  void *task_cls)
1114 {
1115  struct GNUNET_SCHEDULER_Task *t;
1116  struct GNUNET_SCHEDULER_Task *pos;
1117  struct GNUNET_SCHEDULER_Task *prev;
1118  struct GNUNET_TIME_Relative left;
1119 
1120  /* scheduler must be running */
1121  GNUNET_assert (NULL != scheduler_driver);
1122  GNUNET_assert (NULL != task);
1123  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1125  t->callback = task;
1126  t->callback_cls = task_cls;
1127  t->read_fd = -1;
1128  t->write_fd = -1;
1129 #if PROFILE_DELAYS
1130  t->start_time = GNUNET_TIME_absolute_get ();
1131 #endif
1132  t->timeout = at;
1133  t->priority = check_priority (priority);
1135  init_backtrace (t);
1136 
1138  if (0 == left.rel_value_us)
1139  {
1140  queue_ready_task (t);
1141  if (priority > work_priority)
1142  work_priority = priority;
1143  return t;
1144  }
1145 
1146  /* try tail first (optimization in case we are
1147  * appending to a long list of tasks with timeouts) */
1148  if ((NULL == pending_timeout_head) ||
1149  (at.abs_value_us < pending_timeout_head->timeout.abs_value_us))
1150  {
1151  GNUNET_CONTAINER_DLL_insert (pending_timeout_head,
1152  pending_timeout_tail,
1153  t);
1154  }
1155  else
1156  {
1157  /* first move from heuristic start backwards to before start time */
1158  prev = pending_timeout_last;
1159  while ((NULL != prev) &&
1161  prev = prev->prev;
1162  /* now, move from heuristic start (or head of list) forward to insertion point */
1163  if (NULL == prev)
1164  pos = pending_timeout_head;
1165  else
1166  pos = prev->next;
1167  while ((NULL != pos) && (pos->timeout.abs_value_us <=
1168  t->timeout.abs_value_us))
1169  {
1170  prev = pos;
1171  pos = pos->next;
1172  }
1173  GNUNET_CONTAINER_DLL_insert_after (pending_timeout_head,
1174  pending_timeout_tail,
1175  prev,
1176  t);
1177  }
1178  /* finally, update heuristic insertion point to last insertion... */
1179  pending_timeout_last = t;
1181  "Adding task %p\n",
1182  t);
1183  return t;
1184 }
1185 
1186 
1198 struct GNUNET_SCHEDULER_Task *
1201  priority,
1203  void *task_cls)
1204 {
1207  priority,
1208  task,
1209  task_cls);
1210 }
1211 
1212 
1222 struct GNUNET_SCHEDULER_Task *
1225  void *task_cls)
1226 {
1228  prio,
1229  task,
1230  task_cls);
1231 }
1232 
1233 
1245 struct GNUNET_SCHEDULER_Task *
1248  void *task_cls)
1249 {
1252  task,
1253  task_cls);
1254 }
1255 
1256 
1268 struct GNUNET_SCHEDULER_Task *
1271  void *task_cls)
1272 {
1275  task,
1276  task_cls);
1277 }
1278 
1279 
1295 struct GNUNET_SCHEDULER_Task *
1297  void *task_cls)
1298 {
1299  struct GNUNET_SCHEDULER_Task *t;
1300 
1301  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1303  t->callback = task;
1304  t->callback_cls = task_cls;
1305  t->read_fd = -1;
1306  t->write_fd = -1;
1307 #if PROFILE_DELAYS
1308  t->start_time = GNUNET_TIME_absolute_get ();
1309 #endif
1312  t->on_shutdown = GNUNET_YES;
1314  queue_ready_task (t);
1315  init_backtrace (t);
1316  return t;
1317 }
1318 
1319 
1330 struct GNUNET_SCHEDULER_Task *
1332  void *task_cls)
1333 {
1334  struct GNUNET_SCHEDULER_Task *t;
1335 
1336  /* scheduler must be running */
1337  GNUNET_assert (NULL != scheduler_driver);
1338  GNUNET_assert (NULL != task);
1339  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1341  t->callback = task;
1342  t->callback_cls = task_cls;
1343  t->read_fd = -1;
1344  t->write_fd = -1;
1345 #if PROFILE_DELAYS
1346  t->start_time = GNUNET_TIME_absolute_get ();
1347 #endif
1350  t->on_shutdown = GNUNET_YES;
1351  t->lifeness = GNUNET_NO;
1352  GNUNET_CONTAINER_DLL_insert (shutdown_head,
1353  shutdown_tail,
1354  t);
1356  "Adding shutdown task %p\n",
1357  t);
1358  init_backtrace (t);
1359  return t;
1360 }
1361 
1362 
1377 struct GNUNET_SCHEDULER_Task *
1380  void *task_cls)
1381 {
1382  struct GNUNET_SCHEDULER_Task *ret;
1383 
1384  ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1385  ret->lifeness = lifeness;
1386  return ret;
1387 }
1388 
1389 
1390 #if DEBUG_FDS
1391 
1397 void
1398 check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1399 {
1400  if (-1 != raw_fd)
1401  {
1402  int flags = fcntl (raw_fd, F_GETFD);
1403 
1404  if ((flags == -1) && (errno == EBADF))
1405  {
1407  "Got invalid file descriptor %d!\n",
1408  raw_fd);
1409  init_backtrace (t);
1410  GNUNET_assert (0);
1411  }
1412  }
1413 }
1414 
1415 
1416 #endif
1417 
1418 
1444 static struct GNUNET_SCHEDULER_Task *
1447  const struct GNUNET_NETWORK_Handle *read_nh,
1448  const struct GNUNET_NETWORK_Handle *write_nh,
1449  const struct GNUNET_DISK_FileHandle *read_fh,
1450  const struct GNUNET_DISK_FileHandle *write_fh,
1452  void *task_cls)
1453 {
1454  struct GNUNET_SCHEDULER_Task *t;
1455 
1456  /* scheduler must be running */
1457  GNUNET_assert (NULL != scheduler_driver);
1458  GNUNET_assert (NULL != task);
1459  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1461  init_fd_info (t,
1462  &read_nh,
1463  read_nh ? 1 : 0,
1464  &write_nh,
1465  write_nh ? 1 : 0,
1466  &read_fh,
1467  read_fh ? 1 : 0,
1468  &write_fh,
1469  write_fh ? 1 : 0);
1470  t->callback = task;
1471  t->callback_cls = task_cls;
1472 #if DEBUG_FDS
1473  check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1474  check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1475  check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1476  check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1477 #endif
1478 #if PROFILE_DELAYS
1479  t->start_time = GNUNET_TIME_absolute_get ();
1480 #endif
1483  current_priority : priority);
1485  GNUNET_CONTAINER_DLL_insert (pending_head,
1486  pending_tail,
1487  t);
1488  driver_add_multiple (t);
1490  t->priority);
1491  init_backtrace (t);
1492  return t;
1493 }
1494 
1495 
1516 struct GNUNET_SCHEDULER_Task *
1518  struct GNUNET_NETWORK_Handle *rfd,
1520  void *task_cls)
1521 {
1524  rfd, task, task_cls);
1525 }
1526 
1527 
1550 struct GNUNET_SCHEDULER_Task *
1553  priority,
1554  struct GNUNET_NETWORK_Handle *rfd,
1556  void *task_cls)
1557 {
1558  return GNUNET_SCHEDULER_add_net_with_priority (delay, priority,
1559  rfd,
1560  GNUNET_YES,
1561  GNUNET_NO,
1562  task, task_cls);
1563 }
1564 
1565 
1587 struct GNUNET_SCHEDULER_Task *
1589  struct GNUNET_NETWORK_Handle *wfd,
1591  void *task_cls)
1592 {
1595  wfd,
1597  task, task_cls);
1598 }
1599 
1600 
1624 struct GNUNET_SCHEDULER_Task *
1627  struct GNUNET_NETWORK_Handle *fd,
1628  int on_read,
1629  int on_write,
1631  void *task_cls)
1632 {
1633  /* scheduler must be running */
1634  GNUNET_assert (NULL != scheduler_driver);
1635  GNUNET_assert (on_read || on_write);
1637  return add_without_sets (delay, priority,
1638  on_read ? fd : NULL,
1639  on_write ? fd : NULL,
1640  NULL,
1641  NULL,
1642  task, task_cls);
1643 }
1644 
1645 
1666 struct GNUNET_SCHEDULER_Task *
1668  const struct GNUNET_DISK_FileHandle *rfd,
1670  void *task_cls)
1671 {
1674  rfd, GNUNET_YES, GNUNET_NO,
1675  task, task_cls);
1676 }
1677 
1678 
1699 struct GNUNET_SCHEDULER_Task *
1701  const struct GNUNET_DISK_FileHandle *wfd,
1703  void *task_cls)
1704 {
1707  wfd, GNUNET_NO, GNUNET_YES,
1708  task, task_cls);
1709 }
1710 
1711 
1735 struct GNUNET_SCHEDULER_Task *
1738  priority,
1739  const struct
1741  int on_read, int on_write,
1743  void *task_cls)
1744 {
1745  /* scheduler must be running */
1746  GNUNET_assert (NULL != scheduler_driver);
1747  GNUNET_assert (on_read || on_write);
1748  GNUNET_assert (fd->fd >= 0);
1749  return add_without_sets (delay, priority,
1750  NULL,
1751  NULL,
1752  on_read ? fd : NULL,
1753  on_write ? fd : NULL,
1754  task, task_cls);
1755 }
1756 
1757 
1758 void
1760  const struct GNUNET_NETWORK_Handle ***ntarget,
1761  unsigned int *extracted_nhandles,
1762  const struct GNUNET_DISK_FileHandle ***ftarget,
1763  unsigned int *extracted_fhandles)
1764 {
1765  // FIXME: this implementation only works for unix, for WIN32 the file handles
1766  // in fdset must be handled separately
1767  const struct GNUNET_NETWORK_Handle **nhandles;
1768  const struct GNUNET_DISK_FileHandle **fhandles;
1769  unsigned int nhandles_len;
1770  unsigned int fhandles_len;
1771 
1772  nhandles = NULL;
1773  fhandles = NULL;
1774  nhandles_len = 0;
1775  fhandles_len = 0;
1776  for (int sock = 0; sock != fdset->nsds; ++sock)
1777  {
1778  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1779  {
1780  struct GNUNET_NETWORK_Handle *nhandle;
1781  struct GNUNET_DISK_FileHandle *fhandle;
1782 
1783  nhandle = GNUNET_NETWORK_socket_box_native (sock);
1784  if (NULL != nhandle)
1785  {
1786  GNUNET_array_append (nhandles, nhandles_len, nhandle);
1787  }
1788  else
1789  {
1790  fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1791  if (NULL != fhandle)
1792  {
1793  GNUNET_array_append (fhandles, fhandles_len, fhandle);
1794  }
1795  else
1796  {
1797  GNUNET_assert (0);
1798  }
1799  }
1800  }
1801  }
1802  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1803  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1804  *extracted_nhandles = nhandles_len;
1805  *extracted_fhandles = fhandles_len;
1806 }
1807 
1808 
1840 struct GNUNET_SCHEDULER_Task *
1842  struct GNUNET_TIME_Relative delay,
1843  const struct GNUNET_NETWORK_FDSet *rs,
1844  const struct GNUNET_NETWORK_FDSet *ws,
1846  void *task_cls)
1847 {
1848  struct GNUNET_SCHEDULER_Task *t;
1849  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1850  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1851  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1852  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1853  unsigned int read_nhandles_len = 0;
1854  unsigned int write_nhandles_len = 0;
1855  unsigned int read_fhandles_len = 0;
1856  unsigned int write_fhandles_len = 0;
1857 
1858  /* scheduler must be running */
1859  GNUNET_assert (NULL != scheduler_driver);
1860  GNUNET_assert (NULL != task);
1861  int no_rs = (NULL == rs);
1862  int no_ws = (NULL == ws);
1863  int empty_rs = (NULL != rs) && (0 == rs->nsds);
1864  int empty_ws = (NULL != ws) && (0 == ws->nsds);
1865  int no_fds = (no_rs && no_ws) ||
1866  (empty_rs && empty_ws) ||
1867  (no_rs && empty_ws) ||
1868  (no_ws && empty_rs);
1869  if (! no_fds)
1870  {
1871  if (NULL != rs)
1872  {
1873  extract_handles (rs,
1874  &read_nhandles,
1875  &read_nhandles_len,
1876  &read_fhandles,
1877  &read_fhandles_len);
1878  }
1879  if (NULL != ws)
1880  {
1881  extract_handles (ws,
1882  &write_nhandles,
1883  &write_nhandles_len,
1884  &write_fhandles,
1885  &write_fhandles_len);
1886  }
1887  }int no_fds_extracted = (0 == read_nhandles_len) &&
1895  (0 == read_fhandles_len) &&
1896  (0 == write_nhandles_len) &&
1897  (0 == write_fhandles_len);
1898  if (no_fds || no_fds_extracted)
1900  prio,
1901  task,
1902  task_cls);
1903  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1905  init_fd_info (t,
1906  read_nhandles,
1907  read_nhandles_len,
1908  write_nhandles,
1909  write_nhandles_len,
1910  read_fhandles,
1911  read_fhandles_len,
1912  write_fhandles,
1913  write_fhandles_len);
1914  t->callback = task;
1915  t->callback_cls = task_cls;
1916  t->own_handles = GNUNET_YES;
1917  /* free the arrays of pointers to network / file handles, the actual
1918  * handles will be freed in destroy_task */
1919  GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1920  GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1921  GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1922  GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1923 #if PROFILE_DELAYS
1924  t->start_time = GNUNET_TIME_absolute_get ();
1925 #endif
1927  t->priority =
1928  check_priority ((prio ==
1930  prio);
1932  GNUNET_CONTAINER_DLL_insert (pending_head,
1933  pending_tail,
1934  t);
1935  driver_add_multiple (t);
1937  t->priority);
1939  "Adding task %p\n",
1940  t);
1941  init_backtrace (t);
1942  return t;
1943 }
1944 
1945 
1957 void
1959  struct GNUNET_SCHEDULER_FdInfo *fdi)
1960 {
1961  enum GNUNET_SCHEDULER_Reason reason;
1962 
1963  reason = task->reason;
1964  if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1965  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1967  if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1968  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1971  task->reason = reason;
1972  if (GNUNET_NO == task->in_ready_list)
1973  {
1974  GNUNET_CONTAINER_DLL_remove (pending_head,
1975  pending_tail,
1976  task);
1977  queue_ready_task (task);
1978  }
1979 }
1980 
1981 
2002 int
2004 {
2005  struct GNUNET_SCHEDULER_Task *pos;
2006  struct GNUNET_TIME_Absolute now;
2007 
2008  /* check for tasks that reached the timeout! */
2009  now = GNUNET_TIME_absolute_get ();
2010  pos = pending_timeout_head;
2011  while (NULL != pos)
2012  {
2013  struct GNUNET_SCHEDULER_Task *next = pos->next;
2014  if (now.abs_value_us >= pos->timeout.abs_value_us)
2016  if (0 == pos->reason)
2017  break;
2018  GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
2019  pending_timeout_tail,
2020  pos);
2021  if (pending_timeout_last == pos)
2022  pending_timeout_last = NULL;
2023  queue_ready_task (pos);
2024  pos = next;
2025  }
2026  pos = pending_head;
2027  while (NULL != pos)
2028  {
2029  struct GNUNET_SCHEDULER_Task *next = pos->next;
2030  if (now.abs_value_us >= pos->timeout.abs_value_us)
2031  {
2033  GNUNET_CONTAINER_DLL_remove (pending_head,
2034  pending_tail,
2035  pos);
2036  queue_ready_task (pos);
2037  }
2038  pos = next;
2039  }
2040 
2041  if (0 == ready_count)
2042  {
2043  struct GNUNET_TIME_Absolute timeout = get_timeout ();
2044 
2045  if (timeout.abs_value_us > now.abs_value_us)
2060  "GNUNET_SCHEDULER_do_work did not find any ready "
2061  "tasks and timeout has not been reached yet.\n");
2062  }
2063  else
2064  {
2069  GNUNET_assert (0);
2070  }
2071  }
2072  else
2073  {
2074  /* find out which task priority level we are going to
2075  process this time */
2077  GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]);
2078  /* yes, p>0 is correct, 0 is "KEEP" which should
2079  * always be an empty queue (see assertion)! */
2081  work_priority > 0;
2082  work_priority--)
2083  {
2084  pos = ready_head[work_priority];
2085  if (NULL != pos)
2086  break;
2087  }
2088  GNUNET_assert (NULL != pos); /* ready_count wrong? */
2089 
2090  /* process all tasks at this priority level, then yield */
2091  while (NULL != (pos = ready_head[work_priority]))
2092  {
2093  GNUNET_CONTAINER_DLL_remove (ready_head[work_priority],
2094  ready_tail[work_priority],
2095  pos);
2096  ready_count--;
2097  current_priority = pos->priority;
2098  current_lifeness = pos->lifeness;
2099  active_task = pos;
2100 #if PROFILE_DELAYS
2101  if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2102  DELAY_THRESHOLD.rel_value_us)
2103  {
2105  "Task %p took %s to be scheduled\n",
2106  pos,
2108  GNUNET_TIME_absolute_get_duration (pos->start_time),
2109  GNUNET_YES));
2110  }
2111 #endif
2112  tc.reason = pos->reason;
2115  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2116  tc.fds_len = pos->fds_len;
2117  tc.fds = pos->fds;
2118  for (unsigned int i = 0; i != pos->fds_len; ++i)
2119  {
2120  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2121  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2122  {
2124  fdi->sock);
2125  }
2126  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2127  {
2129  fdi->sock);
2130  }
2131  }
2132  tc.read_ready = sh->rs;
2133  tc.write_ready = sh->ws;
2135  "Running task %p\n",
2136  pos);
2137  GNUNET_assert (NULL != pos->callback);
2138  {
2139  struct GNUNET_AsyncScopeSave old_scope;
2140  if (pos->scope.have_scope)
2141  GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2142  else
2143  GNUNET_async_scope_get (&old_scope);
2144  pos->callback (pos->callback_cls);
2145  GNUNET_async_scope_restore (&old_scope);
2146  }
2147  if (NULL != pos->fds)
2148  {
2149  int del_result = scheduler_driver->del (scheduler_driver->cls, 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  }
2161  }
2163  if (0 == ready_count)
2164  {
2165  scheduler_driver->set_wakeup (scheduler_driver->cls,
2166  get_timeout ());
2167  return GNUNET_NO;
2168  }
2169  scheduler_driver->set_wakeup (scheduler_driver->cls,
2171  return GNUNET_YES;
2172 }
2173 
2174 
2206 struct GNUNET_SCHEDULER_Handle *
2208 {
2209  struct GNUNET_SCHEDULER_Handle *sh;
2210  const struct GNUNET_DISK_FileHandle *pr;
2211 
2212  /* scheduler must not be running */
2213  GNUNET_assert (NULL == scheduler_driver);
2214  GNUNET_assert (NULL == shutdown_pipe_handle);
2215  /* general set-up */
2216  sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle);
2217  shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE);
2218  GNUNET_assert (NULL != shutdown_pipe_handle);
2219  pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
2221  my_pid = getpid ();
2222  scheduler_driver = driver;
2223 
2224  /* install signal handlers */
2226  "Registering signal handlers\n");
2227  sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2229  sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2231 #if (SIGTERM != GNUNET_TERM_SIG)
2234 #endif
2235  sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2236  &sighandler_pipe);
2237  sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2239  sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2241 
2242  /* Setup initial tasks */
2245  /* ensure this task runs first, by using a priority level reserved for
2246  the scheduler (not really shutdown, but start-up ;-) */
2247  install_parent_control_task =
2250  NULL);
2251  shutdown_pipe_task =
2253  pr,
2255  NULL);
2257  scheduler_driver->set_wakeup (scheduler_driver->cls,
2258  get_timeout ());
2259  /* begin main event loop */
2263  return sh;
2264 }
2265 
2266 
2281 void
2283 {
2284  GNUNET_assert (NULL == pending_head);
2285  GNUNET_assert (NULL == pending_timeout_head);
2286  GNUNET_assert (NULL == shutdown_head);
2287  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2288  {
2289  GNUNET_assert (NULL == ready_head[i]);
2290  }
2293 
2294  /* uninstall signal handlers */
2297 #if (SIGTERM != GNUNET_TERM_SIG)
2298  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
2299 #endif
2303  GNUNET_DISK_pipe_close (shutdown_pipe_handle);
2304  shutdown_pipe_handle = NULL;
2305  scheduler_driver = NULL;
2306  GNUNET_free (sh);
2307 }
2308 
2309 
2310 static int
2312  struct DriverContext *context)
2313 {
2314  struct GNUNET_NETWORK_FDSet *rs;
2315  struct GNUNET_NETWORK_FDSet *ws;
2316  int select_result;
2317 
2318  GNUNET_assert (NULL != context);
2321  while ((NULL != context->scheduled_head) ||
2322  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2323  context->timeout.abs_value_us))
2324  {
2325  struct GNUNET_TIME_Relative time_remaining;
2326 
2328  "select timeout = %s\n",
2330 
2333 
2334  for (struct Scheduled *pos = context->scheduled_head;
2335  NULL != pos;
2336  pos = pos->next)
2337  {
2338  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2339  {
2340  GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2341  }
2342  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2343  {
2344  GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2345  }
2346  }
2347  time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2348  if (0 < ready_count)
2349  time_remaining = GNUNET_TIME_UNIT_ZERO;
2350  if (NULL == scheduler_select)
2351  {
2352  select_result = GNUNET_NETWORK_socket_select (rs,
2353  ws,
2354  NULL,
2355  time_remaining);
2356  }
2357  else
2358  {
2359  select_result = scheduler_select (scheduler_select_cls,
2360  rs,
2361  ws,
2362  NULL,
2363  time_remaining);
2364  }
2365  if (select_result == GNUNET_SYSERR)
2366  {
2367  if (errno == EINTR)
2368  continue;
2369 
2371  "select");
2372 #if USE_LSOF
2373  char lsof[512];
2374 
2375  snprintf (lsof,
2376  sizeof(lsof),
2377  "lsof -p %d",
2378  getpid ());
2379  (void) close (1);
2380  (void) dup2 (2, 1);
2381  if (0 != system (lsof))
2383  "system");
2384 #endif
2385 #if DEBUG_FDS
2386  for (struct Scheduled *s = context->scheduled_head;
2387  NULL != s;
2388  s = s->next)
2389  {
2390  int flags = fcntl (s->fdi->sock,
2391  F_GETFD);
2392 
2393  if ((flags == -1) &&
2394  (EBADF == errno))
2395  {
2397  "Got invalid file descriptor %d!\n",
2398  s->fdi->sock);
2399 #if EXECINFO
2400  dump_backtrace (s->task);
2401 #endif
2402  }
2403  }
2404 #endif
2405  GNUNET_assert (0);
2408  return GNUNET_SYSERR;
2409  }
2410  if (select_result > 0)
2411  {
2412  for (struct Scheduled *pos = context->scheduled_head;
2413  NULL != pos;
2414  pos = pos->next)
2415  {
2416  int is_ready = GNUNET_NO;
2417 
2418  if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2419  (GNUNET_YES ==
2421  pos->fdi->sock)) )
2422  {
2423  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2424  is_ready = GNUNET_YES;
2425  }
2426  if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2427  (GNUNET_YES ==
2429  pos->fdi->sock)) )
2430  {
2431  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2432  is_ready = GNUNET_YES;
2433  }
2434  if (GNUNET_YES == is_ready)
2435  {
2436  GNUNET_SCHEDULER_task_ready (pos->task,
2437  pos->fdi);
2438  }
2439  }
2440  }
2442  {
2444  "scheduler has more tasks ready!\n");
2445  }
2446  }
2449  return GNUNET_OK;
2450 }
2451 
2452 
2453 static int
2454 select_add (void *cls,
2455  struct GNUNET_SCHEDULER_Task *task,
2456  struct GNUNET_SCHEDULER_FdInfo *fdi)
2457 {
2458  struct DriverContext *context = cls;
2459 
2460  GNUNET_assert (NULL != context);
2461  GNUNET_assert (NULL != task);
2462  GNUNET_assert (NULL != fdi);
2463  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2464  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2465 
2466  if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2467  {
2468  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2469  return GNUNET_SYSERR;
2470  }
2471 
2472  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2473  scheduled->task = task;
2474  scheduled->fdi = fdi;
2475  scheduled->et = fdi->et;
2476 
2478  context->scheduled_tail,
2479  scheduled);
2480  return GNUNET_OK;
2481 }
2482 
2483 
2484 static int
2485 select_del (void *cls,
2486  struct GNUNET_SCHEDULER_Task *task)
2487 {
2488  struct DriverContext *context;
2489  struct Scheduled *pos;
2490  int ret;
2491 
2492  GNUNET_assert (NULL != cls);
2493 
2494  context = cls;
2495  ret = GNUNET_SYSERR;
2496  pos = context->scheduled_head;
2497  while (NULL != pos)
2498  {
2499  struct Scheduled *next = pos->next;
2500  if (pos->task == task)
2501  {
2503  context->scheduled_tail,
2504  pos);
2505  GNUNET_free (pos);
2506  ret = GNUNET_OK;
2507  }
2508  pos = next;
2509  }
2510  return ret;
2511 }
2512 
2513 
2514 static void
2516  struct GNUNET_TIME_Absolute dt)
2517 {
2518  struct DriverContext *context = cls;
2519 
2520  GNUNET_assert (NULL != context);
2521  context->timeout = dt;
2522 }
2523 
2524 
2530 struct GNUNET_SCHEDULER_Driver *
2532 {
2533  struct GNUNET_SCHEDULER_Driver *select_driver;
2534 
2535  select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2536 
2537  select_driver->add = &select_add;
2538  select_driver->del = &select_del;
2539  select_driver->set_wakeup = &select_set_wakeup;
2540 
2541  return select_driver;
2542 }
2543 
2544 
2557 void
2559 {
2560  struct GNUNET_AsyncScopeSave dummy_old_scope;
2561 
2562  GNUNET_assert (NULL != active_task);
2563  /* Since we're in a task, the context will be automatically
2564  restored by the scheduler. */
2565  GNUNET_async_scope_enter (aid, &dummy_old_scope);
2566 }
2567 
2568 
2569 /* end of scheduler.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
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:752
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1080
int read_fd
Set if we only wait for reading from a single FD, otherwise -1.
Definition: scheduler.c:208
No special options, use non-blocking read/write operations.
static unsigned int ready_count
Number of tasks on the ready list.
Definition: scheduler.c:390
int nsds
Maximum number of any socket descriptor in the set (plus one)
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:1110
Information about an event relating to a file descriptor/socket.
struct GNUNET_NETWORK_FDSet * rs
Passed here to avoid constantly allocating/deallocating this element, but generally we want to get ri...
Definition: scheduler.c:88
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
uint64_t rel_value_us
The actual value.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static void install_parent_control_handler(void *cls)
Definition: scheduler.c:928
GNUNET_SCHEDULER_TaskCallback callback
Function to run when ready.
Definition: scheduler.c:149
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:1199
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:732
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition: network.c:1137
The reading socket is ready.
Context information passed to each scheduler task.
static struct GNUNET_SCHEDULER_Task * shutdown_tail
Tail of list of tasks waiting for shutdown.
Definition: scheduler.c:331
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, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1331
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:246
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
The prerequisite task is done.
static GNUNET_SCHEDULER_select scheduler_select
Function to use as a select() in the scheduler.
Definition: scheduler.c:418
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition: scheduler.c:1038
static void sighandler_shutdown()
Wait for a short time.
Definition: scheduler.c:664
struct GNUNET_SCHEDULER_Task * prev
This is a linked list.
Definition: scheduler.c:144
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:423
Run with the same priority as the current job.
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:2207
struct GNUNET_SIGNAL_Context * shc_term
context of the SIGTERM handler
Definition: scheduler.c:105
int GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to, int nfd)
Test native fd in a set.
Definition: network.c:1155
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 ...
static pid_t my_pid
Process ID of this process at the time we installed the various signal handlers.
Definition: scheduler.c:630
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1588
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:720
int on_shutdown
Is this task run on shutdown?
Definition: scheduler.c:224
static struct GNUNET_SCHEDULER_Task * pending_timeout_tail
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:349
API an external event loop has to implement for GNUNET_SCHEDULER_driver_init.
static struct GNUNET_DISK_PipeHandle * shutdown_pipe_handle
Pipe used to communicate shutdown via signal.
Definition: scheduler.c:624
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1700
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1667
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:469
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal hander.
Definition: signal.c:77
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 ...
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct Scheduled * scheduled_head
the head of a DLL containing information about the events the select driver is waiting for ...
Definition: scheduler.c:288
Identifier for an asynchronous execution context.
static struct GNUNET_SCHEDULER_Task * pending_head
Head of list of tasks waiting for an event.
Definition: scheduler.c:316
static struct GNUNET_SCHEDULER_Task * t
Main task.
GNUNET_SCHEDULER_Priority
Valid task priorities.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_file_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_DISK_FileHandle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready...
Definition: scheduler.c:1736
static struct GNUNET_SCHEDULER_Task * active_task
ID of the task that is running right now.
Definition: scheduler.c:360
void GNUNET_SCHEDULER_shutdown()
Request the shutdown of a scheduler.
Definition: scheduler.c:531
void extract_handles(const struct GNUNET_NETWORK_FDSet *fdset, const struct GNUNET_NETWORK_Handle ***ntarget, unsigned int *extracted_nhandles, const struct GNUNET_DISK_FileHandle ***ftarget, unsigned int *extracted_fhandles)
Definition: scheduler.c:1759
uint64_t abs_value_us
The actual value.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority and to be run after the specified delay or wh...
Definition: scheduler.c:1551
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:379
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
int GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:192
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:1672
static struct GNUNET_SCHEDULER_Task * pending_timeout_last
Last inserted task waiting ONLY for a timeout event.
Definition: scheduler.c:355
static pa_context * context
Pulseaudio context.
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select()
Obtain the driver for using select() as the event loop.
Definition: scheduler.c:2531
We are shutting down and are running all shutdown-related tasks.
int write_fd
Set if we only wait for writing to a single FD, otherwise -1.
Definition: scheduler.c:213
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:1066
const struct GNUNET_SCHEDULER_FdInfo * fds
Array of length fds_len with information about ready FDs.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
void GNUNET_async_scope_enter(const struct GNUNET_AsyncScopeId *aid, struct GNUNET_AsyncScopeSave *old_scope)
Set the async scope for the current thread.
Driver context used by GNUNET_SCHEDULER_run.
Definition: scheduler.c:282
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now_with_lifeness(int lifeness, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible with the (transitive) ignore-shutdown flag either e...
Definition: scheduler.c:1378
GNUNET_SCHEDULER_Reason
Reasons why the schedule may have triggered the task now.
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:622
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1266
unsigned int fds_len
Length of the following array.
struct GNUNET_SCHEDULER_FdInfo * fdi
information about the network socket / file descriptor where the event is expected to occur ...
Definition: scheduler.c:269
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition: scheduler.c:2485
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition: scheduler.c:2515
static struct GNUNET_SCHEDULER_Task * pending_tail
Tail of list of tasks waiting for an event.
Definition: scheduler.c:321
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:1269
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1250
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:439
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:1223
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:371
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
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:166
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:820
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:95
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:1296
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
int sock
Underlying OS handle the event was about.
static struct SolverHandle * sh
static int current_lifeness
Value of the &#39;lifeness&#39; flag for the current task.
Definition: scheduler.c:407
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:702
static struct GNUNET_SCHEDULER_Task * pending_timeout_head
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:340
collection of IO descriptors
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1841
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 ...
static void driver_add_multiple(struct GNUNET_SCHEDULER_Task *t)
calls the given function func on each FdInfo related to t.
Definition: scheduler.c:906
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:365
struct GNUNET_SIGNAL_Context * shc_int
context of the SIGINT handler
Definition: scheduler.c:100
A struct representing an event the select driver is waiting for.
Definition: scheduler.c:254
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
static const struct GNUNET_SCHEDULER_Driver * scheduler_driver
The driver used for the event loop.
Definition: scheduler.c:311
The writing-end of a pipe.
Buffer available for writing.
The reading-end of a pipe.
static int fh
Handle to the unique file.
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:385
struct GNUNET_SIGNAL_Context * shc_hup
context of the SIGHUP handler
Definition: scheduler.c:122
static struct GNUNET_SCHEDULER_Task * add_without_sets(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_NETWORK_Handle *read_nh, const struct GNUNET_NETWORK_Handle *write_nh, const struct GNUNET_DISK_FileHandle *read_fh, const struct GNUNET_DISK_FileHandle *write_fh, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1445
#define LOG_STRERROR(kind, syscall)
Definition: scheduler.c:33
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...
Definition: os_priority.c:141
struct GNUNET_SCHEDULER_FdInfo * fds
Information about which FDs are ready for this task (and why).
Definition: scheduler.c:159
void GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
Get the current async scope.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static int select_add(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Definition: scheduler.c:2454
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1456
static struct GNUNET_TIME_Absolute start_time
Start time of the current round; used to determine how long one iteration takes (which influences how...
void * callback_cls
Closure for the callback.
Definition: scheduler.c:154
enum GNUNET_SCHEDULER_Reason reason
Why is the task ready? Set after task is added to ready queue.
Definition: scheduler.c:198
#define GNUNET_free_nz(ptr)
Wrapper around free.
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:51
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:1340
The writing socket is ready.
static int select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition: scheduler.c:2311
This is an internal priority level that is only used for tasks that are being triggered due to shutdo...
Data available for reading.
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:512
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
#define LOG(kind,...)
Definition: scheduler.c:31
Saved async scope identifier or root scope.
#define DELAY_THRESHOLD
Task that were in the queue for longer than this are reported if PROFILE_DELAYS is active...
Definition: scheduler.c:73
The specified timeout has expired.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
void GNUNET_async_scope_restore(struct GNUNET_AsyncScopeSave *old_scope)
Clear the current thread&#39;s async scope.
void GNUNET_NETWORK_fdset_zero(struct GNUNET_NETWORK_FDSet *fds)
Reset FD set (clears all file descriptors).
Definition: network.c:997
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct Scheduled * prev
Definition: scheduler.c:256
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition: scheduler.c:585
static enum GNUNET_SCHEDULER_Priority current_priority
Priority of the task running right now.
Definition: scheduler.c:396
void(* set_wakeup)(void *cls, struct GNUNET_TIME_Absolute dt)
Set time at which we definitively want to get a wakeup call.
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:1171
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
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...
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:2003
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1634
enum GNUNET_SCHEDULER_EventType et
Type of the event that was generated related to sock.
struct GNUNET_SIGNAL_Context * shc_pipe
context of hte SIGPIPE handler
Definition: scheduler.c:127
unsigned int fds_len
Size of the fds array.
Definition: scheduler.c:171
struct GNUNET_TIME_Absolute timeout
the time when the select driver will wake up again (after calling select)
Definition: scheduler.c:300
int own_handles
Do we own the network and file handles referenced by the FdInfo structs in the fds array...
Definition: scheduler.c:178
static enum GNUNET_SCHEDULER_Priority work_priority
Priority used currently in GNUNET_SCHEDULER_do_work().
Definition: scheduler.c:412
static void sighandler_pipe()
Signal handler called for SIGPIPE.
Definition: scheduler.c:636
struct GNUNET_AsyncScopeId scope_id
Saved scope.
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:937
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1310
No event (useful for timeout).
struct Scheduled * scheduled_tail
the tail of a DLL containing information about the events the select driver is waiting for ...
Definition: scheduler.c:294
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:375
struct GNUNET_SCHEDULER_Task * next
This is a linked list.
Definition: scheduler.c:139
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.
static enum GNUNET_SCHEDULER_Priority max_priority_added
Priority of the highest task added in the current select iteration.
Definition: scheduler.c:402
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:454
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:2558
This is the very first task run during startup.
void * cls
Closure to pass to the functions in this struct.
Entry in list of pending tasks.
Definition: scheduler.c:134
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:788
struct GNUNET_SCHEDULER_Task * task
the task, the event is related to
Definition: scheduler.c:263
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:275
handle to a socket
Definition: network.c:52
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition: scheduler.c:2282
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:331
struct GNUNET_TIME_Absolute timeout
Absolute timeout value for the task, or GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout".
Definition: scheduler.c:184
Time for absolute times used by GNUnet, in microseconds.
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:564
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1517
enum GNUNET_SCHEDULER_Priority priority
Task priority.
Definition: scheduler.c:203
int fd
File handle on Unix-like systems.
struct GNUNET_AsyncScopeSave scope
Asynchronous scope of the task that scheduled this scope,.
Definition: scheduler.c:247
Number of priorities (must be the last priority).
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_net_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready...
Definition: scheduler.c:1625
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:1958
static struct GNUNET_SCHEDULER_Task * shutdown_head
Head of list of tasks waiting for shutdown.
Definition: scheduler.c:326
Run with the default priority (normal P2P operations).
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:757
struct GNUNET_NETWORK_FDSet * ws
Passed here to avoid constantly allocating/deallocating this element, but generally we want to get ri...
Definition: scheduler.c:95
int in_ready_list
Is this task in the ready list?
Definition: scheduler.c:229
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:636
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:246
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:1246
struct Scheduled * next
Definition: scheduler.c:258
struct GNUNET_SIGNAL_Context * shc_quit
context of the SIGQUIT handler
Definition: scheduler.c:117
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:68
Argument to be passed from the driver to GNUNET_SCHEDULER_do_work().
Definition: scheduler.c:81
int(* del)(void *cls, struct GNUNET_SCHEDULER_Task *task)
Delete a task from the set of tasks to be run.
unsigned int GNUNET_SCHEDULER_get_load(enum GNUNET_SCHEDULER_Priority p)
Get information about the current load of this scheduler.
Definition: scheduler.c:769
static void * scheduler_select_cls
Closure for scheduler_select.
Definition: scheduler.c:428
Internal DISK related helper functions.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
int lifeness
Should the existence of this task in the queue be counted as reason to not shutdown the scheduler...
Definition: scheduler.c:219
GNUNET_SCHEDULER_EventType
Possible events on FDs, used as a bitmask.
static void shutdown_if_no_lifeness()
Definition: scheduler.c:680
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972