GNUnet  0.19.4
scheduler.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2009-2017, 2022 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  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "disk.h"
29 // DEBUG
30 #include <inttypes.h>
31 
32 #define LOG(kind, ...) GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__)
33 
34 #define LOG_STRERROR(kind, syscall) GNUNET_log_from_strerror (kind, \
35  "util-scheduler", \
36  syscall)
37 
38 
39 #if HAVE_EXECINFO_H
40 #include "execinfo.h"
41 
46 #define USE_LSOF GNUNET_NO
47 
51 #define EXECINFO GNUNET_NO
52 
56 #define DEBUG_FDS GNUNET_NO
57 
61 #define MAX_TRACE_DEPTH 50
62 #endif
63 
68 #define PROFILE_DELAYS GNUNET_NO
69 
74 #define DELAY_THRESHOLD GNUNET_TIME_UNIT_SECONDS
75 
76 
83 {
90 
97 
102 
107 
108 #if (SIGTERM != GNUNET_TERM_SIG)
112  struct GNUNET_SIGNAL_Context *shc_gterm;
113 #endif
114 
119 
124 
129 };
130 
131 
136 {
141 
146 
151 
156 
161 
168 
172  unsigned int fds_len;
173 
180 
186 
187 #if PROFILE_DELAYS
192 #endif
193 
200 
205 
209  int read_fd;
210 
214  int write_fd;
215 
220  int lifeness;
221 
226 
231 
232 #if EXECINFO
237  char **backtrace_strings;
238 
242  int num_backtrace_strings;
243 #endif
244 
249 };
250 
257 
258 
262 struct Scheduled
263 {
264  struct Scheduled *prev;
265 
266  struct Scheduled *next;
267 
272 
278 
284 };
285 
286 
291 {
297 
303 
309 };
310 
311 
320 
325 
330 
335 
340 
349 
358 
364 
369 
373 static struct
375 
379 static struct
381 
388 
394 
398 static unsigned int ready_count;
399 
405 
411 
415 static int current_lifeness;
416 
421 
427 
431 static struct GNUNET_SCHEDULER_TaskContext tc;
432 
436 static void *scheduler_select_cls;
437 
438 
446 void
448  void *new_select_cls)
449 {
450  scheduler_select = new_select;
451  scheduler_select_cls = new_select_cls;
452 }
453 
454 
461 static enum GNUNET_SCHEDULER_Priority
463 {
464  if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
465  return p;
466  GNUNET_assert (0);
467  return 0; /* make compiler happy */
468 }
469 
470 
477 get_timeout ()
478 {
479  struct GNUNET_SCHEDULER_Task *pos;
480  struct GNUNET_TIME_Absolute now;
482 
483  pos = pending_timeout_head;
484  now = GNUNET_TIME_absolute_get ();
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 }
512 
514 {
516  {
519  &pass_end_marker);
521  }
522 }
523 
525 {
528  ready_tail[p],
529  &pass_end_marker);
532  work_priority = p;
533 }
534 
540 static void
542 {
544 
546  ready_tail[p],
547  task);
548  if (p > work_priority)
550  task->in_ready_list = GNUNET_YES;
551  ready_count++;
552 }
553 
554 
561 void
563 {
564  struct GNUNET_SCHEDULER_Task *pos;
565 
567  "GNUNET_SCHEDULER_shutdown\n");
568  if (NULL != install_parent_control_task)
569  {
572  }
573  if (NULL != shutdown_pipe_task)
574  {
576  shutdown_pipe_task = NULL;
577  }
578  while (NULL != (pos = shutdown_head))
579  {
582  pos);
584  queue_ready_task (pos);
585  }
586 }
587 
588 
594 static void
596 {
597 #if EXECINFO
598  for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
600  "Task %p trace %u: %s\n",
601  t,
602  i,
603  t->backtrace_strings[i]);
604 #else
605  (void) t;
606 #endif
607 }
608 
609 
615 static void
617 {
619  "destroying task %p\n",
620  t);
621 
622  if (GNUNET_YES == t->own_handles)
623  {
624  for (unsigned int i = 0; i != t->fds_len; ++i)
625  {
626  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
627  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
628  if (fd)
629  {
631  (struct GNUNET_NETWORK_Handle *) fd);
632  }
633  if (fh)
634  {
635  // FIXME: on WIN32 this is not enough! A function
636  // GNUNET_DISK_file_free_memory_only would be nice
637  GNUNET_free_nz ((void *) fh);
638  }
639  }
640  }
641  if (t->fds_len > 1)
642  {
643  GNUNET_array_grow (t->fds, t->fds_len, 0);
644  }
645 #if EXECINFO
646  GNUNET_free (t->backtrace_strings);
647 #endif
648  GNUNET_free (t);
649 }
650 
651 
656 
661 static pid_t my_pid;
662 
666 static void
668 {
669  return;
670 }
671 
672 
676 static void
678 {
679  static char c;
680  int old_errno = errno; /* backup errno */
681 
682  if (getpid () != my_pid)
683  _exit (1); /* we have fork'ed since the signal handler was created,
684  * ignore the signal, see https://gnunet.org/vfork discussion */
688  &c, sizeof(c));
689  errno = old_errno;
690 }
691 
692 
693 static void
695 {
696  struct GNUNET_SCHEDULER_Task *t;
697 
698  if (ready_count > 0)
699  return;
700  for (t = pending_head; NULL != t; t = t->next)
701  if (GNUNET_YES == t->lifeness)
702  return;
703  for (t = shutdown_head; NULL != t; t = t->next)
704  if (GNUNET_YES == t->lifeness)
705  return;
706  for (t = pending_timeout_head; NULL != t; t = t->next)
707  if (GNUNET_YES == t->lifeness)
708  return;
709  /* No lifeness! */
711 }
712 
713 
714 static int
716  struct DriverContext *context);
717 
718 
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;
778  ret = 0;
779  for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)];
780  NULL != pos;
781  pos = pos->next)
782  ret++;
784  // Don't count the dummy marker
785  ret--;
786  return ret;
787 }
788 
789 
790 void
792  const struct GNUNET_NETWORK_Handle *const *read_nh,
793  unsigned int read_nh_len,
794  const struct GNUNET_NETWORK_Handle *const *write_nh,
795  unsigned int write_nh_len,
796  const struct GNUNET_DISK_FileHandle *const *read_fh,
797  unsigned int read_fh_len,
798  const struct GNUNET_DISK_FileHandle *const *write_fh,
799  unsigned int write_fh_len)
800 {
801  // FIXME: if we have exactly two network handles / exactly two file handles
802  // and they are equal, we can make one FdInfo with both
803  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
804  struct GNUNET_SCHEDULER_FdInfo *fdi;
805 
806  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
807  if (1 == t->fds_len)
808  {
809  fdi = &t->fdx;
810  t->fds = fdi;
811  if (1 == read_nh_len)
812  {
813  GNUNET_assert (NULL != read_nh);
814  GNUNET_assert (NULL != *read_nh);
815  fdi->fd = *read_nh;
816  fdi->et = GNUNET_SCHEDULER_ET_IN;
817  fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
818  t->read_fd = fdi->sock;
819  t->write_fd = -1;
820  }
821  else if (1 == write_nh_len)
822  {
823  GNUNET_assert (NULL != write_nh);
824  GNUNET_assert (NULL != *write_nh);
825  fdi->fd = *write_nh;
827  fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
828  t->read_fd = -1;
829  t->write_fd = fdi->sock;
830  }
831  else if (1 == read_fh_len)
832  {
833  GNUNET_assert (NULL != read_fh);
834  GNUNET_assert (NULL != *read_fh);
835  fdi->fh = *read_fh;
836  fdi->et = GNUNET_SCHEDULER_ET_IN;
837  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
838  t->read_fd = fdi->sock;
839  t->write_fd = -1;
840  }
841  else
842  {
843  GNUNET_assert (NULL != write_fh);
844  GNUNET_assert (NULL != *write_fh);
845  fdi->fh = *write_fh;
847  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
848  t->read_fd = -1;
849  t->write_fd = fdi->sock;
850  }
851  }
852  else
853  {
855  t->fds = fdi;
856  t->read_fd = -1;
857  t->write_fd = -1;
858  unsigned int i;
859  for (i = 0; i != read_nh_len; ++i)
860  {
861  fdi->fd = read_nh[i];
862  GNUNET_assert (NULL != fdi->fd);
863  fdi->et = GNUNET_SCHEDULER_ET_IN;
864  fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
865  ++fdi;
866  }
867  for (i = 0; i != write_nh_len; ++i)
868  {
869  fdi->fd = write_nh[i];
870  GNUNET_assert (NULL != fdi->fd);
872  fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
873  ++fdi;
874  }
875  for (i = 0; i != read_fh_len; ++i)
876  {
877  fdi->fh = read_fh[i];
878  GNUNET_assert (NULL != fdi->fh);
879  fdi->et = GNUNET_SCHEDULER_ET_IN;
880  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
881  ++fdi;
882  }
883  for (i = 0; i != write_fh_len; ++i)
884  {
885  fdi->fh = write_fh[i];
886  GNUNET_assert (NULL != fdi->fh);
888  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
889  ++fdi;
890  }
891  }
892 }
893 
894 
908 static void
910 {
911  struct GNUNET_SCHEDULER_FdInfo *fdi;
912  int success = GNUNET_YES;
913 
914  for (unsigned int i = 0; i != t->fds_len; ++i)
915  {
916  fdi = &t->fds[i];
918  t,
919  fdi) && success;
921  }
922  if (GNUNET_YES != success)
923  {
925  "driver could not add task\n");
926  }
927 }
928 
929 
930 static void
932 {
933  (void) cls;
936 }
937 
938 
939 static void
940 shutdown_pipe_cb (void *cls)
941 {
942  char c;
943  const struct GNUNET_DISK_FileHandle *pr;
944 
945  (void) cls;
946  shutdown_pipe_task = NULL;
950  /* consume the signal */
951  GNUNET_DISK_file_read (pr, &c, sizeof(c));
952  /* mark all active tasks as ready due to shutdown */
956  pr,
958  NULL);
959 }
960 
961 
974 void *
976 {
978  int is_fd_task;
979  void *ret;
980 
982  "canceling task %p\n",
983  task);
984 
985  /* scheduler must be running */
987  is_fd_task = (NULL != task->fds);
988  if (is_fd_task)
989  {
990  int del_result = scheduler_driver->del (scheduler_driver->cls, task);
991  if (GNUNET_OK != del_result)
992  {
994  "driver could not delete task\n");
995  GNUNET_assert (0);
996  }
997  }
998  if (! task->in_ready_list)
999  {
1000  if (is_fd_task)
1001  {
1003  pending_tail,
1004  task);
1005  }
1006  else if (GNUNET_YES == task->on_shutdown)
1007  {
1009  shutdown_tail,
1010  task);
1011  }
1012  else
1013  {
1016  task);
1017  if (pending_timeout_last == task)
1018  pending_timeout_last = NULL;
1019  }
1020  }
1021  else
1022  {
1023  p = check_priority (task->priority);
1025  ready_tail[p],
1026  task);
1027  ready_count--;
1028  }
1029  ret = task->callback_cls;
1030  destroy_task (task);
1031  return ret;
1032 }
1033 
1034 
1040 static void
1042 {
1043 #if EXECINFO
1044  void *backtrace_array[MAX_TRACE_DEPTH];
1045 
1046  t->num_backtrace_strings
1047  = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1048  t->backtrace_strings =
1049  backtrace_symbols (backtrace_array,
1050  t->num_backtrace_strings);
1051  dump_backtrace (t);
1052 #else
1053  (void) t;
1054 #endif
1055 }
1056 
1057 
1068 void
1070  task,
1071  void *task_cls,
1073  reason,
1075  priority)
1076 {
1077  struct GNUNET_SCHEDULER_Task *t;
1078 
1079  /* scheduler must be running */
1080  GNUNET_assert (NULL != scheduler_driver);
1081  GNUNET_assert (NULL != task);
1082  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1083  t->read_fd = -1;
1084  t->write_fd = -1;
1085  t->callback = task;
1086  t->callback_cls = task_cls;
1087 #if PROFILE_DELAYS
1088  t->start_time = GNUNET_TIME_absolute_get ();
1089 #endif
1090  t->reason = reason;
1094  "Adding continuation task %p\n",
1095  t);
1096  init_backtrace (t);
1097  queue_ready_task (t);
1098 }
1099 
1100 
1112 struct GNUNET_SCHEDULER_Task *
1116  void *task_cls)
1117 {
1118  struct GNUNET_SCHEDULER_Task *t;
1119  struct GNUNET_SCHEDULER_Task *pos;
1120  struct GNUNET_SCHEDULER_Task *prev;
1121  struct GNUNET_TIME_Relative left;
1122 
1123  /* scheduler must be running */
1124  GNUNET_assert (NULL != scheduler_driver);
1125  GNUNET_assert (NULL != task);
1126  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1128  t->callback = task;
1129  t->callback_cls = task_cls;
1130  t->read_fd = -1;
1131  t->write_fd = -1;
1132 #if PROFILE_DELAYS
1133  t->start_time = GNUNET_TIME_absolute_get ();
1134 #endif
1135  t->timeout = at;
1136  t->priority = check_priority (priority);
1138  init_backtrace (t);
1139 
1141  if (0 == left.rel_value_us)
1142  {
1143  queue_ready_task (t);
1144  if (priority > work_priority)
1145  work_priority = priority;
1146  return t;
1147  }
1148 
1149  /* try tail first (optimization in case we are
1150  * appending to a long list of tasks with timeouts) */
1151  if ((NULL == pending_timeout_head) ||
1153  {
1156  t);
1157  }
1158  else
1159  {
1160  /* first move from heuristic start backwards to before start time */
1161  prev = pending_timeout_last;
1162  while ((NULL != prev) &&
1164  prev = prev->prev;
1165  /* now, move from heuristic start (or head of list) forward to insertion point */
1166  if (NULL == prev)
1167  pos = pending_timeout_head;
1168  else
1169  pos = prev->next;
1170  while ((NULL != pos) && (pos->timeout.abs_value_us <=
1172  {
1173  prev = pos;
1174  pos = pos->next;
1175  }
1178  prev,
1179  t);
1180  }
1181  /* finally, update heuristic insertion point to last insertion... */
1184  "Adding task %p\n",
1185  t);
1186  return t;
1187 }
1188 
1189 
1201 struct GNUNET_SCHEDULER_Task *
1204  priority,
1206  void *task_cls)
1207 {
1210  priority,
1211  task,
1212  task_cls);
1213 }
1214 
1215 
1225 struct GNUNET_SCHEDULER_Task *
1228  void *task_cls)
1229 {
1231  prio,
1232  task,
1233  task_cls);
1234 }
1235 
1236 
1248 struct GNUNET_SCHEDULER_Task *
1251  void *task_cls)
1252 {
1255  task,
1256  task_cls);
1257 }
1258 
1259 
1271 struct GNUNET_SCHEDULER_Task *
1274  void *task_cls)
1275 {
1278  task,
1279  task_cls);
1280 }
1281 
1282 
1298 struct GNUNET_SCHEDULER_Task *
1300  void *task_cls)
1301 {
1302  struct GNUNET_SCHEDULER_Task *t;
1303 
1304  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1306  t->callback = task;
1307  t->callback_cls = task_cls;
1308  t->read_fd = -1;
1309  t->write_fd = -1;
1310 #if PROFILE_DELAYS
1311  t->start_time = GNUNET_TIME_absolute_get ();
1312 #endif
1317  queue_ready_task (t);
1318  init_backtrace (t);
1319  return t;
1320 }
1321 
1322 
1333 struct GNUNET_SCHEDULER_Task *
1335  void *task_cls)
1336 {
1337  struct GNUNET_SCHEDULER_Task *t;
1338 
1339  /* scheduler must be running */
1340  GNUNET_assert (NULL != scheduler_driver);
1341  GNUNET_assert (NULL != task);
1342  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1344  t->callback = task;
1345  t->callback_cls = task_cls;
1346  t->read_fd = -1;
1347  t->write_fd = -1;
1348 #if PROFILE_DELAYS
1349  t->start_time = GNUNET_TIME_absolute_get ();
1350 #endif
1354  t->lifeness = GNUNET_NO;
1356  shutdown_tail,
1357  t);
1359  "Adding shutdown task %p\n",
1360  t);
1361  init_backtrace (t);
1362  return t;
1363 }
1364 
1365 
1366 struct GNUNET_SCHEDULER_Task *
1369  void *task_cls)
1370 {
1371  struct GNUNET_SCHEDULER_Task *ret;
1372 
1373  ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1374  ret->lifeness = lifeness;
1375  return ret;
1376 }
1377 
1378 
1379 #if DEBUG_FDS
1386 void
1387 check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1388 {
1389  if (-1 != raw_fd)
1390  {
1391  int flags = fcntl (raw_fd, F_GETFD);
1392 
1393  if ((flags == -1) && (errno == EBADF))
1394  {
1396  "Got invalid file descriptor %d!\n",
1397  raw_fd);
1398  init_backtrace (t);
1399  GNUNET_assert (0);
1400  }
1401  }
1402 }
1403 
1404 
1405 #endif
1406 
1407 
1433 static struct GNUNET_SCHEDULER_Task *
1436  const struct GNUNET_NETWORK_Handle *read_nh,
1437  const struct GNUNET_NETWORK_Handle *write_nh,
1438  const struct GNUNET_DISK_FileHandle *read_fh,
1439  const struct GNUNET_DISK_FileHandle *write_fh,
1441  void *task_cls)
1442 {
1443  struct GNUNET_SCHEDULER_Task *t;
1444 
1445  /* scheduler must be running */
1446  GNUNET_assert (NULL != scheduler_driver);
1447  GNUNET_assert (NULL != task);
1448  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1450  init_fd_info (t,
1451  &read_nh,
1452  read_nh ? 1 : 0,
1453  &write_nh,
1454  write_nh ? 1 : 0,
1455  &read_fh,
1456  read_fh ? 1 : 0,
1457  &write_fh,
1458  write_fh ? 1 : 0);
1459  t->callback = task;
1460  t->callback_cls = task_cls;
1461 #if DEBUG_FDS
1462  check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1463  check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1464  check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1465  check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1466 #endif
1467 #if PROFILE_DELAYS
1468  t->start_time = GNUNET_TIME_absolute_get ();
1469 #endif
1475  pending_tail,
1476  t);
1479  t->priority);
1480  init_backtrace (t);
1481  return t;
1482 }
1483 
1484 
1505 struct GNUNET_SCHEDULER_Task *
1507  struct GNUNET_NETWORK_Handle *rfd,
1509  void *task_cls)
1510 {
1513  rfd, task, task_cls);
1514 }
1515 
1516 
1539 struct GNUNET_SCHEDULER_Task *
1542  priority,
1543  struct GNUNET_NETWORK_Handle *rfd,
1545  void *task_cls)
1546 {
1548  rfd,
1549  GNUNET_YES,
1550  GNUNET_NO,
1551  task, task_cls);
1552 }
1553 
1554 
1576 struct GNUNET_SCHEDULER_Task *
1578  struct GNUNET_NETWORK_Handle *wfd,
1580  void *task_cls)
1581 {
1584  wfd,
1586  task, task_cls);
1587 }
1588 
1589 
1613 struct GNUNET_SCHEDULER_Task *
1616  struct GNUNET_NETWORK_Handle *fd,
1617  int on_read,
1618  int on_write,
1620  void *task_cls)
1621 {
1622  /* scheduler must be running */
1623  GNUNET_assert (NULL != scheduler_driver);
1624  GNUNET_assert (on_read || on_write);
1626  return add_without_sets (delay, priority,
1627  on_read ? fd : NULL,
1628  on_write ? fd : NULL,
1629  NULL,
1630  NULL,
1631  task, task_cls);
1632 }
1633 
1634 
1655 struct GNUNET_SCHEDULER_Task *
1657  const struct GNUNET_DISK_FileHandle *rfd,
1659  void *task_cls)
1660 {
1663  rfd, GNUNET_YES, GNUNET_NO,
1664  task, task_cls);
1665 }
1666 
1667 
1688 struct GNUNET_SCHEDULER_Task *
1690  const struct GNUNET_DISK_FileHandle *wfd,
1692  void *task_cls)
1693 {
1696  wfd, GNUNET_NO, GNUNET_YES,
1697  task, task_cls);
1698 }
1699 
1700 
1724 struct GNUNET_SCHEDULER_Task *
1727  priority,
1728  const struct
1730  int on_read, int on_write,
1732  void *task_cls)
1733 {
1734  /* scheduler must be running */
1735  GNUNET_assert (NULL != scheduler_driver);
1736  GNUNET_assert (on_read || on_write);
1737  GNUNET_assert (fd->fd >= 0);
1738  return add_without_sets (delay, priority,
1739  NULL,
1740  NULL,
1741  on_read ? fd : NULL,
1742  on_write ? fd : NULL,
1743  task, task_cls);
1744 }
1745 
1746 
1747 void
1749  const struct GNUNET_NETWORK_Handle ***ntarget,
1750  unsigned int *extracted_nhandles,
1751  const struct GNUNET_DISK_FileHandle ***ftarget,
1752  unsigned int *extracted_fhandles)
1753 {
1754  // FIXME: this implementation only works for unix, for WIN32 the file handles
1755  // in fdset must be handled separately
1756  const struct GNUNET_NETWORK_Handle **nhandles;
1757  const struct GNUNET_DISK_FileHandle **fhandles;
1758  unsigned int nhandles_len;
1759  unsigned int fhandles_len;
1760 
1761  nhandles = NULL;
1762  fhandles = NULL;
1763  nhandles_len = 0;
1764  fhandles_len = 0;
1765  for (int sock = 0; sock != fdset->nsds; ++sock)
1766  {
1767  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1768  {
1769  struct GNUNET_NETWORK_Handle *nhandle;
1770  struct GNUNET_DISK_FileHandle *fhandle;
1771 
1772  nhandle = GNUNET_NETWORK_socket_box_native (sock);
1773  if (NULL != nhandle)
1774  {
1775  GNUNET_array_append (nhandles, nhandles_len, nhandle);
1776  }
1777  else
1778  {
1779  fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1780  if (NULL != fhandle)
1781  {
1782  GNUNET_array_append (fhandles, fhandles_len, fhandle);
1783  }
1784  else
1785  {
1786  GNUNET_assert (0);
1787  }
1788  }
1789  }
1790  }
1791  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1792  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1793  *extracted_nhandles = nhandles_len;
1794  *extracted_fhandles = fhandles_len;
1795 }
1796 
1797 
1829 struct GNUNET_SCHEDULER_Task *
1831  struct GNUNET_TIME_Relative delay,
1832  const struct GNUNET_NETWORK_FDSet *rs,
1833  const struct GNUNET_NETWORK_FDSet *ws,
1835  void *task_cls)
1836 {
1837  struct GNUNET_SCHEDULER_Task *t;
1838  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1839  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1840  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1841  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1842  unsigned int read_nhandles_len = 0;
1843  unsigned int write_nhandles_len = 0;
1844  unsigned int read_fhandles_len = 0;
1845  unsigned int write_fhandles_len = 0;
1846 
1847  /* scheduler must be running */
1848  GNUNET_assert (NULL != scheduler_driver);
1849  GNUNET_assert (NULL != task);
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  if (! no_fds)
1859  {
1860  if (NULL != rs)
1861  {
1862  extract_handles (rs,
1863  &read_nhandles,
1864  &read_nhandles_len,
1865  &read_fhandles,
1866  &read_fhandles_len);
1867  }
1868  if (NULL != ws)
1869  {
1870  extract_handles (ws,
1871  &write_nhandles,
1872  &write_nhandles_len,
1873  &write_fhandles,
1874  &write_fhandles_len);
1875  }
1876  }int no_fds_extracted = (0 == read_nhandles_len) &&
1884  (0 == read_fhandles_len) &&
1885  (0 == write_nhandles_len) &&
1886  (0 == write_fhandles_len);
1887  if (no_fds || no_fds_extracted)
1889  prio,
1890  task,
1891  task_cls);
1892  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1894  init_fd_info (t,
1895  read_nhandles,
1896  read_nhandles_len,
1897  write_nhandles,
1898  write_nhandles_len,
1899  read_fhandles,
1900  read_fhandles_len,
1901  write_fhandles,
1902  write_fhandles_len);
1903  t->callback = task;
1904  t->callback_cls = task_cls;
1906  /* free the arrays of pointers to network / file handles, the actual
1907  * handles will be freed in destroy_task */
1908  GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1909  GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1910  GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1911  GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1912 #if PROFILE_DELAYS
1913  t->start_time = GNUNET_TIME_absolute_get ();
1914 #endif
1916  t->priority =
1917  check_priority ((prio ==
1919  prio);
1922  pending_tail,
1923  t);
1926  t->priority);
1928  "Adding task %p\n",
1929  t);
1930  init_backtrace (t);
1931  return t;
1932 }
1933 
1934 
1946 void
1948  struct GNUNET_SCHEDULER_FdInfo *fdi)
1949 {
1950  enum GNUNET_SCHEDULER_Reason reason;
1951 
1952  reason = task->reason;
1953  if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1954  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1956  if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1957  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1960  task->reason = reason;
1961  if (GNUNET_NO == task->in_ready_list)
1962  {
1964  pending_tail,
1965  task);
1966  queue_ready_task (task);
1967  }
1968 }
1969 
1970 
1991 int
1993 {
1994  struct GNUNET_SCHEDULER_Task *pos;
1995  struct GNUNET_TIME_Absolute now;
1996 
1997  /* check for tasks that reached the timeout! */
1998  now = GNUNET_TIME_absolute_get ();
1999  pos = pending_timeout_head;
2000  while (NULL != pos)
2001  {
2002  struct GNUNET_SCHEDULER_Task *next = pos->next;
2003  if (now.abs_value_us >= pos->timeout.abs_value_us)
2005  if (0 == pos->reason)
2006  break;
2009  pos);
2010  if (pending_timeout_last == pos)
2011  pending_timeout_last = NULL;
2012  queue_ready_task (pos);
2013  pos = next;
2014  }
2015  pos = pending_head;
2016  while (NULL != pos)
2017  {
2018  struct GNUNET_SCHEDULER_Task *next = pos->next;
2019  if (now.abs_value_us >= pos->timeout.abs_value_us)
2020  {
2023  pending_tail,
2024  pos);
2025  queue_ready_task (pos);
2026  }
2027  pos = next;
2028  }
2029 
2030  if (0 == ready_count)
2031  {
2033 
2034  if (timeout.abs_value_us > now.abs_value_us)
2035  {
2050  "GNUNET_SCHEDULER_do_work did not find any ready "
2051  "tasks and timeout has not been reached yet.\n");
2052  }
2053  else
2054  {
2059  GNUNET_assert (0);
2060  }
2061  }
2062  else
2063  {
2064  /* find out which task priority level we are going to
2065  process this time */
2068  /* yes, p>0 is correct, 0 is "KEEP" which should
2069  * always be an empty queue (see assertion)! */
2071  work_priority > 0;
2072  work_priority--)
2073  {
2074  pos = ready_head[work_priority];
2075  if (NULL != pos)
2076  break;
2077  }
2078  GNUNET_assert (NULL != pos); /* ready_count wrong? */
2079 
2080  /* process all *existing* tasks at this priority
2081  level, then yield */
2083  while (NULL != (pos = ready_head[work_priority])
2084  && pos != &pass_end_marker)
2085  {
2088  pos);
2089  ready_count--;
2090  current_priority = pos->priority;
2091  current_lifeness = pos->lifeness;
2092  active_task = pos;
2093 #if PROFILE_DELAYS
2094  if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2095  DELAY_THRESHOLD.rel_value_us)
2096  {
2098  "Task %p took %s to be scheduled\n",
2099  pos,
2101  GNUNET_TIME_absolute_get_duration (pos->start_time),
2102  GNUNET_YES));
2103  }
2104 #endif
2105  tc.reason = pos->reason;
2108  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2109  tc.fds_len = pos->fds_len;
2110  tc.fds = pos->fds;
2111  for (unsigned int i = 0; i != pos->fds_len; ++i)
2112  {
2113  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2114  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2115  {
2117  fdi->sock);
2118  }
2119  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2120  {
2122  fdi->sock);
2123  }
2124  }
2125  tc.read_ready = sh->rs;
2126  tc.write_ready = sh->ws;
2128  "Running task %p\n",
2129  pos);
2130  GNUNET_assert (NULL != pos->callback);
2131  {
2132  struct GNUNET_AsyncScopeSave old_scope;
2133  if (pos->scope.have_scope)
2134  GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2135  else
2136  GNUNET_async_scope_get (&old_scope);
2137  pos->callback (pos->callback_cls);
2138  GNUNET_async_scope_restore (&old_scope);
2139  }
2140  if (NULL != pos->fds)
2141  {
2142  int del_result = scheduler_driver->del (scheduler_driver->cls,
2143  pos);
2144  if (GNUNET_OK != del_result)
2145  {
2147  "driver could not delete task %p\n", pos);
2148  GNUNET_assert (0);
2149  }
2150  }
2151  active_task = NULL;
2152  dump_backtrace (pos);
2153  destroy_task (pos);
2154  }
2156  }
2158  if (0 == ready_count)
2159  {
2161  get_timeout ());
2162  return GNUNET_NO;
2163  }
2166  return GNUNET_YES;
2167 }
2168 
2169 
2201 struct GNUNET_SCHEDULER_Handle *
2203 {
2204  struct GNUNET_SCHEDULER_Handle *sh;
2205  const struct GNUNET_DISK_FileHandle *pr;
2206 
2207  /* scheduler must not be running */
2208  GNUNET_assert (NULL == scheduler_driver);
2210  /* general set-up */
2216  my_pid = getpid ();
2217  scheduler_driver = driver;
2218 
2219  /* install signal handlers */
2221  "Registering signal handlers\n");
2222  sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2224  sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2226 #if (SIGTERM != GNUNET_TERM_SIG)
2229 #endif
2230  sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2231  &sighandler_pipe);
2232  sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2234  sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2236 
2237  /* Setup initial tasks */
2240  /* ensure this task runs first, by using a priority level reserved for
2241  the scheduler (not really shutdown, but start-up ;-) */
2245  NULL);
2248  pr,
2250  NULL);
2253  get_timeout ());
2254  /* begin main event loop */
2258  return sh;
2259 }
2260 
2261 
2276 void
2278 {
2279  GNUNET_assert (NULL == pending_head);
2281  GNUNET_assert (NULL == shutdown_head);
2282  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2283  {
2284  GNUNET_assert (NULL == ready_head[i]);
2285  }
2288 
2289  /* uninstall signal handlers */
2291  GNUNET_SIGNAL_handler_uninstall (sh->shc_term);
2292 #if (SIGTERM != GNUNET_TERM_SIG)
2293  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
2294 #endif
2295  GNUNET_SIGNAL_handler_uninstall (sh->shc_pipe);
2296  GNUNET_SIGNAL_handler_uninstall (sh->shc_quit);
2299  shutdown_pipe_handle = NULL;
2300  scheduler_driver = NULL;
2301  GNUNET_free (sh);
2302 }
2303 
2304 
2305 static int
2307  struct DriverContext *context)
2308 {
2309  struct GNUNET_NETWORK_FDSet *rs;
2310  struct GNUNET_NETWORK_FDSet *ws;
2311  int select_result;
2312 
2313  GNUNET_assert (NULL != context);
2316  while ((NULL != context->scheduled_head) ||
2317  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2318  context->timeout.abs_value_us))
2319  {
2320  struct GNUNET_TIME_Relative time_remaining;
2321 
2323  "select timeout = %s\n",
2325 
2328 
2329  for (struct Scheduled *pos = context->scheduled_head;
2330  NULL != pos;
2331  pos = pos->next)
2332  {
2333  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2334  {
2335  GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2336  }
2337  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2338  {
2339  GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2340  }
2341  }
2342  time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2343  if (0 < ready_count)
2344  time_remaining = GNUNET_TIME_UNIT_ZERO;
2345  if (NULL == scheduler_select)
2346  {
2347  select_result = GNUNET_NETWORK_socket_select (rs,
2348  ws,
2349  NULL,
2350  time_remaining);
2351  }
2352  else
2353  {
2354  select_result = scheduler_select (scheduler_select_cls,
2355  rs,
2356  ws,
2357  NULL,
2358  time_remaining);
2359  }
2360  if (select_result == GNUNET_SYSERR)
2361  {
2362  if (errno == EINTR)
2363  continue;
2364 
2366  "select");
2367 #if USE_LSOF
2368  char lsof[512];
2369 
2370  snprintf (lsof,
2371  sizeof(lsof),
2372  "lsof -p %d",
2373  getpid ());
2374  (void) close (1);
2375  (void) dup2 (2, 1);
2376  if (0 != system (lsof))
2378  "system");
2379 #endif
2380 #if DEBUG_FDS
2381  for (struct Scheduled *s = context->scheduled_head;
2382  NULL != s;
2383  s = s->next)
2384  {
2385  int flags = fcntl (s->fdi->sock,
2386  F_GETFD);
2387 
2388  if ((flags == -1) &&
2389  (EBADF == errno))
2390  {
2392  "Got invalid file descriptor %d!\n",
2393  s->fdi->sock);
2394 #if EXECINFO
2395  dump_backtrace (s->task);
2396 #endif
2397  }
2398  }
2399 #endif
2400  GNUNET_assert (0);
2403  return GNUNET_SYSERR;
2404  }
2405  if (select_result > 0)
2406  {
2407  for (struct Scheduled *pos = context->scheduled_head;
2408  NULL != pos;
2409  pos = pos->next)
2410  {
2411  int is_ready = GNUNET_NO;
2412 
2413  if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2414  (GNUNET_YES ==
2416  pos->fdi->sock)) )
2417  {
2418  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2419  is_ready = GNUNET_YES;
2420  }
2421  if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2422  (GNUNET_YES ==
2424  pos->fdi->sock)) )
2425  {
2426  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2427  is_ready = GNUNET_YES;
2428  }
2429  if (GNUNET_YES == is_ready)
2430  {
2431  GNUNET_SCHEDULER_task_ready (pos->task,
2432  pos->fdi);
2433  }
2434  }
2435  }
2437  {
2439  "scheduler has more tasks ready!\n");
2440  }
2441  }
2444  return GNUNET_OK;
2445 }
2446 
2447 
2448 static int
2449 select_add (void *cls,
2450  struct GNUNET_SCHEDULER_Task *task,
2451  struct GNUNET_SCHEDULER_FdInfo *fdi)
2452 {
2453  struct DriverContext *context = cls;
2454 
2455  GNUNET_assert (NULL != context);
2456  GNUNET_assert (NULL != task);
2457  GNUNET_assert (NULL != fdi);
2458  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2459  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2460 
2461  if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2462  {
2463  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2464  return GNUNET_SYSERR;
2465  }
2466 
2467  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2468  scheduled->task = task;
2469  scheduled->fdi = fdi;
2470  scheduled->et = fdi->et;
2471 
2472  GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2473  context->scheduled_tail,
2474  scheduled);
2475  return GNUNET_OK;
2476 }
2477 
2478 
2479 static int
2480 select_del (void *cls,
2481  struct GNUNET_SCHEDULER_Task *task)
2482 {
2483  struct DriverContext *context;
2484  struct Scheduled *pos;
2485  int ret;
2486 
2487  GNUNET_assert (NULL != cls);
2488 
2489  context = cls;
2490  ret = GNUNET_SYSERR;
2491  pos = context->scheduled_head;
2492  while (NULL != pos)
2493  {
2494  struct Scheduled *next = pos->next;
2495  if (pos->task == task)
2496  {
2497  GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2498  context->scheduled_tail,
2499  pos);
2500  GNUNET_free (pos);
2501  ret = GNUNET_OK;
2502  }
2503  pos = next;
2504  }
2505  return ret;
2506 }
2507 
2508 
2509 static void
2511  struct GNUNET_TIME_Absolute dt)
2512 {
2513  struct DriverContext *context = cls;
2514 
2515  GNUNET_assert (NULL != context);
2516  context->timeout = dt;
2517 }
2518 
2519 
2525 struct GNUNET_SCHEDULER_Driver *
2527 {
2528  struct GNUNET_SCHEDULER_Driver *select_driver;
2529 
2530  select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2531 
2532  select_driver->add = &select_add;
2533  select_driver->del = &select_del;
2534  select_driver->set_wakeup = &select_set_wakeup;
2535 
2536  return select_driver;
2537 }
2538 
2539 
2552 void
2554 {
2555  struct GNUNET_AsyncScopeSave dummy_old_scope;
2556 
2557  GNUNET_assert (NULL != active_task);
2558  /* Since we're in a task, the context will be automatically
2559  restored by the scheduler. */
2560  GNUNET_async_scope_enter (aid, &dummy_old_scope);
2561 }
2562 
2563 
2564 /* end of scheduler.c */
Internal DISK related helper functions.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct SolverHandle * sh
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_TIME_Relative delay
When should dkg communication start?
static struct GNUNET_DISK_FileHandle * fh
File handle to STDIN, for reading restart/quit commands.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static struct GNUNET_SCHEDULER_Task * t
Main task.
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:686
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1587
enum GNUNET_GenericReturnValue GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:185
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:622
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:1617
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1330
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1444
@ 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.
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_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.
@ 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.
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1170
void GNUNET_NETWORK_fdset_zero(struct GNUNET_NETWORK_FDSet *fds)
Reset FD set (clears all file descriptors).
Definition: network.c:917
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1186
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1000
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition: network.c:1057
int GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to, int nfd)
Test native fd in a set.
Definition: network.c:1075
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:565
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:1260
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:1091
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:579
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:133
void GNUNET_SCHEDULER_shutdown()
Request the shutdown of a scheduler.
Definition: scheduler.c:562
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:1540
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:720
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:1299
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition: scheduler.c:2277
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:2202
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:1577
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:1947
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:1069
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:1830
struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select()
Obtain the driver for using select() as the event loop.
Definition: scheduler.c:2526
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:1992
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:1506
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:1656
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:1113
unsigned int GNUNET_SCHEDULER_get_load(enum GNUNET_SCHEDULER_Priority p)
Get information about the current load of this scheduler.
Definition: scheduler.c:769
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:1689
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:1202
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:1367
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:2553
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:1226
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:1725
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
GNUNET_SCHEDULER_Reason
Reasons why the schedule may have triggered the task now.
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:1334
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
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
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:1249
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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:1272
GNUNET_SCHEDULER_EventType
Possible events on FDs, used as a bitmask.
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.
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:1614
@ 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:436
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:405
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:616
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_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:569
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:234
static void sighandler_pipe()
Signal handler called for SIGPIPE.
Definition: scheduler.c:667
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:595
static void driver_add_multiple(struct GNUNET_SCHEDULER_Task *t)
calls the given function func on each FdInfo related to t.
Definition: scheduler.c:909
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:2510
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition: scheduler.c:616
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:541
static int select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition: scheduler.c:2306
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition: scheduler.c:2480
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 void remove_pass_end_marker()
Definition: scheduler.c:513
#define DELAY_THRESHOLD
Task that were in the queue for longer than this are reported if PROFILE_DELAYS is active.
Definition: scheduler.c:74
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:791
static unsigned int ready_count
Number of tasks on the ready list.
Definition: scheduler.c:398
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:1434
static struct GNUNET_DISK_PipeHandle * shutdown_pipe_handle
Pipe used to communicate shutdown via signal.
Definition: scheduler.c:655
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 const struct GNUNET_SCHEDULER_Driver * scheduler_driver
The driver used for the event loop.
Definition: scheduler.c:319
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:1748
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:931
static int select_add(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Definition: scheduler.c:2449
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:694
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 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:524
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition: scheduler.c:1041
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:677
#define LOG(kind,...)
Definition: scheduler.c:32
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:940
#define LOG_STRERROR(kind, syscall)
Definition: scheduler.c:34
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:661
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.
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
struct GNUNET_AsyncScopeId scope_id
Saved 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:68
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
struct GNUNET_NETWORK_FDSet * rs
Passed here to avoid constantly allocating/deallocating this element, but generally we want to get ri...
Definition: scheduler.c:89
struct GNUNET_SIGNAL_Context * shc_quit
context of the SIGQUIT handler
Definition: scheduler.c:118
struct GNUNET_SIGNAL_Context * shc_hup
context of the SIGHUP handler
Definition: scheduler.c:123
struct GNUNET_SIGNAL_Context * shc_int
context of the SIGINT handler
Definition: scheduler.c:101
struct GNUNET_SIGNAL_Context * shc_pipe
context of the SIGPIPE handler
Definition: scheduler.c:128
struct GNUNET_NETWORK_FDSet * ws
Passed here to avoid constantly allocating/deallocating this element, but generally we want to get ri...
Definition: scheduler.c:96
struct GNUNET_SIGNAL_Context * shc_term
context of the SIGTERM handler
Definition: scheduler.c:106
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