GNUnet  0.11.x
scheduler.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2009-2017 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "disk.h"
28 // DEBUG
29 #include <inttypes.h>
30 
31 #define LOG(kind, ...) GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__)
32 
33 #define LOG_STRERROR(kind, syscall) GNUNET_log_from_strerror (kind, \
34  "util-scheduler", \
35  syscall)
36 
37 
38 #if HAVE_EXECINFO_H
39 #include "execinfo.h"
40 
45 #define USE_LSOF GNUNET_NO
46 
50 #define EXECINFO GNUNET_NO
51 
55 #define DEBUG_FDS GNUNET_NO
56 
60 #define MAX_TRACE_DEPTH 50
61 #endif
62 
67 #define PROFILE_DELAYS GNUNET_NO
68 
73 #define DELAY_THRESHOLD GNUNET_TIME_UNIT_SECONDS
74 
75 
82 {
89 
96 
101 
106 
107 #if (SIGTERM != GNUNET_TERM_SIG)
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  task->in_ready_list = GNUNET_YES;
520  ready_count++;
521 }
522 
523 
530 void
532 {
533  struct GNUNET_SCHEDULER_Task *pos;
534 
536  "GNUNET_SCHEDULER_shutdown\n");
537  if (NULL != install_parent_control_task)
538  {
541  }
542  if (NULL != shutdown_pipe_task)
543  {
545  shutdown_pipe_task = NULL;
546  }
547  while (NULL != (pos = shutdown_head))
548  {
551  pos);
553  queue_ready_task (pos);
554  }
555 }
556 
557 
563 static void
565 {
566 #if EXECINFO
567  for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
569  "Task %p trace %u: %s\n",
570  t,
571  i,
572  t->backtrace_strings[i]);
573 #else
574  (void) t;
575 #endif
576 }
577 
578 
584 static void
586 {
588  "destroying task %p\n",
589  t);
590 
591  if (GNUNET_YES == t->own_handles)
592  {
593  for (unsigned int i = 0; i != t->fds_len; ++i)
594  {
595  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
596  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
597  if (fd)
598  {
600  (struct GNUNET_NETWORK_Handle *) fd);
601  }
602  if (fh)
603  {
604  // FIXME: on WIN32 this is not enough! A function
605  // GNUNET_DISK_file_free_memory_only would be nice
606  GNUNET_free_nz ((void *) fh);
607  }
608  }
609  }
610  if (t->fds_len > 1)
611  {
612  GNUNET_array_grow (t->fds, t->fds_len, 0);
613  }
614 #if EXECINFO
615  GNUNET_free (t->backtrace_strings);
616 #endif
617  GNUNET_free (t);
618 }
619 
620 
625 
630 static pid_t my_pid;
631 
635 static void
637 {
638  return;
639 }
640 
641 
643 // * Wait for a short time.
644 // * Sleeps for @a ms ms (as that should be long enough for virtually all
645 // * modern systems to context switch and allow another process to do
646 // * some 'real' work).
647 // *
648 // * @param ms how many ms to wait
649 // */
650 // static void
651 // short_wait (unsigned int ms)
652 // {
653 // struct GNUNET_TIME_Relative timeout;
654 //
655 // timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms);
656 // (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
657 // }
658 
659 
663 static void
665 {
666  static char c;
667  int old_errno = errno; /* backup errno */
668 
669  if (getpid () != my_pid)
670  _exit (1); /* we have fork'ed since the signal handler was created,
671  * ignore the signal, see https://gnunet.org/vfork discussion */
674  &c, sizeof(c));
675  errno = old_errno;
676 }
677 
678 
679 static void
681 {
682  struct GNUNET_SCHEDULER_Task *t;
683 
684  if (ready_count > 0)
685  return;
686  for (t = pending_head; NULL != t; t = t->next)
687  if (GNUNET_YES == t->lifeness)
688  return;
689  for (t = shutdown_head; NULL != t; t = t->next)
690  if (GNUNET_YES == t->lifeness)
691  return;
692  for (t = pending_timeout_head; NULL != t; t = t->next)
693  if (GNUNET_YES == t->lifeness)
694  return;
695  /* No lifeness! */
697 }
698 
699 
700 static int
702  struct DriverContext *context);
703 
704 
719 void
721  void *task_cls)
722 {
723  struct GNUNET_SCHEDULER_Handle *sh;
724  struct GNUNET_SCHEDULER_Driver *driver;
725  struct DriverContext context = {
726  .scheduled_head = NULL,
727  .scheduled_tail = NULL,
728  .timeout = GNUNET_TIME_absolute_get ()
729  };
730 
731  driver = GNUNET_SCHEDULER_driver_select ();
732  driver->cls = &context;
733  sh = GNUNET_SCHEDULER_driver_init (driver);
735  task_cls,
738  select_loop (sh,
739  &context);
741  GNUNET_free (driver);
742 }
743 
744 
751 const struct GNUNET_SCHEDULER_TaskContext *
753 {
754  GNUNET_assert (NULL != active_task);
755  return &tc;
756 }
757 
758 
768 unsigned int
770 {
771  unsigned int ret;
772 
773  GNUNET_assert (NULL != active_task);
775  return ready_count;
778  ret = 0;
779  for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)];
780  NULL != pos;
781  pos = pos->next)
782  ret++;
783  return ret;
784 }
785 
786 
787 void
789  const struct GNUNET_NETWORK_Handle *const *read_nh,
790  unsigned int read_nh_len,
791  const struct GNUNET_NETWORK_Handle *const *write_nh,
792  unsigned int write_nh_len,
793  const struct GNUNET_DISK_FileHandle *const *read_fh,
794  unsigned int read_fh_len,
795  const struct GNUNET_DISK_FileHandle *const *write_fh,
796  unsigned int write_fh_len)
797 {
798  // FIXME: if we have exactly two network handles / exactly two file handles
799  // and they are equal, we can make one FdInfo with both
800  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
801  struct GNUNET_SCHEDULER_FdInfo *fdi;
802 
803  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
804  if (1 == t->fds_len)
805  {
806  fdi = &t->fdx;
807  t->fds = fdi;
808  if (1 == read_nh_len)
809  {
810  GNUNET_assert (NULL != read_nh);
811  GNUNET_assert (NULL != *read_nh);
812  fdi->fd = *read_nh;
813  fdi->et = GNUNET_SCHEDULER_ET_IN;
814  fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
815  t->read_fd = fdi->sock;
816  t->write_fd = -1;
817  }
818  else if (1 == write_nh_len)
819  {
820  GNUNET_assert (NULL != write_nh);
821  GNUNET_assert (NULL != *write_nh);
822  fdi->fd = *write_nh;
824  fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
825  t->read_fd = -1;
826  t->write_fd = fdi->sock;
827  }
828  else if (1 == read_fh_len)
829  {
830  GNUNET_assert (NULL != read_fh);
831  GNUNET_assert (NULL != *read_fh);
832  fdi->fh = *read_fh;
833  fdi->et = GNUNET_SCHEDULER_ET_IN;
834  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
835  t->read_fd = fdi->sock;
836  t->write_fd = -1;
837  }
838  else
839  {
840  GNUNET_assert (NULL != write_fh);
841  GNUNET_assert (NULL != *write_fh);
842  fdi->fh = *write_fh;
844  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
845  t->read_fd = -1;
846  t->write_fd = fdi->sock;
847  }
848  }
849  else
850  {
852  t->fds = fdi;
853  t->read_fd = -1;
854  t->write_fd = -1;
855  unsigned int i;
856  for (i = 0; i != read_nh_len; ++i)
857  {
858  fdi->fd = read_nh[i];
859  GNUNET_assert (NULL != fdi->fd);
860  fdi->et = GNUNET_SCHEDULER_ET_IN;
861  fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
862  ++fdi;
863  }
864  for (i = 0; i != write_nh_len; ++i)
865  {
866  fdi->fd = write_nh[i];
867  GNUNET_assert (NULL != fdi->fd);
869  fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
870  ++fdi;
871  }
872  for (i = 0; i != read_fh_len; ++i)
873  {
874  fdi->fh = read_fh[i];
875  GNUNET_assert (NULL != fdi->fh);
876  fdi->et = GNUNET_SCHEDULER_ET_IN;
877  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
878  ++fdi;
879  }
880  for (i = 0; i != write_fh_len; ++i)
881  {
882  fdi->fh = write_fh[i];
883  GNUNET_assert (NULL != fdi->fh);
885  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
886  ++fdi;
887  }
888  }
889 }
890 
891 
905 static void
907 {
908  struct GNUNET_SCHEDULER_FdInfo *fdi;
909  int success = GNUNET_YES;
910 
911  for (unsigned int i = 0; i != t->fds_len; ++i)
912  {
913  fdi = &t->fds[i];
915  t,
916  fdi) && success;
918  }
919  if (GNUNET_YES != success)
920  {
922  "driver could not add task\n");
923  }
924 }
925 
926 
927 static void
929 {
930  (void) cls;
933 }
934 
935 
936 static void
937 shutdown_pipe_cb (void *cls)
938 {
939  char c;
940  const struct GNUNET_DISK_FileHandle *pr;
941 
942  (void) cls;
943  shutdown_pipe_task = NULL;
947  /* consume the signal */
948  GNUNET_DISK_file_read (pr, &c, sizeof(c));
949  /* mark all active tasks as ready due to shutdown */
953  pr,
955  NULL);
956 }
957 
958 
971 void *
973 {
975  int is_fd_task;
976  void *ret;
977 
979  "canceling task %p\n",
980  task);
981 
982  /* scheduler must be running */
984  is_fd_task = (NULL != task->fds);
985  if (is_fd_task)
986  {
987  int del_result = scheduler_driver->del (scheduler_driver->cls, task);
988  if (GNUNET_OK != del_result)
989  {
991  "driver could not delete task\n");
992  GNUNET_assert (0);
993  }
994  }
995  if (! task->in_ready_list)
996  {
997  if (is_fd_task)
998  {
1000  pending_tail,
1001  task);
1002  }
1003  else if (GNUNET_YES == task->on_shutdown)
1004  {
1006  shutdown_tail,
1007  task);
1008  }
1009  else
1010  {
1013  task);
1014  if (pending_timeout_last == task)
1015  pending_timeout_last = NULL;
1016  }
1017  }
1018  else
1019  {
1020  p = check_priority (task->priority);
1022  ready_tail[p],
1023  task);
1024  ready_count--;
1025  }
1026  ret = task->callback_cls;
1027  destroy_task (task);
1028  return ret;
1029 }
1030 
1031 
1037 static void
1039 {
1040 #if EXECINFO
1041  void *backtrace_array[MAX_TRACE_DEPTH];
1042 
1043  t->num_backtrace_strings
1044  = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1045  t->backtrace_strings =
1046  backtrace_symbols (backtrace_array,
1047  t->num_backtrace_strings);
1048  dump_backtrace (t);
1049 #else
1050  (void) t;
1051 #endif
1052 }
1053 
1054 
1065 void
1067  task,
1068  void *task_cls,
1070  reason,
1072  priority)
1073 {
1074  struct GNUNET_SCHEDULER_Task *t;
1075 
1076  /* scheduler must be running */
1077  GNUNET_assert (NULL != scheduler_driver);
1078  GNUNET_assert (NULL != task);
1079  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1080  t->read_fd = -1;
1081  t->write_fd = -1;
1082  t->callback = task;
1083  t->callback_cls = task_cls;
1084 #if PROFILE_DELAYS
1085  t->start_time = GNUNET_TIME_absolute_get ();
1086 #endif
1087  t->reason = reason;
1091  "Adding continuation task %p\n",
1092  t);
1093  init_backtrace (t);
1094  queue_ready_task (t);
1095 }
1096 
1097 
1109 struct GNUNET_SCHEDULER_Task *
1113  void *task_cls)
1114 {
1115  struct GNUNET_SCHEDULER_Task *t;
1116  struct GNUNET_SCHEDULER_Task *pos;
1117  struct GNUNET_SCHEDULER_Task *prev;
1118  struct GNUNET_TIME_Relative left;
1119 
1120  /* scheduler must be running */
1121  GNUNET_assert (NULL != scheduler_driver);
1122  GNUNET_assert (NULL != task);
1123  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1125  t->callback = task;
1126  t->callback_cls = task_cls;
1127  t->read_fd = -1;
1128  t->write_fd = -1;
1129 #if PROFILE_DELAYS
1130  t->start_time = GNUNET_TIME_absolute_get ();
1131 #endif
1132  t->timeout = at;
1133  t->priority = check_priority (priority);
1135  init_backtrace (t);
1136 
1138  if (0 == left.rel_value_us)
1139  {
1140  queue_ready_task (t);
1141  if (priority > work_priority)
1142  work_priority = priority;
1143  return t;
1144  }
1145 
1146  /* try tail first (optimization in case we are
1147  * appending to a long list of tasks with timeouts) */
1148  if ((NULL == pending_timeout_head) ||
1150  {
1153  t);
1154  }
1155  else
1156  {
1157  /* first move from heuristic start backwards to before start time */
1158  prev = pending_timeout_last;
1159  while ((NULL != prev) &&
1161  prev = prev->prev;
1162  /* now, move from heuristic start (or head of list) forward to insertion point */
1163  if (NULL == prev)
1164  pos = pending_timeout_head;
1165  else
1166  pos = prev->next;
1167  while ((NULL != pos) && (pos->timeout.abs_value_us <=
1169  {
1170  prev = pos;
1171  pos = pos->next;
1172  }
1175  prev,
1176  t);
1177  }
1178  /* finally, update heuristic insertion point to last insertion... */
1181  "Adding task %p\n",
1182  t);
1183  return t;
1184 }
1185 
1186 
1198 struct GNUNET_SCHEDULER_Task *
1201  priority,
1203  void *task_cls)
1204 {
1207  priority,
1208  task,
1209  task_cls);
1210 }
1211 
1212 
1222 struct GNUNET_SCHEDULER_Task *
1225  void *task_cls)
1226 {
1228  prio,
1229  task,
1230  task_cls);
1231 }
1232 
1233 
1245 struct GNUNET_SCHEDULER_Task *
1248  void *task_cls)
1249 {
1252  task,
1253  task_cls);
1254 }
1255 
1256 
1268 struct GNUNET_SCHEDULER_Task *
1271  void *task_cls)
1272 {
1275  task,
1276  task_cls);
1277 }
1278 
1279 
1295 struct GNUNET_SCHEDULER_Task *
1297  void *task_cls)
1298 {
1299  struct GNUNET_SCHEDULER_Task *t;
1300 
1301  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1303  t->callback = task;
1304  t->callback_cls = task_cls;
1305  t->read_fd = -1;
1306  t->write_fd = -1;
1307 #if PROFILE_DELAYS
1308  t->start_time = GNUNET_TIME_absolute_get ();
1309 #endif
1314  queue_ready_task (t);
1315  init_backtrace (t);
1316  return t;
1317 }
1318 
1319 
1330 struct GNUNET_SCHEDULER_Task *
1332  void *task_cls)
1333 {
1334  struct GNUNET_SCHEDULER_Task *t;
1335 
1336  /* scheduler must be running */
1337  GNUNET_assert (NULL != scheduler_driver);
1338  GNUNET_assert (NULL != task);
1339  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1341  t->callback = task;
1342  t->callback_cls = task_cls;
1343  t->read_fd = -1;
1344  t->write_fd = -1;
1345 #if PROFILE_DELAYS
1346  t->start_time = GNUNET_TIME_absolute_get ();
1347 #endif
1351  t->lifeness = GNUNET_NO;
1353  shutdown_tail,
1354  t);
1356  "Adding shutdown task %p\n",
1357  t);
1358  init_backtrace (t);
1359  return t;
1360 }
1361 
1362 
1377 struct GNUNET_SCHEDULER_Task *
1380  void *task_cls)
1381 {
1382  struct GNUNET_SCHEDULER_Task *ret;
1383 
1384  ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1385  ret->lifeness = lifeness;
1386  return ret;
1387 }
1388 
1389 
1390 #if DEBUG_FDS
1397 void
1398 check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1399 {
1400  if (-1 != raw_fd)
1401  {
1402  int flags = fcntl (raw_fd, F_GETFD);
1403 
1404  if ((flags == -1) && (errno == EBADF))
1405  {
1407  "Got invalid file descriptor %d!\n",
1408  raw_fd);
1409  init_backtrace (t);
1410  GNUNET_assert (0);
1411  }
1412  }
1413 }
1414 
1415 
1416 #endif
1417 
1418 
1444 static struct GNUNET_SCHEDULER_Task *
1447  const struct GNUNET_NETWORK_Handle *read_nh,
1448  const struct GNUNET_NETWORK_Handle *write_nh,
1449  const struct GNUNET_DISK_FileHandle *read_fh,
1450  const struct GNUNET_DISK_FileHandle *write_fh,
1452  void *task_cls)
1453 {
1454  struct GNUNET_SCHEDULER_Task *t;
1455 
1456  /* scheduler must be running */
1457  GNUNET_assert (NULL != scheduler_driver);
1458  GNUNET_assert (NULL != task);
1459  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1461  init_fd_info (t,
1462  &read_nh,
1463  read_nh ? 1 : 0,
1464  &write_nh,
1465  write_nh ? 1 : 0,
1466  &read_fh,
1467  read_fh ? 1 : 0,
1468  &write_fh,
1469  write_fh ? 1 : 0);
1470  t->callback = task;
1471  t->callback_cls = task_cls;
1472 #if DEBUG_FDS
1473  check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1474  check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1475  check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1476  check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1477 #endif
1478 #if PROFILE_DELAYS
1479  t->start_time = GNUNET_TIME_absolute_get ();
1480 #endif
1486  pending_tail,
1487  t);
1490  t->priority);
1491  init_backtrace (t);
1492  return t;
1493 }
1494 
1495 
1516 struct GNUNET_SCHEDULER_Task *
1518  struct GNUNET_NETWORK_Handle *rfd,
1520  void *task_cls)
1521 {
1524  rfd, task, task_cls);
1525 }
1526 
1527 
1550 struct GNUNET_SCHEDULER_Task *
1553  priority,
1554  struct GNUNET_NETWORK_Handle *rfd,
1556  void *task_cls)
1557 {
1559  rfd,
1560  GNUNET_YES,
1561  GNUNET_NO,
1562  task, task_cls);
1563 }
1564 
1565 
1587 struct GNUNET_SCHEDULER_Task *
1589  struct GNUNET_NETWORK_Handle *wfd,
1591  void *task_cls)
1592 {
1595  wfd,
1597  task, task_cls);
1598 }
1599 
1600 
1624 struct GNUNET_SCHEDULER_Task *
1627  struct GNUNET_NETWORK_Handle *fd,
1628  int on_read,
1629  int on_write,
1631  void *task_cls)
1632 {
1633  /* scheduler must be running */
1634  GNUNET_assert (NULL != scheduler_driver);
1635  GNUNET_assert (on_read || on_write);
1637  return add_without_sets (delay, priority,
1638  on_read ? fd : NULL,
1639  on_write ? fd : NULL,
1640  NULL,
1641  NULL,
1642  task, task_cls);
1643 }
1644 
1645 
1666 struct GNUNET_SCHEDULER_Task *
1668  const struct GNUNET_DISK_FileHandle *rfd,
1670  void *task_cls)
1671 {
1674  rfd, GNUNET_YES, GNUNET_NO,
1675  task, task_cls);
1676 }
1677 
1678 
1699 struct GNUNET_SCHEDULER_Task *
1701  const struct GNUNET_DISK_FileHandle *wfd,
1703  void *task_cls)
1704 {
1707  wfd, GNUNET_NO, GNUNET_YES,
1708  task, task_cls);
1709 }
1710 
1711 
1735 struct GNUNET_SCHEDULER_Task *
1738  priority,
1739  const struct
1741  int on_read, int on_write,
1743  void *task_cls)
1744 {
1745  /* scheduler must be running */
1746  GNUNET_assert (NULL != scheduler_driver);
1747  GNUNET_assert (on_read || on_write);
1748  GNUNET_assert (fd->fd >= 0);
1749  return add_without_sets (delay, priority,
1750  NULL,
1751  NULL,
1752  on_read ? fd : NULL,
1753  on_write ? fd : NULL,
1754  task, task_cls);
1755 }
1756 
1757 
1758 void
1760  const struct GNUNET_NETWORK_Handle ***ntarget,
1761  unsigned int *extracted_nhandles,
1762  const struct GNUNET_DISK_FileHandle ***ftarget,
1763  unsigned int *extracted_fhandles)
1764 {
1765  // FIXME: this implementation only works for unix, for WIN32 the file handles
1766  // in fdset must be handled separately
1767  const struct GNUNET_NETWORK_Handle **nhandles;
1768  const struct GNUNET_DISK_FileHandle **fhandles;
1769  unsigned int nhandles_len;
1770  unsigned int fhandles_len;
1771 
1772  nhandles = NULL;
1773  fhandles = NULL;
1774  nhandles_len = 0;
1775  fhandles_len = 0;
1776  for (int sock = 0; sock != fdset->nsds; ++sock)
1777  {
1778  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1779  {
1780  struct GNUNET_NETWORK_Handle *nhandle;
1781  struct GNUNET_DISK_FileHandle *fhandle;
1782 
1783  nhandle = GNUNET_NETWORK_socket_box_native (sock);
1784  if (NULL != nhandle)
1785  {
1786  GNUNET_array_append (nhandles, nhandles_len, nhandle);
1787  }
1788  else
1789  {
1790  fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1791  if (NULL != fhandle)
1792  {
1793  GNUNET_array_append (fhandles, fhandles_len, fhandle);
1794  }
1795  else
1796  {
1797  GNUNET_assert (0);
1798  }
1799  }
1800  }
1801  }
1802  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1803  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1804  *extracted_nhandles = nhandles_len;
1805  *extracted_fhandles = fhandles_len;
1806 }
1807 
1808 
1840 struct GNUNET_SCHEDULER_Task *
1842  struct GNUNET_TIME_Relative delay,
1843  const struct GNUNET_NETWORK_FDSet *rs,
1844  const struct GNUNET_NETWORK_FDSet *ws,
1846  void *task_cls)
1847 {
1848  struct GNUNET_SCHEDULER_Task *t;
1849  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1850  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1851  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1852  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1853  unsigned int read_nhandles_len = 0;
1854  unsigned int write_nhandles_len = 0;
1855  unsigned int read_fhandles_len = 0;
1856  unsigned int write_fhandles_len = 0;
1857 
1858  /* scheduler must be running */
1859  GNUNET_assert (NULL != scheduler_driver);
1860  GNUNET_assert (NULL != task);
1861  int no_rs = (NULL == rs);
1862  int no_ws = (NULL == ws);
1863  int empty_rs = (NULL != rs) && (0 == rs->nsds);
1864  int empty_ws = (NULL != ws) && (0 == ws->nsds);
1865  int no_fds = (no_rs && no_ws) ||
1866  (empty_rs && empty_ws) ||
1867  (no_rs && empty_ws) ||
1868  (no_ws && empty_rs);
1869  if (! no_fds)
1870  {
1871  if (NULL != rs)
1872  {
1873  extract_handles (rs,
1874  &read_nhandles,
1875  &read_nhandles_len,
1876  &read_fhandles,
1877  &read_fhandles_len);
1878  }
1879  if (NULL != ws)
1880  {
1881  extract_handles (ws,
1882  &write_nhandles,
1883  &write_nhandles_len,
1884  &write_fhandles,
1885  &write_fhandles_len);
1886  }
1887  }int no_fds_extracted = (0 == read_nhandles_len) &&
1895  (0 == read_fhandles_len) &&
1896  (0 == write_nhandles_len) &&
1897  (0 == write_fhandles_len);
1898  if (no_fds || no_fds_extracted)
1900  prio,
1901  task,
1902  task_cls);
1903  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1905  init_fd_info (t,
1906  read_nhandles,
1907  read_nhandles_len,
1908  write_nhandles,
1909  write_nhandles_len,
1910  read_fhandles,
1911  read_fhandles_len,
1912  write_fhandles,
1913  write_fhandles_len);
1914  t->callback = task;
1915  t->callback_cls = task_cls;
1917  /* free the arrays of pointers to network / file handles, the actual
1918  * handles will be freed in destroy_task */
1919  GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1920  GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1921  GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1922  GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1923 #if PROFILE_DELAYS
1924  t->start_time = GNUNET_TIME_absolute_get ();
1925 #endif
1927  t->priority =
1928  check_priority ((prio ==
1930  prio);
1933  pending_tail,
1934  t);
1937  t->priority);
1939  "Adding task %p\n",
1940  t);
1941  init_backtrace (t);
1942  return t;
1943 }
1944 
1945 
1957 void
1959  struct GNUNET_SCHEDULER_FdInfo *fdi)
1960 {
1961  enum GNUNET_SCHEDULER_Reason reason;
1962 
1963  reason = task->reason;
1964  if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1965  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1967  if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1968  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1971  task->reason = reason;
1972  if (GNUNET_NO == task->in_ready_list)
1973  {
1975  pending_tail,
1976  task);
1977  queue_ready_task (task);
1978  }
1979 }
1980 
1981 
2002 int
2004 {
2005  struct GNUNET_SCHEDULER_Task *pos;
2006  struct GNUNET_TIME_Absolute now;
2007 
2008  /* check for tasks that reached the timeout! */
2009  now = GNUNET_TIME_absolute_get ();
2010  pos = pending_timeout_head;
2011  while (NULL != pos)
2012  {
2013  struct GNUNET_SCHEDULER_Task *next = pos->next;
2014  if (now.abs_value_us >= pos->timeout.abs_value_us)
2016  if (0 == pos->reason)
2017  break;
2020  pos);
2021  if (pending_timeout_last == pos)
2022  pending_timeout_last = NULL;
2023  queue_ready_task (pos);
2024  pos = next;
2025  }
2026  pos = pending_head;
2027  while (NULL != pos)
2028  {
2029  struct GNUNET_SCHEDULER_Task *next = pos->next;
2030  if (now.abs_value_us >= pos->timeout.abs_value_us)
2031  {
2034  pending_tail,
2035  pos);
2036  queue_ready_task (pos);
2037  }
2038  pos = next;
2039  }
2040 
2041  if (0 == ready_count)
2042  {
2044 
2045  if (timeout.abs_value_us > now.abs_value_us)
2060  "GNUNET_SCHEDULER_do_work did not find any ready "
2061  "tasks and timeout has not been reached yet.\n");
2062  }
2063  else
2064  {
2069  GNUNET_assert (0);
2070  }
2071  }
2072  else
2073  {
2074  /* find out which task priority level we are going to
2075  process this time */
2078  /* yes, p>0 is correct, 0 is "KEEP" which should
2079  * always be an empty queue (see assertion)! */
2081  work_priority > 0;
2082  work_priority--)
2083  {
2084  pos = ready_head[work_priority];
2085  if (NULL != pos)
2086  break;
2087  }
2088  GNUNET_assert (NULL != pos); /* ready_count wrong? */
2089 
2090  /* process all tasks at this priority level, then yield */
2091  while (NULL != (pos = ready_head[work_priority]))
2092  {
2095  pos);
2096  ready_count--;
2097  current_priority = pos->priority;
2098  current_lifeness = pos->lifeness;
2099  active_task = pos;
2100 #if PROFILE_DELAYS
2101  if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2102  DELAY_THRESHOLD.rel_value_us)
2103  {
2105  "Task %p took %s to be scheduled\n",
2106  pos,
2108  GNUNET_TIME_absolute_get_duration (pos->start_time),
2109  GNUNET_YES));
2110  }
2111 #endif
2112  tc.reason = pos->reason;
2115  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2116  tc.fds_len = pos->fds_len;
2117  tc.fds = pos->fds;
2118  for (unsigned int i = 0; i != pos->fds_len; ++i)
2119  {
2120  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2121  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2122  {
2124  fdi->sock);
2125  }
2126  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2127  {
2129  fdi->sock);
2130  }
2131  }
2132  tc.read_ready = sh->rs;
2133  tc.write_ready = sh->ws;
2135  "Running task %p\n",
2136  pos);
2137  GNUNET_assert (NULL != pos->callback);
2138  {
2139  struct GNUNET_AsyncScopeSave old_scope;
2140  if (pos->scope.have_scope)
2141  GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2142  else
2143  GNUNET_async_scope_get (&old_scope);
2144  pos->callback (pos->callback_cls);
2145  GNUNET_async_scope_restore (&old_scope);
2146  }
2147  if (NULL != pos->fds)
2148  {
2149  int del_result = scheduler_driver->del (scheduler_driver->cls, pos);
2150  if (GNUNET_OK != del_result)
2151  {
2153  "driver could not delete task %p\n", pos);
2154  GNUNET_assert (0);
2155  }
2156  }
2157  active_task = NULL;
2158  dump_backtrace (pos);
2159  destroy_task (pos);
2160  }
2161  }
2163  if (0 == ready_count)
2164  {
2166  get_timeout ());
2167  return GNUNET_NO;
2168  }
2171  return GNUNET_YES;
2172 }
2173 
2174 
2206 struct GNUNET_SCHEDULER_Handle *
2208 {
2209  struct GNUNET_SCHEDULER_Handle *sh;
2210  const struct GNUNET_DISK_FileHandle *pr;
2211 
2212  /* scheduler must not be running */
2213  GNUNET_assert (NULL == scheduler_driver);
2215  /* general set-up */
2221  my_pid = getpid ();
2222  scheduler_driver = driver;
2223 
2224  /* install signal handlers */
2226  "Registering signal handlers\n");
2227  sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2229  sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2231 #if (SIGTERM != GNUNET_TERM_SIG)
2234 #endif
2235  sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2236  &sighandler_pipe);
2237  sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2239  sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2241 
2242  /* Setup initial tasks */
2245  /* ensure this task runs first, by using a priority level reserved for
2246  the scheduler (not really shutdown, but start-up ;-) */
2250  NULL);
2253  pr,
2255  NULL);
2258  get_timeout ());
2259  /* begin main event loop */
2263  return sh;
2264 }
2265 
2266 
2281 void
2283 {
2284  GNUNET_assert (NULL == pending_head);
2286  GNUNET_assert (NULL == shutdown_head);
2287  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2288  {
2289  GNUNET_assert (NULL == ready_head[i]);
2290  }
2293 
2294  /* uninstall signal handlers */
2296  GNUNET_SIGNAL_handler_uninstall (sh->shc_term);
2297 #if (SIGTERM != GNUNET_TERM_SIG)
2298  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
2299 #endif
2300  GNUNET_SIGNAL_handler_uninstall (sh->shc_pipe);
2301  GNUNET_SIGNAL_handler_uninstall (sh->shc_quit);
2304  shutdown_pipe_handle = NULL;
2305  scheduler_driver = NULL;
2306  GNUNET_free (sh);
2307 }
2308 
2309 
2310 static int
2312  struct DriverContext *context)
2313 {
2314  struct GNUNET_NETWORK_FDSet *rs;
2315  struct GNUNET_NETWORK_FDSet *ws;
2316  int select_result;
2317 
2318  GNUNET_assert (NULL != context);
2321  while ((NULL != context->scheduled_head) ||
2322  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2323  context->timeout.abs_value_us))
2324  {
2325  struct GNUNET_TIME_Relative time_remaining;
2326 
2328  "select timeout = %s\n",
2330 
2333 
2334  for (struct Scheduled *pos = context->scheduled_head;
2335  NULL != pos;
2336  pos = pos->next)
2337  {
2338  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2339  {
2340  GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2341  }
2342  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2343  {
2344  GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2345  }
2346  }
2347  time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2348  if (0 < ready_count)
2349  time_remaining = GNUNET_TIME_UNIT_ZERO;
2350  if (NULL == scheduler_select)
2351  {
2352  select_result = GNUNET_NETWORK_socket_select (rs,
2353  ws,
2354  NULL,
2355  time_remaining);
2356  }
2357  else
2358  {
2359  select_result = scheduler_select (scheduler_select_cls,
2360  rs,
2361  ws,
2362  NULL,
2363  time_remaining);
2364  }
2365  if (select_result == GNUNET_SYSERR)
2366  {
2367  if (errno == EINTR)
2368  continue;
2369 
2371  "select");
2372 #if USE_LSOF
2373  char lsof[512];
2374 
2375  snprintf (lsof,
2376  sizeof(lsof),
2377  "lsof -p %d",
2378  getpid ());
2379  (void) close (1);
2380  (void) dup2 (2, 1);
2381  if (0 != system (lsof))
2383  "system");
2384 #endif
2385 #if DEBUG_FDS
2386  for (struct Scheduled *s = context->scheduled_head;
2387  NULL != s;
2388  s = s->next)
2389  {
2390  int flags = fcntl (s->fdi->sock,
2391  F_GETFD);
2392 
2393  if ((flags == -1) &&
2394  (EBADF == errno))
2395  {
2397  "Got invalid file descriptor %d!\n",
2398  s->fdi->sock);
2399 #if EXECINFO
2400  dump_backtrace (s->task);
2401 #endif
2402  }
2403  }
2404 #endif
2405  GNUNET_assert (0);
2408  return GNUNET_SYSERR;
2409  }
2410  if (select_result > 0)
2411  {
2412  for (struct Scheduled *pos = context->scheduled_head;
2413  NULL != pos;
2414  pos = pos->next)
2415  {
2416  int is_ready = GNUNET_NO;
2417 
2418  if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2419  (GNUNET_YES ==
2421  pos->fdi->sock)) )
2422  {
2423  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2424  is_ready = GNUNET_YES;
2425  }
2426  if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2427  (GNUNET_YES ==
2429  pos->fdi->sock)) )
2430  {
2431  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2432  is_ready = GNUNET_YES;
2433  }
2434  if (GNUNET_YES == is_ready)
2435  {
2436  GNUNET_SCHEDULER_task_ready (pos->task,
2437  pos->fdi);
2438  }
2439  }
2440  }
2442  {
2444  "scheduler has more tasks ready!\n");
2445  }
2446  }
2449  return GNUNET_OK;
2450 }
2451 
2452 
2453 static int
2454 select_add (void *cls,
2455  struct GNUNET_SCHEDULER_Task *task,
2456  struct GNUNET_SCHEDULER_FdInfo *fdi)
2457 {
2458  struct DriverContext *context = cls;
2459 
2460  GNUNET_assert (NULL != context);
2461  GNUNET_assert (NULL != task);
2462  GNUNET_assert (NULL != fdi);
2463  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2464  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2465 
2466  if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2467  {
2468  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2469  return GNUNET_SYSERR;
2470  }
2471 
2472  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2473  scheduled->task = task;
2474  scheduled->fdi = fdi;
2475  scheduled->et = fdi->et;
2476 
2477  GNUNET_CONTAINER_DLL_insert (context->scheduled_head,
2478  context->scheduled_tail,
2479  scheduled);
2480  return GNUNET_OK;
2481 }
2482 
2483 
2484 static int
2485 select_del (void *cls,
2486  struct GNUNET_SCHEDULER_Task *task)
2487 {
2488  struct DriverContext *context;
2489  struct Scheduled *pos;
2490  int ret;
2491 
2492  GNUNET_assert (NULL != cls);
2493 
2494  context = cls;
2495  ret = GNUNET_SYSERR;
2496  pos = context->scheduled_head;
2497  while (NULL != pos)
2498  {
2499  struct Scheduled *next = pos->next;
2500  if (pos->task == task)
2501  {
2502  GNUNET_CONTAINER_DLL_remove (context->scheduled_head,
2503  context->scheduled_tail,
2504  pos);
2505  GNUNET_free (pos);
2506  ret = GNUNET_OK;
2507  }
2508  pos = next;
2509  }
2510  return ret;
2511 }
2512 
2513 
2514 static void
2516  struct GNUNET_TIME_Absolute dt)
2517 {
2518  struct DriverContext *context = cls;
2519 
2520  GNUNET_assert (NULL != context);
2521  context->timeout = dt;
2522 }
2523 
2524 
2530 struct GNUNET_SCHEDULER_Driver *
2532 {
2533  struct GNUNET_SCHEDULER_Driver *select_driver;
2534 
2535  select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2536 
2537  select_driver->add = &select_add;
2538  select_driver->del = &select_del;
2539  select_driver->set_wakeup = &select_set_wakeup;
2540 
2541  return select_driver;
2542 }
2543 
2544 
2557 void
2559 {
2560  struct GNUNET_AsyncScopeSave dummy_old_scope;
2561 
2562  GNUNET_assert (NULL != active_task);
2563  /* Since we're in a task, the context will be automatically
2564  restored by the scheduler. */
2565  GNUNET_async_scope_enter (aid, &dummy_old_scope);
2566 }
2567 
2568 
2569 /* end of scheduler.c */
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_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
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_SCHEDULER_Task * t
Main task.
#define GNUNET_MAX(a, b)
GNUNET_SCHEDULER_Priority
Valid task priorities.
@ 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...
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_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
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_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:1245
void GNUNET_NETWORK_fdset_zero(struct GNUNET_NETWORK_FDSet *fds)
Reset FD set (clears all file descriptors).
Definition: network.c:992
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1261
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1075
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition: network.c:1132
int GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to, int nfd)
Test native fd in a set.
Definition: network.c:1150
void GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
Only free memory of a socket, keep the file descriptor untouched.
Definition: network.c:622
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:1335
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:1166
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native(int fd)
Box a native socket (and check that it is a socket).
Definition: network.c:636
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:531
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority and to be run after the specified delay or wh...
Definition: scheduler.c:1551
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:720
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1296
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition: scheduler.c:2282
struct GNUNET_SCHEDULER_Handle * GNUNET_SCHEDULER_driver_init(const struct GNUNET_SCHEDULER_Driver *driver)
Function called by external event loop implementations to initialize the scheduler.
Definition: scheduler.c:2207
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1588
void GNUNET_SCHEDULER_task_ready(struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Function used by event-loop implementations to signal the scheduler that a particular task is ready d...
Definition: scheduler.c:1958
void GNUNET_SCHEDULER_add_with_reason_and_priority(GNUNET_SCHEDULER_TaskCallback task, void *task_cls, enum GNUNET_SCHEDULER_Reason reason, enum GNUNET_SCHEDULER_Priority priority)
Continue the current execution with the given function.
Definition: scheduler.c:1066
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1841
struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select()
Obtain the driver for using select() as the event loop.
Definition: scheduler.c:2531
int GNUNET_SCHEDULER_do_work(struct GNUNET_SCHEDULER_Handle *sh)
Function called by external event loop implementations to tell the scheduler to run some of the tasks...
Definition: scheduler.c:2003
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1517
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1667
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at_with_priority(struct GNUNET_TIME_Absolute at, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition: scheduler.c:1110
unsigned int GNUNET_SCHEDULER_get_load(enum GNUNET_SCHEDULER_Priority p)
Get information about the current load of this scheduler.
Definition: scheduler.c:769
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1700
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1199
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now_with_lifeness(int lifeness, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible with the (transitive) ignore-shutdown flag either e...
Definition: scheduler.c:1378
void GNUNET_SCHEDULER_begin_async_scope(struct GNUNET_AsyncScopeId *aid)
Change the async scope for the currently executing task and (transitively) for all tasks scheduled by...
Definition: scheduler.c:2558
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1223
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_file_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_DISK_FileHandle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready.
Definition: scheduler.c:1736
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:1331
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context()
Obtain the task context, giving the reason why the current task was started.
Definition: scheduler.c:752
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at(struct GNUNET_TIME_Absolute at, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition: scheduler.c:1246
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
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:1625
@ 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:263
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:232
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:604
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:181
#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:557
#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:636
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:564
static void driver_add_multiple(struct GNUNET_SCHEDULER_Task *t)
calls the given function func on each FdInfo related to t.
Definition: scheduler.c:906
static struct GNUNET_SCHEDULER_Task * 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:2515
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition: scheduler.c:585
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:2311
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition: scheduler.c:2485
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:788
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:1445
static struct GNUNET_DISK_PipeHandle * shutdown_pipe_handle
Pipe used to communicate shutdown via signal.
Definition: scheduler.c:624
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:1759
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:928
static int select_add(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Definition: scheduler.c:2454
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 * 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:1038
static void shutdown_if_no_lifeness()
Definition: scheduler.c:680
static void sighandler_shutdown()
‍**
Definition: scheduler.c:664
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
#define LOG(kind,...)
Definition: scheduler.c:31
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:937
#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:630
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