GNUnet  0.17.6
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  */
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)
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
191 #endif
192 
199 
204 
208  int read_fd;
209 
213  int write_fd;
214 
219  int lifeness;
220 
225 
230 
231 #if EXECINFO
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 
423 static struct GNUNET_SCHEDULER_TaskContext tc;
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 
469 get_timeout ()
470 {
471  struct GNUNET_SCHEDULER_Task *pos;
472  struct GNUNET_TIME_Absolute now;
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 
517  ready_tail[p],
518  task);
519  if (p > work_priority)
520  work_priority = p;
521  task->in_ready_list = GNUNET_YES;
522  ready_count++;
523 }
524 
525 
532 void
534 {
535  struct GNUNET_SCHEDULER_Task *pos;
536 
538  "GNUNET_SCHEDULER_shutdown\n");
539  if (NULL != install_parent_control_task)
540  {
543  }
544  if (NULL != shutdown_pipe_task)
545  {
547  shutdown_pipe_task = NULL;
548  }
549  while (NULL != (pos = shutdown_head))
550  {
553  pos);
555  queue_ready_task (pos);
556  }
557 }
558 
559 
565 static void
567 {
568 #if EXECINFO
569  for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
571  "Task %p trace %u: %s\n",
572  t,
573  i,
574  t->backtrace_strings[i]);
575 #else
576  (void) t;
577 #endif
578 }
579 
580 
586 static void
588 {
590  "destroying task %p\n",
591  t);
592 
593  if (GNUNET_YES == t->own_handles)
594  {
595  for (unsigned int i = 0; i != t->fds_len; ++i)
596  {
597  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
598  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
599  if (fd)
600  {
602  (struct GNUNET_NETWORK_Handle *) fd);
603  }
604  if (fh)
605  {
606  // FIXME: on WIN32 this is not enough! A function
607  // GNUNET_DISK_file_free_memory_only would be nice
608  GNUNET_free_nz ((void *) fh);
609  }
610  }
611  }
612  if (t->fds_len > 1)
613  {
614  GNUNET_array_grow (t->fds, t->fds_len, 0);
615  }
616 #if EXECINFO
617  GNUNET_free (t->backtrace_strings);
618 #endif
619  GNUNET_free (t);
620 }
621 
622 
627 
632 static pid_t my_pid;
633 
637 static void
639 {
640  return;
641 }
642 
643 
647 static void
649 {
650  static char c;
651  int old_errno = errno; /* backup errno */
652 
653  if (getpid () != my_pid)
654  _exit (1); /* we have fork'ed since the signal handler was created,
655  * ignore the signal, see https://gnunet.org/vfork discussion */
659  &c, sizeof(c));
660  errno = old_errno;
661 }
662 
663 
664 static void
666 {
667  struct GNUNET_SCHEDULER_Task *t;
668 
669  if (ready_count > 0)
670  return;
671  for (t = pending_head; NULL != t; t = t->next)
672  if (GNUNET_YES == t->lifeness)
673  return;
674  for (t = shutdown_head; NULL != t; t = t->next)
675  if (GNUNET_YES == t->lifeness)
676  return;
677  for (t = pending_timeout_head; NULL != t; t = t->next)
678  if (GNUNET_YES == t->lifeness)
679  return;
680  /* No lifeness! */
682 }
683 
684 
685 static int
687  struct DriverContext *context);
688 
689 
704 void
706  void *task_cls)
707 {
708  struct GNUNET_SCHEDULER_Handle *sh;
709  struct GNUNET_SCHEDULER_Driver *driver;
710  struct DriverContext context = {
711  .scheduled_head = NULL,
712  .scheduled_tail = NULL,
713  .timeout = GNUNET_TIME_absolute_get ()
714  };
715 
716  driver = GNUNET_SCHEDULER_driver_select ();
717  driver->cls = &context;
718  sh = GNUNET_SCHEDULER_driver_init (driver);
720  task_cls,
723  select_loop (sh,
724  &context);
726  GNUNET_free (driver);
727 }
728 
729 
736 const struct GNUNET_SCHEDULER_TaskContext *
738 {
739  GNUNET_assert (NULL != active_task);
740  return &tc;
741 }
742 
743 
753 unsigned int
755 {
756  unsigned int ret;
757 
758  GNUNET_assert (NULL != active_task);
760  return ready_count;
763  ret = 0;
764  for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)];
765  NULL != pos;
766  pos = pos->next)
767  ret++;
768  return ret;
769 }
770 
771 
772 void
774  const struct GNUNET_NETWORK_Handle *const *read_nh,
775  unsigned int read_nh_len,
776  const struct GNUNET_NETWORK_Handle *const *write_nh,
777  unsigned int write_nh_len,
778  const struct GNUNET_DISK_FileHandle *const *read_fh,
779  unsigned int read_fh_len,
780  const struct GNUNET_DISK_FileHandle *const *write_fh,
781  unsigned int write_fh_len)
782 {
783  // FIXME: if we have exactly two network handles / exactly two file handles
784  // and they are equal, we can make one FdInfo with both
785  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
786  struct GNUNET_SCHEDULER_FdInfo *fdi;
787 
788  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
789  if (1 == t->fds_len)
790  {
791  fdi = &t->fdx;
792  t->fds = fdi;
793  if (1 == read_nh_len)
794  {
795  GNUNET_assert (NULL != read_nh);
796  GNUNET_assert (NULL != *read_nh);
797  fdi->fd = *read_nh;
798  fdi->et = GNUNET_SCHEDULER_ET_IN;
799  fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
800  t->read_fd = fdi->sock;
801  t->write_fd = -1;
802  }
803  else if (1 == write_nh_len)
804  {
805  GNUNET_assert (NULL != write_nh);
806  GNUNET_assert (NULL != *write_nh);
807  fdi->fd = *write_nh;
809  fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
810  t->read_fd = -1;
811  t->write_fd = fdi->sock;
812  }
813  else if (1 == read_fh_len)
814  {
815  GNUNET_assert (NULL != read_fh);
816  GNUNET_assert (NULL != *read_fh);
817  fdi->fh = *read_fh;
818  fdi->et = GNUNET_SCHEDULER_ET_IN;
819  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
820  t->read_fd = fdi->sock;
821  t->write_fd = -1;
822  }
823  else
824  {
825  GNUNET_assert (NULL != write_fh);
826  GNUNET_assert (NULL != *write_fh);
827  fdi->fh = *write_fh;
829  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
830  t->read_fd = -1;
831  t->write_fd = fdi->sock;
832  }
833  }
834  else
835  {
837  t->fds = fdi;
838  t->read_fd = -1;
839  t->write_fd = -1;
840  unsigned int i;
841  for (i = 0; i != read_nh_len; ++i)
842  {
843  fdi->fd = read_nh[i];
844  GNUNET_assert (NULL != fdi->fd);
845  fdi->et = GNUNET_SCHEDULER_ET_IN;
846  fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
847  ++fdi;
848  }
849  for (i = 0; i != write_nh_len; ++i)
850  {
851  fdi->fd = write_nh[i];
852  GNUNET_assert (NULL != fdi->fd);
854  fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
855  ++fdi;
856  }
857  for (i = 0; i != read_fh_len; ++i)
858  {
859  fdi->fh = read_fh[i];
860  GNUNET_assert (NULL != fdi->fh);
861  fdi->et = GNUNET_SCHEDULER_ET_IN;
862  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
863  ++fdi;
864  }
865  for (i = 0; i != write_fh_len; ++i)
866  {
867  fdi->fh = write_fh[i];
868  GNUNET_assert (NULL != fdi->fh);
870  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
871  ++fdi;
872  }
873  }
874 }
875 
876 
890 static void
892 {
893  struct GNUNET_SCHEDULER_FdInfo *fdi;
894  int success = GNUNET_YES;
895 
896  for (unsigned int i = 0; i != t->fds_len; ++i)
897  {
898  fdi = &t->fds[i];
900  t,
901  fdi) && success;
903  }
904  if (GNUNET_YES != success)
905  {
907  "driver could not add task\n");
908  }
909 }
910 
911 
912 static void
914 {
915  (void) cls;
918 }
919 
920 
921 static void
922 shutdown_pipe_cb (void *cls)
923 {
924  char c;
925  const struct GNUNET_DISK_FileHandle *pr;
926 
927  (void) cls;
928  shutdown_pipe_task = NULL;
932  /* consume the signal */
933  GNUNET_DISK_file_read (pr, &c, sizeof(c));
934  /* mark all active tasks as ready due to shutdown */
938  pr,
940  NULL);
941 }
942 
943 
956 void *
958 {
960  int is_fd_task;
961  void *ret;
962 
964  "canceling task %p\n",
965  task);
966 
967  /* scheduler must be running */
969  is_fd_task = (NULL != task->fds);
970  if (is_fd_task)
971  {
972  int del_result = scheduler_driver->del (scheduler_driver->cls, task);
973  if (GNUNET_OK != del_result)
974  {
976  "driver could not delete task\n");
977  GNUNET_assert (0);
978  }
979  }
980  if (! task->in_ready_list)
981  {
982  if (is_fd_task)
983  {
985  pending_tail,
986  task);
987  }
988  else if (GNUNET_YES == task->on_shutdown)
989  {
992  task);
993  }
994  else
995  {
998  task);
999  if (pending_timeout_last == task)
1000  pending_timeout_last = NULL;
1001  }
1002  }
1003  else
1004  {
1005  p = check_priority (task->priority);
1007  ready_tail[p],
1008  task);
1009  ready_count--;
1010  }
1011  ret = task->callback_cls;
1012  destroy_task (task);
1013  return ret;
1014 }
1015 
1016 
1022 static void
1024 {
1025 #if EXECINFO
1026  void *backtrace_array[MAX_TRACE_DEPTH];
1027 
1028  t->num_backtrace_strings
1029  = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1030  t->backtrace_strings =
1031  backtrace_symbols (backtrace_array,
1032  t->num_backtrace_strings);
1033  dump_backtrace (t);
1034 #else
1035  (void) t;
1036 #endif
1037 }
1038 
1039 
1050 void
1052  task,
1053  void *task_cls,
1055  reason,
1057  priority)
1058 {
1059  struct GNUNET_SCHEDULER_Task *t;
1060 
1061  /* scheduler must be running */
1062  GNUNET_assert (NULL != scheduler_driver);
1063  GNUNET_assert (NULL != task);
1064  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1065  t->read_fd = -1;
1066  t->write_fd = -1;
1067  t->callback = task;
1068  t->callback_cls = task_cls;
1069 #if PROFILE_DELAYS
1070  t->start_time = GNUNET_TIME_absolute_get ();
1071 #endif
1072  t->reason = reason;
1076  "Adding continuation task %p\n",
1077  t);
1078  init_backtrace (t);
1079  queue_ready_task (t);
1080 }
1081 
1082 
1094 struct GNUNET_SCHEDULER_Task *
1098  void *task_cls)
1099 {
1100  struct GNUNET_SCHEDULER_Task *t;
1101  struct GNUNET_SCHEDULER_Task *pos;
1102  struct GNUNET_SCHEDULER_Task *prev;
1103  struct GNUNET_TIME_Relative left;
1104 
1105  /* scheduler must be running */
1106  GNUNET_assert (NULL != scheduler_driver);
1107  GNUNET_assert (NULL != task);
1108  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1110  t->callback = task;
1111  t->callback_cls = task_cls;
1112  t->read_fd = -1;
1113  t->write_fd = -1;
1114 #if PROFILE_DELAYS
1115  t->start_time = GNUNET_TIME_absolute_get ();
1116 #endif
1117  t->timeout = at;
1118  t->priority = check_priority (priority);
1120  init_backtrace (t);
1121 
1123  if (0 == left.rel_value_us)
1124  {
1125  queue_ready_task (t);
1126  if (priority > work_priority)
1127  work_priority = priority;
1128  return t;
1129  }
1130 
1131  /* try tail first (optimization in case we are
1132  * appending to a long list of tasks with timeouts) */
1133  if ((NULL == pending_timeout_head) ||
1135  {
1138  t);
1139  }
1140  else
1141  {
1142  /* first move from heuristic start backwards to before start time */
1143  prev = pending_timeout_last;
1144  while ((NULL != prev) &&
1146  prev = prev->prev;
1147  /* now, move from heuristic start (or head of list) forward to insertion point */
1148  if (NULL == prev)
1149  pos = pending_timeout_head;
1150  else
1151  pos = prev->next;
1152  while ((NULL != pos) && (pos->timeout.abs_value_us <=
1154  {
1155  prev = pos;
1156  pos = pos->next;
1157  }
1160  prev,
1161  t);
1162  }
1163  /* finally, update heuristic insertion point to last insertion... */
1166  "Adding task %p\n",
1167  t);
1168  return t;
1169 }
1170 
1171 
1183 struct GNUNET_SCHEDULER_Task *
1186  priority,
1188  void *task_cls)
1189 {
1192  priority,
1193  task,
1194  task_cls);
1195 }
1196 
1197 
1207 struct GNUNET_SCHEDULER_Task *
1210  void *task_cls)
1211 {
1213  prio,
1214  task,
1215  task_cls);
1216 }
1217 
1218 
1230 struct GNUNET_SCHEDULER_Task *
1233  void *task_cls)
1234 {
1237  task,
1238  task_cls);
1239 }
1240 
1241 
1253 struct GNUNET_SCHEDULER_Task *
1256  void *task_cls)
1257 {
1260  task,
1261  task_cls);
1262 }
1263 
1264 
1280 struct GNUNET_SCHEDULER_Task *
1282  void *task_cls)
1283 {
1284  struct GNUNET_SCHEDULER_Task *t;
1285 
1286  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1288  t->callback = task;
1289  t->callback_cls = task_cls;
1290  t->read_fd = -1;
1291  t->write_fd = -1;
1292 #if PROFILE_DELAYS
1293  t->start_time = GNUNET_TIME_absolute_get ();
1294 #endif
1299  queue_ready_task (t);
1300  init_backtrace (t);
1301  return t;
1302 }
1303 
1304 
1315 struct GNUNET_SCHEDULER_Task *
1317  void *task_cls)
1318 {
1319  struct GNUNET_SCHEDULER_Task *t;
1320 
1321  /* scheduler must be running */
1322  GNUNET_assert (NULL != scheduler_driver);
1323  GNUNET_assert (NULL != task);
1324  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1326  t->callback = task;
1327  t->callback_cls = task_cls;
1328  t->read_fd = -1;
1329  t->write_fd = -1;
1330 #if PROFILE_DELAYS
1331  t->start_time = GNUNET_TIME_absolute_get ();
1332 #endif
1336  t->lifeness = GNUNET_NO;
1338  shutdown_tail,
1339  t);
1341  "Adding shutdown task %p\n",
1342  t);
1343  init_backtrace (t);
1344  return t;
1345 }
1346 
1347 
1362 struct GNUNET_SCHEDULER_Task *
1365  void *task_cls)
1366 {
1367  struct GNUNET_SCHEDULER_Task *ret;
1368 
1369  ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1370  ret->lifeness = lifeness;
1371  return ret;
1372 }
1373 
1374 
1375 #if DEBUG_FDS
1382 void
1383 check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1384 {
1385  if (-1 != raw_fd)
1386  {
1387  int flags = fcntl (raw_fd, F_GETFD);
1388 
1389  if ((flags == -1) && (errno == EBADF))
1390  {
1392  "Got invalid file descriptor %d!\n",
1393  raw_fd);
1394  init_backtrace (t);
1395  GNUNET_assert (0);
1396  }
1397  }
1398 }
1399 
1400 
1401 #endif
1402 
1403 
1429 static struct GNUNET_SCHEDULER_Task *
1432  const struct GNUNET_NETWORK_Handle *read_nh,
1433  const struct GNUNET_NETWORK_Handle *write_nh,
1434  const struct GNUNET_DISK_FileHandle *read_fh,
1435  const struct GNUNET_DISK_FileHandle *write_fh,
1437  void *task_cls)
1438 {
1439  struct GNUNET_SCHEDULER_Task *t;
1440 
1441  /* scheduler must be running */
1442  GNUNET_assert (NULL != scheduler_driver);
1443  GNUNET_assert (NULL != task);
1444  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1446  init_fd_info (t,
1447  &read_nh,
1448  read_nh ? 1 : 0,
1449  &write_nh,
1450  write_nh ? 1 : 0,
1451  &read_fh,
1452  read_fh ? 1 : 0,
1453  &write_fh,
1454  write_fh ? 1 : 0);
1455  t->callback = task;
1456  t->callback_cls = task_cls;
1457 #if DEBUG_FDS
1458  check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1459  check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1460  check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1461  check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1462 #endif
1463 #if PROFILE_DELAYS
1464  t->start_time = GNUNET_TIME_absolute_get ();
1465 #endif
1471  pending_tail,
1472  t);
1475  t->priority);
1476  init_backtrace (t);
1477  return t;
1478 }
1479 
1480 
1501 struct GNUNET_SCHEDULER_Task *
1503  struct GNUNET_NETWORK_Handle *rfd,
1505  void *task_cls)
1506 {
1509  rfd, task, task_cls);
1510 }
1511 
1512 
1535 struct GNUNET_SCHEDULER_Task *
1538  priority,
1539  struct GNUNET_NETWORK_Handle *rfd,
1541  void *task_cls)
1542 {
1544  rfd,
1545  GNUNET_YES,
1546  GNUNET_NO,
1547  task, task_cls);
1548 }
1549 
1550 
1572 struct GNUNET_SCHEDULER_Task *
1574  struct GNUNET_NETWORK_Handle *wfd,
1576  void *task_cls)
1577 {
1580  wfd,
1582  task, task_cls);
1583 }
1584 
1585 
1609 struct GNUNET_SCHEDULER_Task *
1612  struct GNUNET_NETWORK_Handle *fd,
1613  int on_read,
1614  int on_write,
1616  void *task_cls)
1617 {
1618  /* scheduler must be running */
1619  GNUNET_assert (NULL != scheduler_driver);
1620  GNUNET_assert (on_read || on_write);
1622  return add_without_sets (delay, priority,
1623  on_read ? fd : NULL,
1624  on_write ? fd : NULL,
1625  NULL,
1626  NULL,
1627  task, task_cls);
1628 }
1629 
1630 
1651 struct GNUNET_SCHEDULER_Task *
1653  const struct GNUNET_DISK_FileHandle *rfd,
1655  void *task_cls)
1656 {
1659  rfd, GNUNET_YES, GNUNET_NO,
1660  task, task_cls);
1661 }
1662 
1663 
1684 struct GNUNET_SCHEDULER_Task *
1686  const struct GNUNET_DISK_FileHandle *wfd,
1688  void *task_cls)
1689 {
1692  wfd, GNUNET_NO, GNUNET_YES,
1693  task, task_cls);
1694 }
1695 
1696 
1720 struct GNUNET_SCHEDULER_Task *
1723  priority,
1724  const struct
1726  int on_read, int on_write,
1728  void *task_cls)
1729 {
1730  /* scheduler must be running */
1731  GNUNET_assert (NULL != scheduler_driver);
1732  GNUNET_assert (on_read || on_write);
1733  GNUNET_assert (fd->fd >= 0);
1734  return add_without_sets (delay, priority,
1735  NULL,
1736  NULL,
1737  on_read ? fd : NULL,
1738  on_write ? fd : NULL,
1739  task, task_cls);
1740 }
1741 
1742 
1743 void
1745  const struct GNUNET_NETWORK_Handle ***ntarget,
1746  unsigned int *extracted_nhandles,
1747  const struct GNUNET_DISK_FileHandle ***ftarget,
1748  unsigned int *extracted_fhandles)
1749 {
1750  // FIXME: this implementation only works for unix, for WIN32 the file handles
1751  // in fdset must be handled separately
1752  const struct GNUNET_NETWORK_Handle **nhandles;
1753  const struct GNUNET_DISK_FileHandle **fhandles;
1754  unsigned int nhandles_len;
1755  unsigned int fhandles_len;
1756 
1757  nhandles = NULL;
1758  fhandles = NULL;
1759  nhandles_len = 0;
1760  fhandles_len = 0;
1761  for (int sock = 0; sock != fdset->nsds; ++sock)
1762  {
1763  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1764  {
1765  struct GNUNET_NETWORK_Handle *nhandle;
1766  struct GNUNET_DISK_FileHandle *fhandle;
1767 
1768  nhandle = GNUNET_NETWORK_socket_box_native (sock);
1769  if (NULL != nhandle)
1770  {
1771  GNUNET_array_append (nhandles, nhandles_len, nhandle);
1772  }
1773  else
1774  {
1775  fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1776  if (NULL != fhandle)
1777  {
1778  GNUNET_array_append (fhandles, fhandles_len, fhandle);
1779  }
1780  else
1781  {
1782  GNUNET_assert (0);
1783  }
1784  }
1785  }
1786  }
1787  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1788  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1789  *extracted_nhandles = nhandles_len;
1790  *extracted_fhandles = fhandles_len;
1791 }
1792 
1793 
1825 struct GNUNET_SCHEDULER_Task *
1827  struct GNUNET_TIME_Relative delay,
1828  const struct GNUNET_NETWORK_FDSet *rs,
1829  const struct GNUNET_NETWORK_FDSet *ws,
1831  void *task_cls)
1832 {
1833  struct GNUNET_SCHEDULER_Task *t;
1834  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1835  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1836  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1837  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1838  unsigned int read_nhandles_len = 0;
1839  unsigned int write_nhandles_len = 0;
1840  unsigned int read_fhandles_len = 0;
1841  unsigned int write_fhandles_len = 0;
1842 
1843  /* scheduler must be running */
1844  GNUNET_assert (NULL != scheduler_driver);
1845  GNUNET_assert (NULL != task);
1846  int no_rs = (NULL == rs);
1847  int no_ws = (NULL == ws);
1848  int empty_rs = (NULL != rs) && (0 == rs->nsds);
1849  int empty_ws = (NULL != ws) && (0 == ws->nsds);
1850  int no_fds = (no_rs && no_ws) ||
1851  (empty_rs && empty_ws) ||
1852  (no_rs && empty_ws) ||
1853  (no_ws && empty_rs);
1854  if (! no_fds)
1855  {
1856  if (NULL != rs)
1857  {
1858  extract_handles (rs,
1859  &read_nhandles,
1860  &read_nhandles_len,
1861  &read_fhandles,
1862  &read_fhandles_len);
1863  }
1864  if (NULL != ws)
1865  {
1866  extract_handles (ws,
1867  &write_nhandles,
1868  &write_nhandles_len,
1869  &write_fhandles,
1870  &write_fhandles_len);
1871  }
1872  }int no_fds_extracted = (0 == read_nhandles_len) &&
1880  (0 == read_fhandles_len) &&
1881  (0 == write_nhandles_len) &&
1882  (0 == write_fhandles_len);
1883  if (no_fds || no_fds_extracted)
1885  prio,
1886  task,
1887  task_cls);
1888  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1890  init_fd_info (t,
1891  read_nhandles,
1892  read_nhandles_len,
1893  write_nhandles,
1894  write_nhandles_len,
1895  read_fhandles,
1896  read_fhandles_len,
1897  write_fhandles,
1898  write_fhandles_len);
1899  t->callback = task;
1900  t->callback_cls = task_cls;
1902  /* free the arrays of pointers to network / file handles, the actual
1903  * handles will be freed in destroy_task */
1904  GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1905  GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1906  GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1907  GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1908 #if PROFILE_DELAYS
1909  t->start_time = GNUNET_TIME_absolute_get ();
1910 #endif
1912  t->priority =
1913  check_priority ((prio ==
1915  prio);
1918  pending_tail,
1919  t);
1922  t->priority);
1924  "Adding task %p\n",
1925  t);
1926  init_backtrace (t);
1927  return t;
1928 }
1929 
1930 
1942 void
1944  struct GNUNET_SCHEDULER_FdInfo *fdi)
1945 {
1946  enum GNUNET_SCHEDULER_Reason reason;
1947 
1948  reason = task->reason;
1949  if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1950  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1952  if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1953  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1956  task->reason = reason;
1957  if (GNUNET_NO == task->in_ready_list)
1958  {
1960  pending_tail,
1961  task);
1962  queue_ready_task (task);
1963  }
1964 }
1965 
1966 
1987 int
1989 {
1990  struct GNUNET_SCHEDULER_Task *pos;
1991  struct GNUNET_TIME_Absolute now;
1992 
1993  /* check for tasks that reached the timeout! */
1994  now = GNUNET_TIME_absolute_get ();
1995  pos = pending_timeout_head;
1996  while (NULL != pos)
1997  {
1998  struct GNUNET_SCHEDULER_Task *next = pos->next;
1999  if (now.abs_value_us >= pos->timeout.abs_value_us)
2001  if (0 == pos->reason)
2002  break;
2005  pos);
2006  if (pending_timeout_last == pos)
2007  pending_timeout_last = NULL;
2008  queue_ready_task (pos);
2009  pos = next;
2010  }
2011  pos = pending_head;
2012  while (NULL != pos)
2013  {
2014  struct GNUNET_SCHEDULER_Task *next = pos->next;
2015  if (now.abs_value_us >= pos->timeout.abs_value_us)
2016  {
2019  pending_tail,
2020  pos);
2021  queue_ready_task (pos);
2022  }
2023  pos = next;
2024  }
2025 
2026  if (0 == ready_count)
2027  {
2029 
2030  if (timeout.abs_value_us > now.abs_value_us)
2031  {
2046  "GNUNET_SCHEDULER_do_work did not find any ready "
2047  "tasks and timeout has not been reached yet.\n");
2048  }
2049  else
2050  {
2055  GNUNET_assert (0);
2056  }
2057  }
2058  else
2059  {
2060  struct GNUNET_SCHEDULER_Task *last;
2061 
2062  /* find out which task priority level we are going to
2063  process this time */
2066  /* yes, p>0 is correct, 0 is "KEEP" which should
2067  * always be an empty queue (see assertion)! */
2069  work_priority > 0;
2070  work_priority--)
2071  {
2072  pos = ready_head[work_priority];
2073  if (NULL != pos)
2074  break;
2075  }
2076  GNUNET_assert (NULL != pos); /* ready_count wrong? */
2077 
2078  /* process all *existing* tasks at this priority
2079  level, then yield */
2080  last = ready_tail[work_priority];
2081  while (NULL != (pos = ready_head[work_priority]))
2082  {
2085  pos);
2086  ready_count--;
2087  current_priority = pos->priority;
2088  current_lifeness = pos->lifeness;
2089  active_task = pos;
2090 #if PROFILE_DELAYS
2091  if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2092  DELAY_THRESHOLD.rel_value_us)
2093  {
2095  "Task %p took %s to be scheduled\n",
2096  pos,
2098  GNUNET_TIME_absolute_get_duration (pos->start_time),
2099  GNUNET_YES));
2100  }
2101 #endif
2102  tc.reason = pos->reason;
2105  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2106  tc.fds_len = pos->fds_len;
2107  tc.fds = pos->fds;
2108  for (unsigned int i = 0; i != pos->fds_len; ++i)
2109  {
2110  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2111  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2112  {
2114  fdi->sock);
2115  }
2116  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2117  {
2119  fdi->sock);
2120  }
2121  }
2122  tc.read_ready = sh->rs;
2123  tc.write_ready = sh->ws;
2125  "Running task %p\n",
2126  pos);
2127  GNUNET_assert (NULL != pos->callback);
2128  {
2129  struct GNUNET_AsyncScopeSave old_scope;
2130  if (pos->scope.have_scope)
2131  GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2132  else
2133  GNUNET_async_scope_get (&old_scope);
2134  pos->callback (pos->callback_cls);
2135  GNUNET_async_scope_restore (&old_scope);
2136  }
2137  if (NULL != pos->fds)
2138  {
2139  int del_result = scheduler_driver->del (scheduler_driver->cls,
2140  pos);
2141  if (GNUNET_OK != del_result)
2142  {
2144  "driver could not delete task %p\n", pos);
2145  GNUNET_assert (0);
2146  }
2147  }
2148  active_task = NULL;
2149  dump_backtrace (pos);
2150  destroy_task (pos);
2151  /* pointer 'pos' was free'd, but we can still safely check for
2152  pointer equality still. */
2153  if (pos == last)
2154  break; /* All tasks that _were_ ready when we started were
2155  executed. New tasks may have been added in the
2156  meantime, but we should check with the OS to
2157  be sure no higher-priority actions are pending! */
2158  }
2159  }
2161  if (0 == ready_count)
2162  {
2164  get_timeout ());
2165  return GNUNET_NO;
2166  }
2169  return GNUNET_YES;
2170 }
2171 
2172 
2204 struct GNUNET_SCHEDULER_Handle *
2206 {
2207  struct GNUNET_SCHEDULER_Handle *sh;
2208  const struct GNUNET_DISK_FileHandle *pr;
2209 
2210  /* scheduler must not be running */
2211  GNUNET_assert (NULL == scheduler_driver);
2213  /* general set-up */
2219  my_pid = getpid ();
2220  scheduler_driver = driver;
2221 
2222  /* install signal handlers */
2224  "Registering signal handlers\n");
2225  sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2227  sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2229 #if (SIGTERM != GNUNET_TERM_SIG)
2232 #endif
2233  sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2234  &sighandler_pipe);
2235  sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2237  sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2239 
2240  /* Setup initial tasks */
2243  /* ensure this task runs first, by using a priority level reserved for
2244  the scheduler (not really shutdown, but start-up ;-) */
2248  NULL);
2251  pr,
2253  NULL);
2256  get_timeout ());
2257  /* begin main event loop */
2261  return sh;
2262 }
2263 
2264 
2279 void
2281 {
2282  GNUNET_assert (NULL == pending_head);
2284  GNUNET_assert (NULL == shutdown_head);
2285  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2286  {
2287  GNUNET_assert (NULL == ready_head[i]);
2288  }
2291 
2292  /* uninstall signal handlers */
2294  GNUNET_SIGNAL_handler_uninstall (sh->shc_term);
2295 #if (SIGTERM != GNUNET_TERM_SIG)
2296  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
2297 #endif
2298  GNUNET_SIGNAL_handler_uninstall (sh->shc_pipe);
2299  GNUNET_SIGNAL_handler_uninstall (sh->shc_quit);
2302  shutdown_pipe_handle = NULL;
2303  scheduler_driver = NULL;
2304  GNUNET_free (sh);
2305 }
2306 
2307 
2308 static int
2310  struct DriverContext *context)
2311 {
2312  struct GNUNET_NETWORK_FDSet *rs;
2313  struct GNUNET_NETWORK_FDSet *ws;
2314  int select_result;
2315 
2316  GNUNET_assert (NULL != context);
2319  while ((NULL != context->scheduled_head) ||
2320  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2321  context->timeout.abs_value_us))
2322  {
2323  struct GNUNET_TIME_Relative time_remaining;
2324 
2326  "select timeout = %s\n",
2328 
2331 
2332  for (struct Scheduled *pos = context->scheduled_head;
2333  NULL != pos;
2334  pos = pos->next)
2335  {
2336  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2337  {
2338  GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2339  }
2340  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2341  {
2342  GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2343  }
2344  }
2345  time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2346  if (0 < ready_count)
2347  time_remaining = GNUNET_TIME_UNIT_ZERO;
2348  if (NULL == scheduler_select)
2349  {
2350  select_result = GNUNET_NETWORK_socket_select (rs,
2351  ws,
2352  NULL,
2353  time_remaining);
2354  }
2355  else
2356  {
2357  select_result = scheduler_select (scheduler_select_cls,
2358  rs,
2359  ws,
2360  NULL,
2361  time_remaining);
2362  }
2363  if (select_result == GNUNET_SYSERR)
2364  {
2365  if (errno == EINTR)
2366  continue;
2367 
2369  "select");
2370 #if USE_LSOF
2371  char lsof[512];
2372 
2373  snprintf (lsof,
2374  sizeof(lsof),
2375  "lsof -p %d",
2376  getpid ());
2377  (void) close (1);
2378  (void) dup2 (2, 1);
2379  if (0 != system (lsof))
2381  "system");
2382 #endif
2383 #if DEBUG_FDS
2384  for (struct Scheduled *s = context->scheduled_head;
2385  NULL != s;
2386  s = s->next)
2387  {
2388  int flags = fcntl (s->fdi->sock,
2389  F_GETFD);
2390 
2391  if ((flags == -1) &&
2392  (EBADF == errno))
2393  {
2395  "Got invalid file descriptor %d!\n",
2396  s->fdi->sock);
2397 #if EXECINFO
2398  dump_backtrace (s->task);
2399 #endif
2400  }
2401  }
2402 #endif
2403  GNUNET_assert (0);
2406  return GNUNET_SYSERR;
2407  }
2408  if (select_result > 0)
2409  {
2410  for (struct Scheduled *pos = context->scheduled_head;
2411  NULL != pos;
2412  pos = pos->next)
2413  {
2414  int is_ready = GNUNET_NO;
2415 
2416  if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2417  (GNUNET_YES ==
2419  pos->fdi->sock)) )
2420  {
2421  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2422  is_ready = GNUNET_YES;
2423  }
2424  if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2425  (GNUNET_YES ==
2427  pos->fdi->sock)) )
2428  {
2429  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2430  is_ready = GNUNET_YES;
2431  }
2432  if (GNUNET_YES == is_ready)
2433  {
2434  GNUNET_SCHEDULER_task_ready (pos->task,
2435  pos->fdi);
2436  }
2437  }
2438  }
2440  {
2442  "scheduler has more tasks ready!\n");
2443  }
2444  }
2447  return GNUNET_OK;
2448 }
2449 
2450 
2451 static int
2452 select_add (void *cls,
2453  struct GNUNET_SCHEDULER_Task *task,
2454  struct GNUNET_SCHEDULER_FdInfo *fdi)
2455 {
2456  struct DriverContext *context = cls;
2457 
2458  GNUNET_assert (NULL != context);
2459  GNUNET_assert (NULL != task);
2460  GNUNET_assert (NULL != fdi);
2461  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2462  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2463 
2464  if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2465  {
2466  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2467  return GNUNET_SYSERR;
2468  }
2469 
2470  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2471  scheduled->task = task;
2472  scheduled->fdi = fdi;
2473  scheduled->et = fdi->et;
2474 
2475  GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2476  context->scheduled_tail,
2477  scheduled);
2478  return GNUNET_OK;
2479 }
2480 
2481 
2482 static int
2483 select_del (void *cls,
2484  struct GNUNET_SCHEDULER_Task *task)
2485 {
2486  struct DriverContext *context;
2487  struct Scheduled *pos;
2488  int ret;
2489 
2490  GNUNET_assert (NULL != cls);
2491 
2492  context = cls;
2493  ret = GNUNET_SYSERR;
2494  pos = context->scheduled_head;
2495  while (NULL != pos)
2496  {
2497  struct Scheduled *next = pos->next;
2498  if (pos->task == task)
2499  {
2500  GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2501  context->scheduled_tail,
2502  pos);
2503  GNUNET_free (pos);
2504  ret = GNUNET_OK;
2505  }
2506  pos = next;
2507  }
2508  return ret;
2509 }
2510 
2511 
2512 static void
2514  struct GNUNET_TIME_Absolute dt)
2515 {
2516  struct DriverContext *context = cls;
2517 
2518  GNUNET_assert (NULL != context);
2519  context->timeout = dt;
2520 }
2521 
2522 
2528 struct GNUNET_SCHEDULER_Driver *
2530 {
2531  struct GNUNET_SCHEDULER_Driver *select_driver;
2532 
2533  select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2534 
2535  select_driver->add = &select_add;
2536  select_driver->del = &select_del;
2537  select_driver->set_wakeup = &select_set_wakeup;
2538 
2539  return select_driver;
2540 }
2541 
2542 
2555 void
2557 {
2558  struct GNUNET_AsyncScopeSave dummy_old_scope;
2559 
2560  GNUNET_assert (NULL != active_task);
2561  /* Since we're in a task, the context will be automatically
2562  restored by the scheduler. */
2563  GNUNET_async_scope_enter (aid, &dummy_old_scope);
2564 }
2565 
2566 
2567 /* 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:37
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:1585
enum GNUNET_GenericReturnValue GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:186
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:1616
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1328
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1442
@ 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
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#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:1193
void GNUNET_NETWORK_fdset_zero(struct GNUNET_NETWORK_FDSet *fds)
Reset FD set (clears all file descriptors).
Definition: network.c:940
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1209
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1023
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition: network.c:1080
int GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to, int nfd)
Test native fd in a set.
Definition: network.c:1098
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:570
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:1283
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:1114
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:584
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:140
void GNUNET_SCHEDULER_shutdown()
Request the shutdown of a scheduler.
Definition: scheduler.c:533
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:1536
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:705
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:1281
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition: scheduler.c:2280
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:2205
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:1573
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:1943
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:1051
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:1826
struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select()
Obtain the driver for using select() as the event loop.
Definition: scheduler.c:2529
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:1988
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:1502
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:1652
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:1095
unsigned int GNUNET_SCHEDULER_get_load(enum GNUNET_SCHEDULER_Priority p)
Get information about the current load of this scheduler.
Definition: scheduler.c:754
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:1685
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:1184
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:1363
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:2556
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:1208
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:1721
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
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:1316
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:737
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:1231
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
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:1254
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:1610
@ 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:51
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal handler.
Definition: signal.c:77
#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:435
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:404
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:110
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:617
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:315
#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:570
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:233
static void sighandler_pipe()
Signal handler called for SIGPIPE.
Definition: scheduler.c:638
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:566
static void driver_add_multiple(struct GNUNET_SCHEDULER_Task *t)
calls the given function func on each FdInfo related to t.
Definition: scheduler.c:891
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
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition: scheduler.c:2513
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition: scheduler.c:587
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
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
static int select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition: scheduler.c:2309
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition: scheduler.c:2483
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
static struct GNUNET_SCHEDULER_Task * active_task
ID of the task that is running right now.
Definition: scheduler.c:360
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
static enum GNUNET_SCHEDULER_Priority current_priority
Priority of the task running right now.
Definition: scheduler.c:396
static struct GNUNET_SCHEDULER_Task * pending_head
Head of list of tasks waiting for an event.
Definition: scheduler.c:316
#define DELAY_THRESHOLD
Task that were in the queue for longer than this are reported if PROFILE_DELAYS is active.
Definition: scheduler.c:73
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:773
static unsigned int ready_count
Number of tasks on the ready list.
Definition: scheduler.c:390
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:1430
static struct GNUNET_DISK_PipeHandle * shutdown_pipe_handle
Pipe used to communicate shutdown via signal.
Definition: scheduler.c:626
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
static const struct GNUNET_SCHEDULER_Driver * scheduler_driver
The driver used for the event loop.
Definition: scheduler.c:311
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:1744
static struct GNUNET_SCHEDULER_Task * pending_timeout_head
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:340
static void install_parent_control_handler(void *cls)
Definition: scheduler.c:913
static int select_add(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Definition: scheduler.c:2452
static GNUNET_SCHEDULER_select scheduler_select
Function to use as a select() in the scheduler.
Definition: scheduler.c:418
static enum GNUNET_SCHEDULER_Priority work_priority
Priority used currently in GNUNET_SCHEDULER_do_work().
Definition: scheduler.c:412
static void shutdown_if_no_lifeness(void)
Definition: scheduler.c:665
static void * scheduler_select_cls
Closure for scheduler_select.
Definition: scheduler.c:428
static struct GNUNET_SCHEDULER_Task * pending_timeout_tail
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:349
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
static int current_lifeness
Value of the 'lifeness' flag for the current task.
Definition: scheduler.c:407
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition: scheduler.c:1023
static enum GNUNET_SCHEDULER_Priority max_priority_added
Priority of the highest task added in the current select iteration.
Definition: scheduler.c:402
static struct GNUNET_SCHEDULER_Task * pending_timeout_last
Last inserted task waiting ONLY for a timeout event.
Definition: scheduler.c:355
static void sighandler_shutdown(void)
Signal handler called for signals that should cause us to shutdown.
Definition: scheduler.c:648
#define LOG(kind,...)
Definition: scheduler.c:31
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:922
#define LOG_STRERROR(kind, syscall)
Definition: scheduler.c:33
static struct GNUNET_SCHEDULER_Task * pending_tail
Tail of list of tasks waiting for an event.
Definition: scheduler.c:321
static struct GNUNET_SCHEDULER_Task * shutdown_tail
Tail of list of tasks waiting for shutdown.
Definition: scheduler.c:331
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:423
static struct GNUNET_SCHEDULER_Task * shutdown_head
Head of list of tasks waiting for shutdown.
Definition: scheduler.c:326
static pid_t my_pid
Process ID of this process at the time we installed the various signal handlers.
Definition: scheduler.c:632
Driver context used by GNUNET_SCHEDULER_run.
Definition: scheduler.c:283
struct Scheduled * scheduled_head
the head of a DLL containing information about the events the select driver is waiting for
Definition: scheduler.c:288
struct GNUNET_TIME_Absolute timeout
the time when the select driver will wake up again (after calling select)
Definition: scheduler.c:300
struct Scheduled * scheduled_tail
the tail of a DLL containing information about the events the select driver is waiting for
Definition: scheduler.c:294
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:69
collection of IO descriptors
int nsds
Maximum number of any socket descriptor in the set (plus one)
handle to a socket
Definition: network.c:53
API an external event loop has to implement for GNUNET_SCHEDULER_driver_init.
void * cls
Closure to pass to the functions in this struct.
int(* add)(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Add a task to be run if the conditions specified in the et field of the given fdi are satisfied.
void(* set_wakeup)(void *cls, struct GNUNET_TIME_Absolute dt)
Set time at which we definitively want to get a wakeup call.
int(* del)(void *cls, struct GNUNET_SCHEDULER_Task *task)
Delete a task from the set of tasks to be run.
Information about an event relating to a file descriptor/socket.
int sock
Underlying OS handle the event was about.
enum GNUNET_SCHEDULER_EventType et
Type of the event that was generated related to sock.
const struct GNUNET_DISK_FileHandle * fh
GNUnet file handle the event is about, matches sock, NULL if this is about a network socket or if no ...
const struct GNUNET_NETWORK_Handle * fd
GNUnet network socket the event is about, matches sock, NULL if this is about a file handle or if no ...
Argument to be passed from the driver to GNUNET_SCHEDULER_do_work().
Definition: scheduler.c:82
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
struct GNUNET_SIGNAL_Context * shc_quit
context of the SIGQUIT handler
Definition: scheduler.c:117
struct GNUNET_SIGNAL_Context * shc_hup
context of the SIGHUP handler
Definition: scheduler.c:122
struct GNUNET_SIGNAL_Context * shc_int
context of the SIGINT handler
Definition: scheduler.c:100
struct GNUNET_SIGNAL_Context * shc_pipe
context of the SIGPIPE handler
Definition: scheduler.c:127
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
struct GNUNET_SIGNAL_Context * shc_term
context of the SIGTERM handler
Definition: scheduler.c:105
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:135
enum GNUNET_SCHEDULER_Priority priority
Task priority.
Definition: scheduler.c:203
struct GNUNET_SCHEDULER_Task * prev
This is a linked list.
Definition: scheduler.c:144
void * callback_cls
Closure for the callback.
Definition: scheduler.c:154
int in_ready_list
Is this task in the ready list?
Definition: scheduler.c:229
int lifeness
Should the existence of this task in the queue be counted as reason to not shutdown the scheduler?
Definition: scheduler.c:219
enum GNUNET_SCHEDULER_Reason reason
Why is the task ready? Set after task is added to ready queue.
Definition: scheduler.c:198
int own_handles
Do we own the network and file handles referenced by the FdInfo structs in the fds array.
Definition: scheduler.c:178
struct GNUNET_AsyncScopeSave scope
Asynchronous scope of the task that scheduled this scope,.
Definition: scheduler.c:247
struct GNUNET_SCHEDULER_Task * next
This is a linked list.
Definition: scheduler.c:139
int on_shutdown
Is this task run on shutdown?
Definition: scheduler.c:224
struct GNUNET_SCHEDULER_FdInfo * fds
Information about which FDs are ready for this task (and why).
Definition: scheduler.c:159
unsigned int fds_len
Size of the fds array.
Definition: scheduler.c:171
struct GNUNET_TIME_Absolute timeout
Absolute timeout value for the task, or GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout".
Definition: scheduler.c:184
GNUNET_SCHEDULER_TaskCallback callback
Function to run when ready.
Definition: scheduler.c:149
int write_fd
Set if we only wait for writing to a single FD, otherwise -1.
Definition: scheduler.c:213
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
int read_fd
Set if we only wait for reading from a single FD, otherwise -1.
Definition: scheduler.c:208
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:255
struct Scheduled * next
Definition: scheduler.c:258
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
struct Scheduled * prev
Definition: scheduler.c:256
struct GNUNET_SCHEDULER_FdInfo * fdi
information about the network socket / file descriptor where the event is expected to occur
Definition: scheduler.c:269
struct GNUNET_SCHEDULER_Task * task
the task, the event is related to
Definition: scheduler.c:263