GNUnet  0.19.2
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 
251 
255 struct Scheduled
256 {
257  struct Scheduled *prev;
258 
259  struct Scheduled *next;
260 
265 
271 
277 };
278 
279 
284 {
290 
296 
302 };
303 
304 
313 
318 
323 
328 
333 
342 
351 
357 
362 
366 static struct
368 
372 static struct
374 
381 
387 
391 static unsigned int ready_count;
392 
398 
404 
408 static int current_lifeness;
409 
414 
420 
424 static struct GNUNET_SCHEDULER_TaskContext tc;
425 
429 static void *scheduler_select_cls;
430 
431 
439 void
441  void *new_select_cls)
442 {
443  scheduler_select = new_select;
444  scheduler_select_cls = new_select_cls;
445 }
446 
447 
454 static enum GNUNET_SCHEDULER_Priority
456 {
457  if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
458  return p;
459  GNUNET_assert (0);
460  return 0; /* make compiler happy */
461 }
462 
463 
470 get_timeout ()
471 {
472  struct GNUNET_SCHEDULER_Task *pos;
473  struct GNUNET_TIME_Absolute now;
475 
476  pos = pending_timeout_head;
477  now = GNUNET_TIME_absolute_get ();
479  if (NULL != pos)
480  {
481  if (0 != pos->reason)
482  {
483  return now;
484  }
485  else
486  {
487  timeout = pos->timeout;
488  }
489  }
490  for (pos = pending_head; NULL != pos; pos = pos->next)
491  {
492  if (0 != pos->reason)
493  {
494  return now;
495  }
496  else if ((pos->timeout.abs_value_us !=
497  GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
498  (timeout.abs_value_us > pos->timeout.abs_value_us))
499  {
500  timeout = pos->timeout;
501  }
502  }
503  return timeout;
504 }
505 
506 
512 static void
514 {
516 
518  ready_tail[p],
519  task);
520  if (p > work_priority)
521  work_priority = p;
522  task->in_ready_list = GNUNET_YES;
523  ready_count++;
524 }
525 
526 
533 void
535 {
536  struct GNUNET_SCHEDULER_Task *pos;
537 
539  "GNUNET_SCHEDULER_shutdown\n");
540  if (NULL != install_parent_control_task)
541  {
544  }
545  if (NULL != shutdown_pipe_task)
546  {
548  shutdown_pipe_task = NULL;
549  }
550  while (NULL != (pos = shutdown_head))
551  {
554  pos);
556  queue_ready_task (pos);
557  }
558 }
559 
560 
566 static void
568 {
569 #if EXECINFO
570  for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
572  "Task %p trace %u: %s\n",
573  t,
574  i,
575  t->backtrace_strings[i]);
576 #else
577  (void) t;
578 #endif
579 }
580 
581 
587 static void
589 {
591  "destroying task %p\n",
592  t);
593 
594  if (GNUNET_YES == t->own_handles)
595  {
596  for (unsigned int i = 0; i != t->fds_len; ++i)
597  {
598  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
599  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
600  if (fd)
601  {
603  (struct GNUNET_NETWORK_Handle *) fd);
604  }
605  if (fh)
606  {
607  // FIXME: on WIN32 this is not enough! A function
608  // GNUNET_DISK_file_free_memory_only would be nice
609  GNUNET_free_nz ((void *) fh);
610  }
611  }
612  }
613  if (t->fds_len > 1)
614  {
615  GNUNET_array_grow (t->fds, t->fds_len, 0);
616  }
617 #if EXECINFO
618  GNUNET_free (t->backtrace_strings);
619 #endif
620  GNUNET_free (t);
621 }
622 
623 
628 
633 static pid_t my_pid;
634 
638 static void
640 {
641  return;
642 }
643 
644 
648 static void
650 {
651  static char c;
652  int old_errno = errno; /* backup errno */
653 
654  if (getpid () != my_pid)
655  _exit (1); /* we have fork'ed since the signal handler was created,
656  * ignore the signal, see https://gnunet.org/vfork discussion */
660  &c, sizeof(c));
661  errno = old_errno;
662 }
663 
664 
665 static void
667 {
668  struct GNUNET_SCHEDULER_Task *t;
669 
670  if (ready_count > 0)
671  return;
672  for (t = pending_head; NULL != t; t = t->next)
673  if (GNUNET_YES == t->lifeness)
674  return;
675  for (t = shutdown_head; NULL != t; t = t->next)
676  if (GNUNET_YES == t->lifeness)
677  return;
678  for (t = pending_timeout_head; NULL != t; t = t->next)
679  if (GNUNET_YES == t->lifeness)
680  return;
681  /* No lifeness! */
683 }
684 
685 
686 static int
688  struct DriverContext *context);
689 
690 
691 void
693  void *task_cls)
694 {
695  struct GNUNET_SCHEDULER_Handle *sh;
696  struct GNUNET_SCHEDULER_Driver *driver;
697  struct DriverContext context = {
698  .scheduled_head = NULL,
699  .scheduled_tail = NULL,
700  .timeout = GNUNET_TIME_absolute_get ()
701  };
702 
703  driver = GNUNET_SCHEDULER_driver_select ();
704  driver->cls = &context;
705  sh = GNUNET_SCHEDULER_driver_init (driver);
707  task_cls,
710  select_loop (sh,
711  &context);
713  GNUNET_free (driver);
714 }
715 
716 
723 const struct GNUNET_SCHEDULER_TaskContext *
725 {
726  GNUNET_assert (NULL != active_task);
727  return &tc;
728 }
729 
730 
740 unsigned int
742 {
743  unsigned int ret;
744 
745  GNUNET_assert (NULL != active_task);
747  return ready_count;
750  ret = 0;
751  for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)];
752  NULL != pos;
753  pos = pos->next)
754  ret++;
755  return ret;
756 }
757 
758 
759 void
761  const struct GNUNET_NETWORK_Handle *const *read_nh,
762  unsigned int read_nh_len,
763  const struct GNUNET_NETWORK_Handle *const *write_nh,
764  unsigned int write_nh_len,
765  const struct GNUNET_DISK_FileHandle *const *read_fh,
766  unsigned int read_fh_len,
767  const struct GNUNET_DISK_FileHandle *const *write_fh,
768  unsigned int write_fh_len)
769 {
770  // FIXME: if we have exactly two network handles / exactly two file handles
771  // and they are equal, we can make one FdInfo with both
772  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
773  struct GNUNET_SCHEDULER_FdInfo *fdi;
774 
775  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
776  if (1 == t->fds_len)
777  {
778  fdi = &t->fdx;
779  t->fds = fdi;
780  if (1 == read_nh_len)
781  {
782  GNUNET_assert (NULL != read_nh);
783  GNUNET_assert (NULL != *read_nh);
784  fdi->fd = *read_nh;
785  fdi->et = GNUNET_SCHEDULER_ET_IN;
786  fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
787  t->read_fd = fdi->sock;
788  t->write_fd = -1;
789  }
790  else if (1 == write_nh_len)
791  {
792  GNUNET_assert (NULL != write_nh);
793  GNUNET_assert (NULL != *write_nh);
794  fdi->fd = *write_nh;
796  fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
797  t->read_fd = -1;
798  t->write_fd = fdi->sock;
799  }
800  else if (1 == read_fh_len)
801  {
802  GNUNET_assert (NULL != read_fh);
803  GNUNET_assert (NULL != *read_fh);
804  fdi->fh = *read_fh;
805  fdi->et = GNUNET_SCHEDULER_ET_IN;
806  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
807  t->read_fd = fdi->sock;
808  t->write_fd = -1;
809  }
810  else
811  {
812  GNUNET_assert (NULL != write_fh);
813  GNUNET_assert (NULL != *write_fh);
814  fdi->fh = *write_fh;
816  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
817  t->read_fd = -1;
818  t->write_fd = fdi->sock;
819  }
820  }
821  else
822  {
824  t->fds = fdi;
825  t->read_fd = -1;
826  t->write_fd = -1;
827  unsigned int i;
828  for (i = 0; i != read_nh_len; ++i)
829  {
830  fdi->fd = read_nh[i];
831  GNUNET_assert (NULL != fdi->fd);
832  fdi->et = GNUNET_SCHEDULER_ET_IN;
833  fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
834  ++fdi;
835  }
836  for (i = 0; i != write_nh_len; ++i)
837  {
838  fdi->fd = write_nh[i];
839  GNUNET_assert (NULL != fdi->fd);
841  fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
842  ++fdi;
843  }
844  for (i = 0; i != read_fh_len; ++i)
845  {
846  fdi->fh = read_fh[i];
847  GNUNET_assert (NULL != fdi->fh);
848  fdi->et = GNUNET_SCHEDULER_ET_IN;
849  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
850  ++fdi;
851  }
852  for (i = 0; i != write_fh_len; ++i)
853  {
854  fdi->fh = write_fh[i];
855  GNUNET_assert (NULL != fdi->fh);
857  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
858  ++fdi;
859  }
860  }
861 }
862 
863 
877 static void
879 {
880  struct GNUNET_SCHEDULER_FdInfo *fdi;
881  int success = GNUNET_YES;
882 
883  for (unsigned int i = 0; i != t->fds_len; ++i)
884  {
885  fdi = &t->fds[i];
887  t,
888  fdi) && success;
890  }
891  if (GNUNET_YES != success)
892  {
894  "driver could not add task\n");
895  }
896 }
897 
898 
899 static void
901 {
902  (void) cls;
905 }
906 
907 
908 static void
909 shutdown_pipe_cb (void *cls)
910 {
911  char c;
912  const struct GNUNET_DISK_FileHandle *pr;
913 
914  (void) cls;
915  shutdown_pipe_task = NULL;
919  /* consume the signal */
920  GNUNET_DISK_file_read (pr, &c, sizeof(c));
921  /* mark all active tasks as ready due to shutdown */
925  pr,
927  NULL);
928 }
929 
930 
943 void *
945 {
947  int is_fd_task;
948  void *ret;
949 
951  "canceling task %p\n",
952  task);
953 
954  /* scheduler must be running */
956  is_fd_task = (NULL != task->fds);
957  if (is_fd_task)
958  {
959  int del_result = scheduler_driver->del (scheduler_driver->cls, task);
960  if (GNUNET_OK != del_result)
961  {
963  "driver could not delete task\n");
964  GNUNET_assert (0);
965  }
966  }
967  if (! task->in_ready_list)
968  {
969  if (is_fd_task)
970  {
972  pending_tail,
973  task);
974  }
975  else if (GNUNET_YES == task->on_shutdown)
976  {
979  task);
980  }
981  else
982  {
985  task);
986  if (pending_timeout_last == task)
987  pending_timeout_last = NULL;
988  }
989  }
990  else
991  {
992  p = check_priority (task->priority);
994  ready_tail[p],
995  task);
996  ready_count--;
997  }
998  ret = task->callback_cls;
999  destroy_task (task);
1000  return ret;
1001 }
1002 
1003 
1009 static void
1011 {
1012 #if EXECINFO
1013  void *backtrace_array[MAX_TRACE_DEPTH];
1014 
1015  t->num_backtrace_strings
1016  = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1017  t->backtrace_strings =
1018  backtrace_symbols (backtrace_array,
1019  t->num_backtrace_strings);
1020  dump_backtrace (t);
1021 #else
1022  (void) t;
1023 #endif
1024 }
1025 
1026 
1037 void
1039  task,
1040  void *task_cls,
1042  reason,
1044  priority)
1045 {
1046  struct GNUNET_SCHEDULER_Task *t;
1047 
1048  /* scheduler must be running */
1049  GNUNET_assert (NULL != scheduler_driver);
1050  GNUNET_assert (NULL != task);
1051  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1052  t->read_fd = -1;
1053  t->write_fd = -1;
1054  t->callback = task;
1055  t->callback_cls = task_cls;
1056 #if PROFILE_DELAYS
1057  t->start_time = GNUNET_TIME_absolute_get ();
1058 #endif
1059  t->reason = reason;
1063  "Adding continuation task %p\n",
1064  t);
1065  init_backtrace (t);
1066  queue_ready_task (t);
1067 }
1068 
1069 
1081 struct GNUNET_SCHEDULER_Task *
1085  void *task_cls)
1086 {
1087  struct GNUNET_SCHEDULER_Task *t;
1088  struct GNUNET_SCHEDULER_Task *pos;
1089  struct GNUNET_SCHEDULER_Task *prev;
1090  struct GNUNET_TIME_Relative left;
1091 
1092  /* scheduler must be running */
1093  GNUNET_assert (NULL != scheduler_driver);
1094  GNUNET_assert (NULL != task);
1095  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1097  t->callback = task;
1098  t->callback_cls = task_cls;
1099  t->read_fd = -1;
1100  t->write_fd = -1;
1101 #if PROFILE_DELAYS
1102  t->start_time = GNUNET_TIME_absolute_get ();
1103 #endif
1104  t->timeout = at;
1105  t->priority = check_priority (priority);
1107  init_backtrace (t);
1108 
1110  if (0 == left.rel_value_us)
1111  {
1112  queue_ready_task (t);
1113  if (priority > work_priority)
1114  work_priority = priority;
1115  return t;
1116  }
1117 
1118  /* try tail first (optimization in case we are
1119  * appending to a long list of tasks with timeouts) */
1120  if ((NULL == pending_timeout_head) ||
1122  {
1125  t);
1126  }
1127  else
1128  {
1129  /* first move from heuristic start backwards to before start time */
1130  prev = pending_timeout_last;
1131  while ((NULL != prev) &&
1133  prev = prev->prev;
1134  /* now, move from heuristic start (or head of list) forward to insertion point */
1135  if (NULL == prev)
1136  pos = pending_timeout_head;
1137  else
1138  pos = prev->next;
1139  while ((NULL != pos) && (pos->timeout.abs_value_us <=
1141  {
1142  prev = pos;
1143  pos = pos->next;
1144  }
1147  prev,
1148  t);
1149  }
1150  /* finally, update heuristic insertion point to last insertion... */
1153  "Adding task %p\n",
1154  t);
1155  return t;
1156 }
1157 
1158 
1170 struct GNUNET_SCHEDULER_Task *
1173  priority,
1175  void *task_cls)
1176 {
1179  priority,
1180  task,
1181  task_cls);
1182 }
1183 
1184 
1194 struct GNUNET_SCHEDULER_Task *
1197  void *task_cls)
1198 {
1200  prio,
1201  task,
1202  task_cls);
1203 }
1204 
1205 
1217 struct GNUNET_SCHEDULER_Task *
1220  void *task_cls)
1221 {
1224  task,
1225  task_cls);
1226 }
1227 
1228 
1240 struct GNUNET_SCHEDULER_Task *
1243  void *task_cls)
1244 {
1247  task,
1248  task_cls);
1249 }
1250 
1251 
1267 struct GNUNET_SCHEDULER_Task *
1269  void *task_cls)
1270 {
1271  struct GNUNET_SCHEDULER_Task *t;
1272 
1273  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1275  t->callback = task;
1276  t->callback_cls = task_cls;
1277  t->read_fd = -1;
1278  t->write_fd = -1;
1279 #if PROFILE_DELAYS
1280  t->start_time = GNUNET_TIME_absolute_get ();
1281 #endif
1286  queue_ready_task (t);
1287  init_backtrace (t);
1288  return t;
1289 }
1290 
1291 
1302 struct GNUNET_SCHEDULER_Task *
1304  void *task_cls)
1305 {
1306  struct GNUNET_SCHEDULER_Task *t;
1307 
1308  /* scheduler must be running */
1309  GNUNET_assert (NULL != scheduler_driver);
1310  GNUNET_assert (NULL != task);
1311  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1313  t->callback = task;
1314  t->callback_cls = task_cls;
1315  t->read_fd = -1;
1316  t->write_fd = -1;
1317 #if PROFILE_DELAYS
1318  t->start_time = GNUNET_TIME_absolute_get ();
1319 #endif
1323  t->lifeness = GNUNET_NO;
1325  shutdown_tail,
1326  t);
1328  "Adding shutdown task %p\n",
1329  t);
1330  init_backtrace (t);
1331  return t;
1332 }
1333 
1334 
1335 struct GNUNET_SCHEDULER_Task *
1338  void *task_cls)
1339 {
1340  struct GNUNET_SCHEDULER_Task *ret;
1341 
1342  ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1343  ret->lifeness = lifeness;
1344  return ret;
1345 }
1346 
1347 
1348 #if DEBUG_FDS
1355 void
1356 check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1357 {
1358  if (-1 != raw_fd)
1359  {
1360  int flags = fcntl (raw_fd, F_GETFD);
1361 
1362  if ((flags == -1) && (errno == EBADF))
1363  {
1365  "Got invalid file descriptor %d!\n",
1366  raw_fd);
1367  init_backtrace (t);
1368  GNUNET_assert (0);
1369  }
1370  }
1371 }
1372 
1373 
1374 #endif
1375 
1376 
1402 static struct GNUNET_SCHEDULER_Task *
1405  const struct GNUNET_NETWORK_Handle *read_nh,
1406  const struct GNUNET_NETWORK_Handle *write_nh,
1407  const struct GNUNET_DISK_FileHandle *read_fh,
1408  const struct GNUNET_DISK_FileHandle *write_fh,
1410  void *task_cls)
1411 {
1412  struct GNUNET_SCHEDULER_Task *t;
1413 
1414  /* scheduler must be running */
1415  GNUNET_assert (NULL != scheduler_driver);
1416  GNUNET_assert (NULL != task);
1417  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1419  init_fd_info (t,
1420  &read_nh,
1421  read_nh ? 1 : 0,
1422  &write_nh,
1423  write_nh ? 1 : 0,
1424  &read_fh,
1425  read_fh ? 1 : 0,
1426  &write_fh,
1427  write_fh ? 1 : 0);
1428  t->callback = task;
1429  t->callback_cls = task_cls;
1430 #if DEBUG_FDS
1431  check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1432  check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1433  check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1434  check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1435 #endif
1436 #if PROFILE_DELAYS
1437  t->start_time = GNUNET_TIME_absolute_get ();
1438 #endif
1444  pending_tail,
1445  t);
1448  t->priority);
1449  init_backtrace (t);
1450  return t;
1451 }
1452 
1453 
1474 struct GNUNET_SCHEDULER_Task *
1476  struct GNUNET_NETWORK_Handle *rfd,
1478  void *task_cls)
1479 {
1482  rfd, task, task_cls);
1483 }
1484 
1485 
1508 struct GNUNET_SCHEDULER_Task *
1511  priority,
1512  struct GNUNET_NETWORK_Handle *rfd,
1514  void *task_cls)
1515 {
1517  rfd,
1518  GNUNET_YES,
1519  GNUNET_NO,
1520  task, task_cls);
1521 }
1522 
1523 
1545 struct GNUNET_SCHEDULER_Task *
1547  struct GNUNET_NETWORK_Handle *wfd,
1549  void *task_cls)
1550 {
1553  wfd,
1555  task, task_cls);
1556 }
1557 
1558 
1582 struct GNUNET_SCHEDULER_Task *
1585  struct GNUNET_NETWORK_Handle *fd,
1586  int on_read,
1587  int on_write,
1589  void *task_cls)
1590 {
1591  /* scheduler must be running */
1592  GNUNET_assert (NULL != scheduler_driver);
1593  GNUNET_assert (on_read || on_write);
1595  return add_without_sets (delay, priority,
1596  on_read ? fd : NULL,
1597  on_write ? fd : NULL,
1598  NULL,
1599  NULL,
1600  task, task_cls);
1601 }
1602 
1603 
1624 struct GNUNET_SCHEDULER_Task *
1626  const struct GNUNET_DISK_FileHandle *rfd,
1628  void *task_cls)
1629 {
1632  rfd, GNUNET_YES, GNUNET_NO,
1633  task, task_cls);
1634 }
1635 
1636 
1657 struct GNUNET_SCHEDULER_Task *
1659  const struct GNUNET_DISK_FileHandle *wfd,
1661  void *task_cls)
1662 {
1665  wfd, GNUNET_NO, GNUNET_YES,
1666  task, task_cls);
1667 }
1668 
1669 
1693 struct GNUNET_SCHEDULER_Task *
1696  priority,
1697  const struct
1699  int on_read, int on_write,
1701  void *task_cls)
1702 {
1703  /* scheduler must be running */
1704  GNUNET_assert (NULL != scheduler_driver);
1705  GNUNET_assert (on_read || on_write);
1706  GNUNET_assert (fd->fd >= 0);
1707  return add_without_sets (delay, priority,
1708  NULL,
1709  NULL,
1710  on_read ? fd : NULL,
1711  on_write ? fd : NULL,
1712  task, task_cls);
1713 }
1714 
1715 
1716 void
1718  const struct GNUNET_NETWORK_Handle ***ntarget,
1719  unsigned int *extracted_nhandles,
1720  const struct GNUNET_DISK_FileHandle ***ftarget,
1721  unsigned int *extracted_fhandles)
1722 {
1723  // FIXME: this implementation only works for unix, for WIN32 the file handles
1724  // in fdset must be handled separately
1725  const struct GNUNET_NETWORK_Handle **nhandles;
1726  const struct GNUNET_DISK_FileHandle **fhandles;
1727  unsigned int nhandles_len;
1728  unsigned int fhandles_len;
1729 
1730  nhandles = NULL;
1731  fhandles = NULL;
1732  nhandles_len = 0;
1733  fhandles_len = 0;
1734  for (int sock = 0; sock != fdset->nsds; ++sock)
1735  {
1736  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1737  {
1738  struct GNUNET_NETWORK_Handle *nhandle;
1739  struct GNUNET_DISK_FileHandle *fhandle;
1740 
1741  nhandle = GNUNET_NETWORK_socket_box_native (sock);
1742  if (NULL != nhandle)
1743  {
1744  GNUNET_array_append (nhandles, nhandles_len, nhandle);
1745  }
1746  else
1747  {
1748  fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1749  if (NULL != fhandle)
1750  {
1751  GNUNET_array_append (fhandles, fhandles_len, fhandle);
1752  }
1753  else
1754  {
1755  GNUNET_assert (0);
1756  }
1757  }
1758  }
1759  }
1760  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1761  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1762  *extracted_nhandles = nhandles_len;
1763  *extracted_fhandles = fhandles_len;
1764 }
1765 
1766 
1798 struct GNUNET_SCHEDULER_Task *
1800  struct GNUNET_TIME_Relative delay,
1801  const struct GNUNET_NETWORK_FDSet *rs,
1802  const struct GNUNET_NETWORK_FDSet *ws,
1804  void *task_cls)
1805 {
1806  struct GNUNET_SCHEDULER_Task *t;
1807  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1808  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1809  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1810  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1811  unsigned int read_nhandles_len = 0;
1812  unsigned int write_nhandles_len = 0;
1813  unsigned int read_fhandles_len = 0;
1814  unsigned int write_fhandles_len = 0;
1815 
1816  /* scheduler must be running */
1817  GNUNET_assert (NULL != scheduler_driver);
1818  GNUNET_assert (NULL != task);
1819  int no_rs = (NULL == rs);
1820  int no_ws = (NULL == ws);
1821  int empty_rs = (NULL != rs) && (0 == rs->nsds);
1822  int empty_ws = (NULL != ws) && (0 == ws->nsds);
1823  int no_fds = (no_rs && no_ws) ||
1824  (empty_rs && empty_ws) ||
1825  (no_rs && empty_ws) ||
1826  (no_ws && empty_rs);
1827  if (! no_fds)
1828  {
1829  if (NULL != rs)
1830  {
1831  extract_handles (rs,
1832  &read_nhandles,
1833  &read_nhandles_len,
1834  &read_fhandles,
1835  &read_fhandles_len);
1836  }
1837  if (NULL != ws)
1838  {
1839  extract_handles (ws,
1840  &write_nhandles,
1841  &write_nhandles_len,
1842  &write_fhandles,
1843  &write_fhandles_len);
1844  }
1845  }int no_fds_extracted = (0 == read_nhandles_len) &&
1853  (0 == read_fhandles_len) &&
1854  (0 == write_nhandles_len) &&
1855  (0 == write_fhandles_len);
1856  if (no_fds || no_fds_extracted)
1858  prio,
1859  task,
1860  task_cls);
1861  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1863  init_fd_info (t,
1864  read_nhandles,
1865  read_nhandles_len,
1866  write_nhandles,
1867  write_nhandles_len,
1868  read_fhandles,
1869  read_fhandles_len,
1870  write_fhandles,
1871  write_fhandles_len);
1872  t->callback = task;
1873  t->callback_cls = task_cls;
1875  /* free the arrays of pointers to network / file handles, the actual
1876  * handles will be freed in destroy_task */
1877  GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1878  GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1879  GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1880  GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1881 #if PROFILE_DELAYS
1882  t->start_time = GNUNET_TIME_absolute_get ();
1883 #endif
1885  t->priority =
1886  check_priority ((prio ==
1888  prio);
1891  pending_tail,
1892  t);
1895  t->priority);
1897  "Adding task %p\n",
1898  t);
1899  init_backtrace (t);
1900  return t;
1901 }
1902 
1903 
1915 void
1917  struct GNUNET_SCHEDULER_FdInfo *fdi)
1918 {
1919  enum GNUNET_SCHEDULER_Reason reason;
1920 
1921  reason = task->reason;
1922  if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1923  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1925  if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1926  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1929  task->reason = reason;
1930  if (GNUNET_NO == task->in_ready_list)
1931  {
1933  pending_tail,
1934  task);
1935  queue_ready_task (task);
1936  }
1937 }
1938 
1939 
1960 int
1962 {
1963  struct GNUNET_SCHEDULER_Task *pos;
1964  struct GNUNET_TIME_Absolute now;
1965 
1966  /* check for tasks that reached the timeout! */
1967  now = GNUNET_TIME_absolute_get ();
1968  pos = pending_timeout_head;
1969  while (NULL != pos)
1970  {
1971  struct GNUNET_SCHEDULER_Task *next = pos->next;
1972  if (now.abs_value_us >= pos->timeout.abs_value_us)
1974  if (0 == pos->reason)
1975  break;
1978  pos);
1979  if (pending_timeout_last == pos)
1980  pending_timeout_last = NULL;
1981  queue_ready_task (pos);
1982  pos = next;
1983  }
1984  pos = pending_head;
1985  while (NULL != pos)
1986  {
1987  struct GNUNET_SCHEDULER_Task *next = pos->next;
1988  if (now.abs_value_us >= pos->timeout.abs_value_us)
1989  {
1992  pending_tail,
1993  pos);
1994  queue_ready_task (pos);
1995  }
1996  pos = next;
1997  }
1998 
1999  if (0 == ready_count)
2000  {
2002 
2003  if (timeout.abs_value_us > now.abs_value_us)
2004  {
2019  "GNUNET_SCHEDULER_do_work did not find any ready "
2020  "tasks and timeout has not been reached yet.\n");
2021  }
2022  else
2023  {
2028  GNUNET_assert (0);
2029  }
2030  }
2031  else
2032  {
2033  struct GNUNET_SCHEDULER_Task *last;
2034 
2035  /* find out which task priority level we are going to
2036  process this time */
2039  /* yes, p>0 is correct, 0 is "KEEP" which should
2040  * always be an empty queue (see assertion)! */
2042  work_priority > 0;
2043  work_priority--)
2044  {
2045  pos = ready_head[work_priority];
2046  if (NULL != pos)
2047  break;
2048  }
2049  GNUNET_assert (NULL != pos); /* ready_count wrong? */
2050 
2051  /* process all *existing* tasks at this priority
2052  level, then yield */
2053  last = ready_tail[work_priority];
2054  while (NULL != (pos = ready_head[work_priority]))
2055  {
2058  pos);
2059  ready_count--;
2060  current_priority = pos->priority;
2061  current_lifeness = pos->lifeness;
2062  active_task = pos;
2063 #if PROFILE_DELAYS
2064  if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2065  DELAY_THRESHOLD.rel_value_us)
2066  {
2068  "Task %p took %s to be scheduled\n",
2069  pos,
2071  GNUNET_TIME_absolute_get_duration (pos->start_time),
2072  GNUNET_YES));
2073  }
2074 #endif
2075  tc.reason = pos->reason;
2078  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2079  tc.fds_len = pos->fds_len;
2080  tc.fds = pos->fds;
2081  for (unsigned int i = 0; i != pos->fds_len; ++i)
2082  {
2083  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2084  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2085  {
2087  fdi->sock);
2088  }
2089  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2090  {
2092  fdi->sock);
2093  }
2094  }
2095  tc.read_ready = sh->rs;
2096  tc.write_ready = sh->ws;
2098  "Running task %p\n",
2099  pos);
2100  GNUNET_assert (NULL != pos->callback);
2101  {
2102  struct GNUNET_AsyncScopeSave old_scope;
2103  if (pos->scope.have_scope)
2104  GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2105  else
2106  GNUNET_async_scope_get (&old_scope);
2107  pos->callback (pos->callback_cls);
2108  GNUNET_async_scope_restore (&old_scope);
2109  }
2110  if (NULL != pos->fds)
2111  {
2112  int del_result = scheduler_driver->del (scheduler_driver->cls,
2113  pos);
2114  if (GNUNET_OK != del_result)
2115  {
2117  "driver could not delete task %p\n", pos);
2118  GNUNET_assert (0);
2119  }
2120  }
2121  active_task = NULL;
2122  dump_backtrace (pos);
2123  destroy_task (pos);
2124  /* pointer 'pos' was free'd, but we can still safely check for
2125  pointer equality still. */
2126  if (pos == last)
2127  break; /* All tasks that _were_ ready when we started were
2128  executed. New tasks may have been added in the
2129  meantime, but we should check with the OS to
2130  be sure no higher-priority actions are pending! */
2131  }
2132  }
2134  if (0 == ready_count)
2135  {
2137  get_timeout ());
2138  return GNUNET_NO;
2139  }
2142  return GNUNET_YES;
2143 }
2144 
2145 
2177 struct GNUNET_SCHEDULER_Handle *
2179 {
2180  struct GNUNET_SCHEDULER_Handle *sh;
2181  const struct GNUNET_DISK_FileHandle *pr;
2182 
2183  /* scheduler must not be running */
2184  GNUNET_assert (NULL == scheduler_driver);
2186  /* general set-up */
2192  my_pid = getpid ();
2193  scheduler_driver = driver;
2194 
2195  /* install signal handlers */
2197  "Registering signal handlers\n");
2198  sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2200  sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2202 #if (SIGTERM != GNUNET_TERM_SIG)
2205 #endif
2206  sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2207  &sighandler_pipe);
2208  sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2210  sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2212 
2213  /* Setup initial tasks */
2216  /* ensure this task runs first, by using a priority level reserved for
2217  the scheduler (not really shutdown, but start-up ;-) */
2221  NULL);
2224  pr,
2226  NULL);
2229  get_timeout ());
2230  /* begin main event loop */
2234  return sh;
2235 }
2236 
2237 
2252 void
2254 {
2255  GNUNET_assert (NULL == pending_head);
2257  GNUNET_assert (NULL == shutdown_head);
2258  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2259  {
2260  GNUNET_assert (NULL == ready_head[i]);
2261  }
2264 
2265  /* uninstall signal handlers */
2267  GNUNET_SIGNAL_handler_uninstall (sh->shc_term);
2268 #if (SIGTERM != GNUNET_TERM_SIG)
2269  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
2270 #endif
2271  GNUNET_SIGNAL_handler_uninstall (sh->shc_pipe);
2272  GNUNET_SIGNAL_handler_uninstall (sh->shc_quit);
2275  shutdown_pipe_handle = NULL;
2276  scheduler_driver = NULL;
2277  GNUNET_free (sh);
2278 }
2279 
2280 
2281 static int
2283  struct DriverContext *context)
2284 {
2285  struct GNUNET_NETWORK_FDSet *rs;
2286  struct GNUNET_NETWORK_FDSet *ws;
2287  int select_result;
2288 
2289  GNUNET_assert (NULL != context);
2292  while ((NULL != context->scheduled_head) ||
2293  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2294  context->timeout.abs_value_us))
2295  {
2296  struct GNUNET_TIME_Relative time_remaining;
2297 
2299  "select timeout = %s\n",
2301 
2304 
2305  for (struct Scheduled *pos = context->scheduled_head;
2306  NULL != pos;
2307  pos = pos->next)
2308  {
2309  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2310  {
2311  GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2312  }
2313  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2314  {
2315  GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2316  }
2317  }
2318  time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2319  if (0 < ready_count)
2320  time_remaining = GNUNET_TIME_UNIT_ZERO;
2321  if (NULL == scheduler_select)
2322  {
2323  select_result = GNUNET_NETWORK_socket_select (rs,
2324  ws,
2325  NULL,
2326  time_remaining);
2327  }
2328  else
2329  {
2330  select_result = scheduler_select (scheduler_select_cls,
2331  rs,
2332  ws,
2333  NULL,
2334  time_remaining);
2335  }
2336  if (select_result == GNUNET_SYSERR)
2337  {
2338  if (errno == EINTR)
2339  continue;
2340 
2342  "select");
2343 #if USE_LSOF
2344  char lsof[512];
2345 
2346  snprintf (lsof,
2347  sizeof(lsof),
2348  "lsof -p %d",
2349  getpid ());
2350  (void) close (1);
2351  (void) dup2 (2, 1);
2352  if (0 != system (lsof))
2354  "system");
2355 #endif
2356 #if DEBUG_FDS
2357  for (struct Scheduled *s = context->scheduled_head;
2358  NULL != s;
2359  s = s->next)
2360  {
2361  int flags = fcntl (s->fdi->sock,
2362  F_GETFD);
2363 
2364  if ((flags == -1) &&
2365  (EBADF == errno))
2366  {
2368  "Got invalid file descriptor %d!\n",
2369  s->fdi->sock);
2370 #if EXECINFO
2371  dump_backtrace (s->task);
2372 #endif
2373  }
2374  }
2375 #endif
2376  GNUNET_assert (0);
2379  return GNUNET_SYSERR;
2380  }
2381  if (select_result > 0)
2382  {
2383  for (struct Scheduled *pos = context->scheduled_head;
2384  NULL != pos;
2385  pos = pos->next)
2386  {
2387  int is_ready = GNUNET_NO;
2388 
2389  if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2390  (GNUNET_YES ==
2392  pos->fdi->sock)) )
2393  {
2394  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2395  is_ready = GNUNET_YES;
2396  }
2397  if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2398  (GNUNET_YES ==
2400  pos->fdi->sock)) )
2401  {
2402  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2403  is_ready = GNUNET_YES;
2404  }
2405  if (GNUNET_YES == is_ready)
2406  {
2407  GNUNET_SCHEDULER_task_ready (pos->task,
2408  pos->fdi);
2409  }
2410  }
2411  }
2413  {
2415  "scheduler has more tasks ready!\n");
2416  }
2417  }
2420  return GNUNET_OK;
2421 }
2422 
2423 
2424 static int
2425 select_add (void *cls,
2426  struct GNUNET_SCHEDULER_Task *task,
2427  struct GNUNET_SCHEDULER_FdInfo *fdi)
2428 {
2429  struct DriverContext *context = cls;
2430 
2431  GNUNET_assert (NULL != context);
2432  GNUNET_assert (NULL != task);
2433  GNUNET_assert (NULL != fdi);
2434  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2435  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2436 
2437  if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2438  {
2439  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2440  return GNUNET_SYSERR;
2441  }
2442 
2443  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2444  scheduled->task = task;
2445  scheduled->fdi = fdi;
2446  scheduled->et = fdi->et;
2447 
2448  GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2449  context->scheduled_tail,
2450  scheduled);
2451  return GNUNET_OK;
2452 }
2453 
2454 
2455 static int
2456 select_del (void *cls,
2457  struct GNUNET_SCHEDULER_Task *task)
2458 {
2459  struct DriverContext *context;
2460  struct Scheduled *pos;
2461  int ret;
2462 
2463  GNUNET_assert (NULL != cls);
2464 
2465  context = cls;
2466  ret = GNUNET_SYSERR;
2467  pos = context->scheduled_head;
2468  while (NULL != pos)
2469  {
2470  struct Scheduled *next = pos->next;
2471  if (pos->task == task)
2472  {
2473  GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2474  context->scheduled_tail,
2475  pos);
2476  GNUNET_free (pos);
2477  ret = GNUNET_OK;
2478  }
2479  pos = next;
2480  }
2481  return ret;
2482 }
2483 
2484 
2485 static void
2487  struct GNUNET_TIME_Absolute dt)
2488 {
2489  struct DriverContext *context = cls;
2490 
2491  GNUNET_assert (NULL != context);
2492  context->timeout = dt;
2493 }
2494 
2495 
2501 struct GNUNET_SCHEDULER_Driver *
2503 {
2504  struct GNUNET_SCHEDULER_Driver *select_driver;
2505 
2506  select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2507 
2508  select_driver->add = &select_add;
2509  select_driver->del = &select_del;
2510  select_driver->set_wakeup = &select_set_wakeup;
2511 
2512  return select_driver;
2513 }
2514 
2515 
2528 void
2530 {
2531  struct GNUNET_AsyncScopeSave dummy_old_scope;
2532 
2533  GNUNET_assert (NULL != active_task);
2534  /* Since we're in a task, the context will be automatically
2535  restored by the scheduler. */
2536  GNUNET_async_scope_enter (aid, &dummy_old_scope);
2537 }
2538 
2539 
2540 /* 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:685
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1584
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:621
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:1615
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1327
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1441
@ 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:534
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:1509
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:692
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:1268
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition: scheduler.c:2253
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:2178
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:1546
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:1916
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:1038
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:1799
struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select()
Obtain the driver for using select() as the event loop.
Definition: scheduler.c:2502
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:1961
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:1475
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:1625
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:1082
unsigned int GNUNET_SCHEDULER_get_load(enum GNUNET_SCHEDULER_Priority p)
Get information about the current load of this scheduler.
Definition: scheduler.c:741
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:1658
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:1171
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:1336
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:2529
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:1195
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:1694
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:440
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:1303
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:724
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:1218
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:944
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:1241
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:1583
@ 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:233
static void sighandler_pipe()
Signal handler called for SIGPIPE.
Definition: scheduler.c:639
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:567
static void driver_add_multiple(struct GNUNET_SCHEDULER_Task *t)
calls the given function func on each FdInfo related to t.
Definition: scheduler.c:878
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:386
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition: scheduler.c:2486
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition: scheduler.c:588
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:455
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:513
static int select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition: scheduler.c:2282
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition: scheduler.c:2456
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:380
static struct GNUNET_SCHEDULER_Task * active_task
ID of the task that is running right now.
Definition: scheduler.c:361
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:372
static enum GNUNET_SCHEDULER_Priority current_priority
Priority of the task running right now.
Definition: scheduler.c:397
static struct GNUNET_SCHEDULER_Task * pending_head
Head of list of tasks waiting for an event.
Definition: scheduler.c:317
#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:760
static unsigned int ready_count
Number of tasks on the ready list.
Definition: scheduler.c:391
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:1403
static struct GNUNET_DISK_PipeHandle * shutdown_pipe_handle
Pipe used to communicate shutdown via signal.
Definition: scheduler.c:627
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:470
static const struct GNUNET_SCHEDULER_Driver * scheduler_driver
The driver used for the event loop.
Definition: scheduler.c:312
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:1717
static struct GNUNET_SCHEDULER_Task * pending_timeout_head
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:341
static void install_parent_control_handler(void *cls)
Definition: scheduler.c:900
static int select_add(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Definition: scheduler.c:2425
static GNUNET_SCHEDULER_select scheduler_select
Function to use as a select() in the scheduler.
Definition: scheduler.c:419
static enum GNUNET_SCHEDULER_Priority work_priority
Priority used currently in GNUNET_SCHEDULER_do_work().
Definition: scheduler.c:413
static void shutdown_if_no_lifeness(void)
Definition: scheduler.c:666
static void * scheduler_select_cls
Closure for scheduler_select.
Definition: scheduler.c:429
static struct GNUNET_SCHEDULER_Task * pending_timeout_tail
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:350
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:366
static int current_lifeness
Value of the 'lifeness' flag for the current task.
Definition: scheduler.c:408
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition: scheduler.c:1010
static enum GNUNET_SCHEDULER_Priority max_priority_added
Priority of the highest task added in the current select iteration.
Definition: scheduler.c:403
static struct GNUNET_SCHEDULER_Task * pending_timeout_last
Last inserted task waiting ONLY for a timeout event.
Definition: scheduler.c:356
static void sighandler_shutdown(void)
Signal handler called for signals that should cause us to shutdown.
Definition: scheduler.c:649
#define LOG(kind,...)
Definition: scheduler.c:32
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:909
#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:322
static struct GNUNET_SCHEDULER_Task * shutdown_tail
Tail of list of tasks waiting for shutdown.
Definition: scheduler.c:332
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:424
static struct GNUNET_SCHEDULER_Task * shutdown_head
Head of list of tasks waiting for shutdown.
Definition: scheduler.c:327
static pid_t my_pid
Process ID of this process at the time we installed the various signal handlers.
Definition: scheduler.c:633
Driver context used by GNUNET_SCHEDULER_run.
Definition: scheduler.c:284
struct Scheduled * scheduled_head
the head of a DLL containing information about the events the select driver is waiting for
Definition: scheduler.c:289
struct GNUNET_TIME_Absolute timeout
the time when the select driver will wake up again (after calling select)
Definition: scheduler.c:301
struct Scheduled * scheduled_tail
the tail of a DLL containing information about the events the select driver is waiting for
Definition: scheduler.c:295
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:256
struct Scheduled * next
Definition: scheduler.c:259
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:276
struct Scheduled * prev
Definition: scheduler.c:257
struct GNUNET_SCHEDULER_FdInfo * fdi
information about the network socket / file descriptor where the event is expected to occur
Definition: scheduler.c:270
struct GNUNET_SCHEDULER_Task * task
the task, the event is related to
Definition: scheduler.c:264