GNUnet  0.11.x
scheduler.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2009-2017 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "disk.h"
28 // DEBUG
29 #include <inttypes.h>
30 
31 #define LOG(kind, ...) GNUNET_log_from (kind, "util-scheduler", __VA_ARGS__)
32 
33 #define LOG_STRERROR(kind, syscall) GNUNET_log_from_strerror (kind, \
34  "util-scheduler", \
35  syscall)
36 
37 
38 #if HAVE_EXECINFO_H
39 #include "execinfo.h"
40 
45 #define USE_LSOF GNUNET_NO
46 
50 #define EXECINFO GNUNET_NO
51 
55 #define DEBUG_FDS GNUNET_NO
56 
60 #define MAX_TRACE_DEPTH 50
61 #endif
62 
67 #define PROFILE_DELAYS GNUNET_NO
68 
73 #define DELAY_THRESHOLD GNUNET_TIME_UNIT_SECONDS
74 
75 
82 {
89 
96 
101 
106 
107 #if (SIGTERM != GNUNET_TERM_SIG)
108 
111  struct GNUNET_SIGNAL_Context *shc_gterm;
112 #endif
113 
118 
123 
128 };
129 
130 
135 {
140 
145 
150 
155 
160 
167 
171  unsigned int fds_len;
172 
179 
185 
186 #if PROFILE_DELAYS
187 
191 #endif
192 
199 
204 
208  int read_fd;
209 
213  int write_fd;
214 
219  int lifeness;
220 
225 
230 
231 #if EXECINFO
232 
236  char **backtrace_strings;
237 
241  int num_backtrace_strings;
242 #endif
243 
248 };
249 
250 
254 struct Scheduled
255 {
256  struct Scheduled *prev;
257 
258  struct Scheduled *next;
259 
264 
270 
276 };
277 
278 
283 {
289 
295 
301 };
302 
303 
312 
317 
322 
327 
332 
341 
350 
356 
361 
365 static struct
367 
371 static struct
373 
380 
386 
390 static unsigned int ready_count;
391 
397 
403 
407 static int current_lifeness;
408 
414 
419 
423 static void *scheduler_select_cls;
424 
425 
433 void
435  void *new_select_cls)
436 {
437  scheduler_select = new_select;
438  scheduler_select_cls = new_select_cls;
439 }
440 
441 
448 static enum GNUNET_SCHEDULER_Priority
450 {
451  if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
452  return p;
453  GNUNET_assert (0);
454  return 0; /* make compiler happy */
455 }
456 
457 
465 {
466  struct GNUNET_SCHEDULER_Task *pos;
467  struct GNUNET_TIME_Absolute now;
468  struct GNUNET_TIME_Absolute timeout;
469 
470  pos = pending_timeout_head;
471  now = GNUNET_TIME_absolute_get ();
473  if (NULL != pos)
474  {
475  if (0 != pos->reason)
476  {
477  return now;
478  }
479  else
480  {
481  timeout = pos->timeout;
482  }
483  }
484  for (pos = pending_head; NULL != pos; pos = pos->next)
485  {
486  if (0 != pos->reason)
487  {
488  return now;
489  }
490  else if ((pos->timeout.abs_value_us !=
491  GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
492  (timeout.abs_value_us > pos->timeout.abs_value_us))
493  {
494  timeout = pos->timeout;
495  }
496  }
497  return timeout;
498 }
499 
500 
506 static void
508 {
510 
511  GNUNET_CONTAINER_DLL_insert (ready_head[p],
512  ready_tail[p],
513  task);
514  task->in_ready_list = GNUNET_YES;
515  ready_count++;
516 }
517 
518 
525 void
527 {
528  struct GNUNET_SCHEDULER_Task *pos;
529 
531  "GNUNET_SCHEDULER_shutdown\n");
532  if (NULL != install_parent_control_task)
533  {
534  GNUNET_SCHEDULER_cancel (install_parent_control_task);
535  install_parent_control_task = NULL;
536  }
537  if (NULL != shutdown_pipe_task)
538  {
539  GNUNET_SCHEDULER_cancel (shutdown_pipe_task);
540  shutdown_pipe_task = NULL;
541  }
542  while (NULL != (pos = shutdown_head))
543  {
544  GNUNET_CONTAINER_DLL_remove (shutdown_head,
545  shutdown_tail,
546  pos);
548  queue_ready_task (pos);
549  }
550 }
551 
552 
558 static void
560 {
561 #if EXECINFO
562  for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
564  "Task %p trace %u: %s\n",
565  t,
566  i,
567  t->backtrace_strings[i]);
568 #else
569  (void) t;
570 #endif
571 }
572 
573 
579 static void
581 {
582  unsigned int i;
583 
585  "destroying task %p\n",
586  t);
587 
588  if (GNUNET_YES == t->own_handles)
589  {
590  for (i = 0; i != t->fds_len; ++i)
591  {
592  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
593  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
594  if (fd)
595  {
597  GNUNET_NETWORK_Handle *) fd);
598  }
599  if (fh)
600  {
601  // FIXME: on WIN32 this is not enough! A function
602  // GNUNET_DISK_file_free_memory_only would be nice
603  GNUNET_free ((void *) fh);
604  }
605  }
606  }
607  if (t->fds_len > 1)
608  {
609  GNUNET_array_grow (t->fds, t->fds_len, 0);
610  }
611 #if EXECINFO
612  GNUNET_free (t->backtrace_strings);
613 #endif
614  GNUNET_free (t);
615 }
616 
617 
622 
627 static pid_t my_pid;
628 
632 static void
634 {
635  return;
636 }
637 
638 
640 // * Wait for a short time.
641 // * Sleeps for @a ms ms (as that should be long enough for virtually all
642 // * modern systems to context switch and allow another process to do
643 // * some 'real' work).
644 // *
645 // * @param ms how many ms to wait
646 // */
647 // static void
648 // short_wait (unsigned int ms)
649 // {
650 // struct GNUNET_TIME_Relative timeout;
651 //
652 // timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms);
653 // (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
654 // }
655 
656 
660 static void
662 {
663  static char c;
664  int old_errno = errno; /* backup errno */
665 
666  if (getpid () != my_pid)
667  _exit (1); /* we have fork'ed since the signal handler was created,
668  * ignore the signal, see https://gnunet.org/vfork discussion */
670  (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE),
671  &c, sizeof(c));
672  errno = old_errno;
673 }
674 
675 
676 static void
678 {
679  struct GNUNET_SCHEDULER_Task *t;
680 
681  if (ready_count > 0)
682  return;
683  for (t = pending_head; NULL != t; t = t->next)
684  if (GNUNET_YES == t->lifeness)
685  return;
686  for (t = shutdown_head; NULL != t; t = t->next)
687  if (GNUNET_YES == t->lifeness)
688  return;
689  for (t = pending_timeout_head; NULL != t; t = t->next)
690  if (GNUNET_YES == t->lifeness)
691  return;
692  /* No lifeness! */
694 }
695 
696 
697 static int
699  struct DriverContext *context);
700 
701 
716 void
718  void *task_cls)
719 {
720  struct GNUNET_SCHEDULER_Handle *sh;
721  struct GNUNET_SCHEDULER_Driver *driver;
722  struct DriverContext context = { .scheduled_head = NULL,
723  .scheduled_tail = NULL,
724  .timeout = GNUNET_TIME_absolute_get () };
725 
726  driver = GNUNET_SCHEDULER_driver_select ();
727  driver->cls = &context;
728  sh = GNUNET_SCHEDULER_driver_init (driver);
730  task_cls,
733  select_loop (sh,
734  &context);
736  GNUNET_free (driver);
737 }
738 
739 
746 const struct GNUNET_SCHEDULER_TaskContext *
748 {
749  GNUNET_assert (NULL != active_task);
750  return &tc;
751 }
752 
753 
763 unsigned int
765 {
766  struct GNUNET_SCHEDULER_Task *pos;
767  unsigned int ret;
768 
769  GNUNET_assert (NULL != active_task);
771  return ready_count;
773  p = current_priority;
774  ret = 0;
775  for (pos = ready_head[check_priority (p)]; NULL != pos; pos = pos->next)
776  ret++;
777  return ret;
778 }
779 
780 
781 void
783  const struct GNUNET_NETWORK_Handle *const *read_nh,
784  unsigned int read_nh_len,
785  const struct GNUNET_NETWORK_Handle *const *write_nh,
786  unsigned int write_nh_len,
787  const struct GNUNET_DISK_FileHandle *const *read_fh,
788  unsigned int read_fh_len,
789  const struct GNUNET_DISK_FileHandle *const *write_fh,
790  unsigned int write_fh_len)
791 {
792  // FIXME: if we have exactly two network handles / exactly two file handles
793  // and they are equal, we can make one FdInfo with both
794  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
795  struct GNUNET_SCHEDULER_FdInfo *fdi;
796 
797  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
798  if (1 == t->fds_len)
799  {
800  fdi = &t->fdx;
801  t->fds = fdi;
802  if (1 == read_nh_len)
803  {
804  GNUNET_assert (NULL != read_nh);
805  GNUNET_assert (NULL != *read_nh);
806  fdi->fd = *read_nh;
807  fdi->et = GNUNET_SCHEDULER_ET_IN;
808  fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
809  t->read_fd = fdi->sock;
810  t->write_fd = -1;
811  }
812  else if (1 == write_nh_len)
813  {
814  GNUNET_assert (NULL != write_nh);
815  GNUNET_assert (NULL != *write_nh);
816  fdi->fd = *write_nh;
818  fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
819  t->read_fd = -1;
820  t->write_fd = fdi->sock;
821  }
822  else if (1 == read_fh_len)
823  {
824  GNUNET_assert (NULL != read_fh);
825  GNUNET_assert (NULL != *read_fh);
826  fdi->fh = *read_fh;
827  fdi->et = GNUNET_SCHEDULER_ET_IN;
828  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
829  t->read_fd = fdi->sock;
830  t->write_fd = -1;
831  }
832  else
833  {
834  GNUNET_assert (NULL != write_fh);
835  GNUNET_assert (NULL != *write_fh);
836  fdi->fh = *write_fh;
838  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
839  t->read_fd = -1;
840  t->write_fd = fdi->sock;
841  }
842  }
843  else
844  {
846  t->fds = fdi;
847  t->read_fd = -1;
848  t->write_fd = -1;
849  unsigned int i;
850  for (i = 0; i != read_nh_len; ++i)
851  {
852  fdi->fd = read_nh[i];
853  GNUNET_assert (NULL != fdi->fd);
854  fdi->et = GNUNET_SCHEDULER_ET_IN;
855  fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
856  ++fdi;
857  }
858  for (i = 0; i != write_nh_len; ++i)
859  {
860  fdi->fd = write_nh[i];
861  GNUNET_assert (NULL != fdi->fd);
863  fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
864  ++fdi;
865  }
866  for (i = 0; i != read_fh_len; ++i)
867  {
868  fdi->fh = read_fh[i];
869  GNUNET_assert (NULL != fdi->fh);
870  fdi->et = GNUNET_SCHEDULER_ET_IN;
871  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
872  ++fdi;
873  }
874  for (i = 0; i != write_fh_len; ++i)
875  {
876  fdi->fh = write_fh[i];
877  GNUNET_assert (NULL != fdi->fh);
879  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
880  ++fdi;
881  }
882  }
883 }
884 
885 
899 static void
901 {
902  struct GNUNET_SCHEDULER_FdInfo *fdi;
903  int success = GNUNET_YES;
904 
905  for (unsigned int i = 0; i != t->fds_len; ++i)
906  {
907  fdi = &t->fds[i];
908  success = scheduler_driver->add (scheduler_driver->cls,
909  t,
910  fdi) && success;
912  }
913  if (GNUNET_YES != success)
914  {
916  "driver could not add task\n");
917  }
918 }
919 
920 
921 static void
923 {
924  (void) cls;
925  install_parent_control_task = NULL;
927 }
928 
929 
930 static void
931 shutdown_pipe_cb (void *cls)
932 {
933  char c;
934  const struct GNUNET_DISK_FileHandle *pr;
935 
936  (void) cls;
937  shutdown_pipe_task = NULL;
938  pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
941  /* consume the signal */
942  GNUNET_DISK_file_read (pr, &c, sizeof(c));
943  /* mark all active tasks as ready due to shutdown */
945  shutdown_pipe_task =
947  pr,
949  NULL);
950 }
951 
952 
965 void *
967 {
969  int is_fd_task;
970  void *ret;
971 
973  "canceling task %p\n",
974  task);
975 
976  /* scheduler must be running */
977  GNUNET_assert (NULL != scheduler_driver);
978  is_fd_task = (NULL != task->fds);
979  if (is_fd_task)
980  {
981  int del_result = scheduler_driver->del (scheduler_driver->cls, task);
982  if (GNUNET_OK != del_result)
983  {
985  "driver could not delete task\n");
986  GNUNET_assert (0);
987  }
988  }
989  if (! task->in_ready_list)
990  {
991  if (is_fd_task)
992  {
993  GNUNET_CONTAINER_DLL_remove (pending_head,
994  pending_tail,
995  task);
996  }
997  else if (GNUNET_YES == task->on_shutdown)
998  {
999  GNUNET_CONTAINER_DLL_remove (shutdown_head,
1000  shutdown_tail,
1001  task);
1002  }
1003  else
1004  {
1005  GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
1006  pending_timeout_tail,
1007  task);
1008  if (pending_timeout_last == task)
1009  pending_timeout_last = NULL;
1010  }
1011  }
1012  else
1013  {
1014  p = check_priority (task->priority);
1015  GNUNET_CONTAINER_DLL_remove (ready_head[p],
1016  ready_tail[p],
1017  task);
1018  ready_count--;
1019  }
1020  ret = task->callback_cls;
1021  destroy_task (task);
1022  return ret;
1023 }
1024 
1025 
1031 static void
1033 {
1034 #if EXECINFO
1035  void *backtrace_array[MAX_TRACE_DEPTH];
1036 
1037  t->num_backtrace_strings
1038  = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1039  t->backtrace_strings =
1040  backtrace_symbols (backtrace_array,
1041  t->num_backtrace_strings);
1042  dump_backtrace (t);
1043 #else
1044  (void) t;
1045 #endif
1046 }
1047 
1048 
1059 void
1061  task,
1062  void *task_cls,
1064  reason,
1066  priority)
1067 {
1068  struct GNUNET_SCHEDULER_Task *t;
1069 
1070  /* scheduler must be running */
1071  GNUNET_assert (NULL != scheduler_driver);
1072  GNUNET_assert (NULL != task);
1073  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1074  t->read_fd = -1;
1075  t->write_fd = -1;
1076  t->callback = task;
1077  t->callback_cls = task_cls;
1078 #if PROFILE_DELAYS
1079  t->start_time = GNUNET_TIME_absolute_get ();
1080 #endif
1081  t->reason = reason;
1082  t->priority = check_priority (priority);
1085  "Adding continuation task %p\n",
1086  t);
1087  init_backtrace (t);
1088  queue_ready_task (t);
1089 }
1090 
1091 
1103 struct GNUNET_SCHEDULER_Task *
1107  void *task_cls)
1108 {
1109  struct GNUNET_SCHEDULER_Task *t;
1110  struct GNUNET_SCHEDULER_Task *pos;
1111  struct GNUNET_SCHEDULER_Task *prev;
1112 
1113  /* scheduler must be running */
1114  GNUNET_assert (NULL != scheduler_driver);
1115  GNUNET_assert (NULL != task);
1116  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1118  t->callback = task;
1119  t->callback_cls = task_cls;
1120  t->read_fd = -1;
1121  t->write_fd = -1;
1122 #if PROFILE_DELAYS
1123  t->start_time = GNUNET_TIME_absolute_get ();
1124 #endif
1125  t->timeout = at;
1126  t->priority = check_priority (priority);
1128  /* try tail first (optimization in case we are
1129  * appending to a long list of tasks with timeouts) */
1130  if ((NULL == pending_timeout_head) ||
1131  (at.abs_value_us < pending_timeout_head->timeout.abs_value_us))
1132  {
1133  GNUNET_CONTAINER_DLL_insert (pending_timeout_head,
1134  pending_timeout_tail,
1135  t);
1136  }
1137  else
1138  {
1139  /* first move from heuristic start backwards to before start time */
1140  prev = pending_timeout_last;
1141  while ((NULL != prev) &&
1143  prev = prev->prev;
1144  /* now, move from heuristic start (or head of list) forward to insertion point */
1145  if (NULL == prev)
1146  pos = pending_timeout_head;
1147  else
1148  pos = prev->next;
1149  while ((NULL != pos) && (pos->timeout.abs_value_us <=
1150  t->timeout.abs_value_us))
1151  {
1152  prev = pos;
1153  pos = pos->next;
1154  }
1155  GNUNET_CONTAINER_DLL_insert_after (pending_timeout_head,
1156  pending_timeout_tail,
1157  prev,
1158  t);
1159  }
1160  /* finally, update heuristic insertion point to last insertion... */
1161  pending_timeout_last = t;
1162 
1164  "Adding task %p\n",
1165  t);
1166  init_backtrace (t);
1167  return t;
1168 }
1169 
1170 
1182 struct GNUNET_SCHEDULER_Task *
1185  priority,
1187  void *task_cls)
1188 {
1191  priority,
1192  task,
1193  task_cls);
1194 }
1195 
1196 
1206 struct GNUNET_SCHEDULER_Task *
1209  void *task_cls)
1210 {
1212  prio,
1213  task,
1214  task_cls);
1215 }
1216 
1217 
1229 struct GNUNET_SCHEDULER_Task *
1232  void *task_cls)
1233 {
1236  task,
1237  task_cls);
1238 }
1239 
1240 
1252 struct GNUNET_SCHEDULER_Task *
1255  void *task_cls)
1256 {
1259  task,
1260  task_cls);
1261 }
1262 
1263 
1279 struct GNUNET_SCHEDULER_Task *
1281  void *task_cls)
1282 {
1284  task,
1285  task_cls);
1286 }
1287 
1288 
1299 struct GNUNET_SCHEDULER_Task *
1301  void *task_cls)
1302 {
1303  struct GNUNET_SCHEDULER_Task *t;
1304 
1305  /* scheduler must be running */
1306  GNUNET_assert (NULL != scheduler_driver);
1307  GNUNET_assert (NULL != task);
1308  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1310  t->callback = task;
1311  t->callback_cls = task_cls;
1312  t->read_fd = -1;
1313  t->write_fd = -1;
1314 #if PROFILE_DELAYS
1315  t->start_time = GNUNET_TIME_absolute_get ();
1316 #endif
1319  t->on_shutdown = GNUNET_YES;
1320  t->lifeness = GNUNET_NO;
1321  GNUNET_CONTAINER_DLL_insert (shutdown_head,
1322  shutdown_tail,
1323  t);
1325  "Adding shutdown task %p\n",
1326  t);
1327  init_backtrace (t);
1328  return t;
1329 }
1330 
1331 
1346 struct GNUNET_SCHEDULER_Task *
1349  void *task_cls)
1350 {
1351  struct GNUNET_SCHEDULER_Task *ret;
1352 
1353  ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1354  ret->lifeness = lifeness;
1355  return ret;
1356 }
1357 
1358 
1359 #if DEBUG_FDS
1360 
1366 void
1367 check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1368 {
1369  if (-1 != raw_fd)
1370  {
1371  int flags = fcntl (raw_fd, F_GETFD);
1372 
1373  if ((flags == -1) && (errno == EBADF))
1374  {
1376  "Got invalid file descriptor %d!\n",
1377  raw_fd);
1378  init_backtrace (t);
1379  GNUNET_assert (0);
1380  }
1381  }
1382 }
1383 
1384 
1385 #endif
1386 
1387 
1413 static struct GNUNET_SCHEDULER_Task *
1416  const struct GNUNET_NETWORK_Handle *read_nh,
1417  const struct GNUNET_NETWORK_Handle *write_nh,
1418  const struct GNUNET_DISK_FileHandle *read_fh,
1419  const struct GNUNET_DISK_FileHandle *write_fh,
1421  void *task_cls)
1422 {
1423  struct GNUNET_SCHEDULER_Task *t;
1424 
1425  /* scheduler must be running */
1426  GNUNET_assert (NULL != scheduler_driver);
1427  GNUNET_assert (NULL != task);
1428  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1430  init_fd_info (t,
1431  &read_nh,
1432  read_nh ? 1 : 0,
1433  &write_nh,
1434  write_nh ? 1 : 0,
1435  &read_fh,
1436  read_fh ? 1 : 0,
1437  &write_fh,
1438  write_fh ? 1 : 0);
1439  t->callback = task;
1440  t->callback_cls = task_cls;
1441 #if DEBUG_FDS
1442  check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1443  check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1444  check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1445  check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1446 #endif
1447 #if PROFILE_DELAYS
1448  t->start_time = GNUNET_TIME_absolute_get ();
1449 #endif
1452  current_priority : priority);
1454  GNUNET_CONTAINER_DLL_insert (pending_head,
1455  pending_tail,
1456  t);
1457  driver_add_multiple (t);
1459  t->priority);
1460  init_backtrace (t);
1461  return t;
1462 }
1463 
1464 
1485 struct GNUNET_SCHEDULER_Task *
1487  struct GNUNET_NETWORK_Handle *rfd,
1489  void *task_cls)
1490 {
1493  rfd, task, task_cls);
1494 }
1495 
1496 
1519 struct GNUNET_SCHEDULER_Task *
1522  priority,
1523  struct GNUNET_NETWORK_Handle *rfd,
1525  void *task_cls)
1526 {
1527  return GNUNET_SCHEDULER_add_net_with_priority (delay, priority,
1528  rfd,
1529  GNUNET_YES,
1530  GNUNET_NO,
1531  task, task_cls);
1532 }
1533 
1534 
1556 struct GNUNET_SCHEDULER_Task *
1558  struct GNUNET_NETWORK_Handle *wfd,
1560  void *task_cls)
1561 {
1564  wfd,
1566  task, task_cls);
1567 }
1568 
1569 
1593 struct GNUNET_SCHEDULER_Task *
1596  struct GNUNET_NETWORK_Handle *fd,
1597  int on_read,
1598  int on_write,
1600  void *task_cls)
1601 {
1602  /* scheduler must be running */
1603  GNUNET_assert (NULL != scheduler_driver);
1604  GNUNET_assert (on_read || on_write);
1606  return add_without_sets (delay, priority,
1607  on_read ? fd : NULL,
1608  on_write ? fd : NULL,
1609  NULL,
1610  NULL,
1611  task, task_cls);
1612 }
1613 
1614 
1635 struct GNUNET_SCHEDULER_Task *
1637  const struct GNUNET_DISK_FileHandle *rfd,
1639  void *task_cls)
1640 {
1643  rfd, GNUNET_YES, GNUNET_NO,
1644  task, task_cls);
1645 }
1646 
1647 
1668 struct GNUNET_SCHEDULER_Task *
1670  const struct GNUNET_DISK_FileHandle *wfd,
1672  void *task_cls)
1673 {
1676  wfd, GNUNET_NO, GNUNET_YES,
1677  task, task_cls);
1678 }
1679 
1680 
1704 struct GNUNET_SCHEDULER_Task *
1707  priority,
1708  const struct
1710  int on_read, int on_write,
1712  void *task_cls)
1713 {
1714  /* scheduler must be running */
1715  GNUNET_assert (NULL != scheduler_driver);
1716  GNUNET_assert (on_read || on_write);
1717  GNUNET_assert (fd->fd >= 0);
1718  return add_without_sets (delay, priority,
1719  NULL,
1720  NULL,
1721  on_read ? fd : NULL,
1722  on_write ? fd : NULL,
1723  task, task_cls);
1724 }
1725 
1726 
1727 void
1729  const struct GNUNET_NETWORK_Handle ***ntarget,
1730  unsigned int *extracted_nhandles,
1731  const struct GNUNET_DISK_FileHandle ***ftarget,
1732  unsigned int *extracted_fhandles)
1733 {
1734  // FIXME: this implementation only works for unix, for WIN32 the file handles
1735  // in fdset must be handled separately
1736  const struct GNUNET_NETWORK_Handle **nhandles;
1737  const struct GNUNET_DISK_FileHandle **fhandles;
1738  unsigned int nhandles_len;
1739  unsigned int fhandles_len;
1740 
1741  nhandles = NULL;
1742  fhandles = NULL;
1743  nhandles_len = 0;
1744  fhandles_len = 0;
1745  for (int sock = 0; sock != fdset->nsds; ++sock)
1746  {
1747  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1748  {
1749  struct GNUNET_NETWORK_Handle *nhandle;
1750  struct GNUNET_DISK_FileHandle *fhandle;
1751 
1752  nhandle = GNUNET_NETWORK_socket_box_native (sock);
1753  if (NULL != nhandle)
1754  {
1755  GNUNET_array_append (nhandles, nhandles_len, nhandle);
1756  }
1757  else
1758  {
1759  fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1760  if (NULL != fhandle)
1761  {
1762  GNUNET_array_append (fhandles, fhandles_len, fhandle);
1763  }
1764  else
1765  {
1766  GNUNET_assert (0);
1767  }
1768  }
1769  }
1770  }
1771  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1772  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1773  *extracted_nhandles = nhandles_len;
1774  *extracted_fhandles = fhandles_len;
1775 }
1776 
1777 
1809 struct GNUNET_SCHEDULER_Task *
1811  struct GNUNET_TIME_Relative delay,
1812  const struct GNUNET_NETWORK_FDSet *rs,
1813  const struct GNUNET_NETWORK_FDSet *ws,
1815  void *task_cls)
1816 {
1817  struct GNUNET_SCHEDULER_Task *t;
1818  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1819  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1820  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1821  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1822  unsigned int read_nhandles_len = 0;
1823  unsigned int write_nhandles_len = 0;
1824  unsigned int read_fhandles_len = 0;
1825  unsigned int write_fhandles_len = 0;
1826 
1827  /* scheduler must be running */
1828  GNUNET_assert (NULL != scheduler_driver);
1829  GNUNET_assert (NULL != task);
1830  int no_rs = (NULL == rs);
1831  int no_ws = (NULL == ws);
1832  int empty_rs = (NULL != rs) && (0 == rs->nsds);
1833  int empty_ws = (NULL != ws) && (0 == ws->nsds);
1834  int no_fds = (no_rs && no_ws) ||
1835  (empty_rs && empty_ws) ||
1836  (no_rs && empty_ws) ||
1837  (no_ws && empty_rs);
1838  if (! no_fds)
1839  {
1840  if (NULL != rs)
1841  {
1842  extract_handles (rs,
1843  &read_nhandles,
1844  &read_nhandles_len,
1845  &read_fhandles,
1846  &read_fhandles_len);
1847  }
1848  if (NULL != ws)
1849  {
1850  extract_handles (ws,
1851  &write_nhandles,
1852  &write_nhandles_len,
1853  &write_fhandles,
1854  &write_fhandles_len);
1855  }
1856  }int no_fds_extracted = (0 == read_nhandles_len) &&
1864  (0 == read_fhandles_len) &&
1865  (0 == write_nhandles_len) &&
1866  (0 == write_fhandles_len);
1867  if (no_fds || no_fds_extracted)
1869  prio,
1870  task,
1871  task_cls);
1872  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1874  init_fd_info (t,
1875  read_nhandles,
1876  read_nhandles_len,
1877  write_nhandles,
1878  write_nhandles_len,
1879  read_fhandles,
1880  read_fhandles_len,
1881  write_fhandles,
1882  write_fhandles_len);
1883  t->callback = task;
1884  t->callback_cls = task_cls;
1885  t->own_handles = GNUNET_YES;
1886  /* free the arrays of pointers to network / file handles, the actual
1887  * handles will be freed in destroy_task */
1888  GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1889  GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1890  GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1891  GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1892 #if PROFILE_DELAYS
1893  t->start_time = GNUNET_TIME_absolute_get ();
1894 #endif
1896  t->priority =
1897  check_priority ((prio ==
1899  prio);
1901  GNUNET_CONTAINER_DLL_insert (pending_head,
1902  pending_tail,
1903  t);
1904  driver_add_multiple (t);
1906  t->priority);
1908  "Adding task %p\n",
1909  t);
1910  init_backtrace (t);
1911  return t;
1912 }
1913 
1914 
1926 void
1928  struct GNUNET_SCHEDULER_FdInfo *fdi)
1929 {
1930  enum GNUNET_SCHEDULER_Reason reason;
1931 
1932  reason = task->reason;
1933  if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1934  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1936  if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1937  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1940  task->reason = reason;
1941  if (GNUNET_NO == task->in_ready_list)
1942  {
1943  GNUNET_CONTAINER_DLL_remove (pending_head,
1944  pending_tail,
1945  task);
1946  queue_ready_task (task);
1947  }
1948 }
1949 
1950 
1971 int
1973 {
1975  struct GNUNET_SCHEDULER_Task *pos;
1976  struct GNUNET_TIME_Absolute now;
1977 
1978  /* check for tasks that reached the timeout! */
1979  now = GNUNET_TIME_absolute_get ();
1980  pos = pending_timeout_head;
1981  while (NULL != pos)
1982  {
1983  struct GNUNET_SCHEDULER_Task *next = pos->next;
1984  if (now.abs_value_us >= pos->timeout.abs_value_us)
1986  if (0 == pos->reason)
1987  break;
1988  GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
1989  pending_timeout_tail,
1990  pos);
1991  if (pending_timeout_last == pos)
1992  pending_timeout_last = NULL;
1993  queue_ready_task (pos);
1994  pos = next;
1995  }
1996  pos = pending_head;
1997  while (NULL != pos)
1998  {
1999  struct GNUNET_SCHEDULER_Task *next = pos->next;
2000  if (now.abs_value_us >= pos->timeout.abs_value_us)
2001  {
2003  GNUNET_CONTAINER_DLL_remove (pending_head,
2004  pending_tail,
2005  pos);
2006  queue_ready_task (pos);
2007  }
2008  pos = next;
2009  }
2010 
2011  if (0 == ready_count)
2012  {
2013  struct GNUNET_TIME_Absolute timeout = get_timeout ();
2014 
2015  if (timeout.abs_value_us > now.abs_value_us)
2030  "GNUNET_SCHEDULER_do_work did not find any ready "
2031  "tasks and timeout has not been reached yet.\n");
2032  }
2033  else
2034  {
2039  GNUNET_assert (0);
2040  }
2041  }
2042  else
2043  {
2044  /* find out which task priority level we are going to
2045  process this time */
2047  GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]);
2048  /* yes, p>0 is correct, 0 is "KEEP" which should
2049  * always be an empty queue (see assertion)! */
2050  for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--)
2051  {
2052  pos = ready_head[p];
2053  if (NULL != pos)
2054  break;
2055  }
2056  GNUNET_assert (NULL != pos); /* ready_count wrong? */
2057 
2058  /* process all tasks at this priority level, then yield */
2059  while (NULL != (pos = ready_head[p]))
2060  {
2061  GNUNET_CONTAINER_DLL_remove (ready_head[p],
2062  ready_tail[p],
2063  pos);
2064  ready_count--;
2065  current_priority = pos->priority;
2066  current_lifeness = pos->lifeness;
2067  active_task = pos;
2068 #if PROFILE_DELAYS
2069  if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2070  DELAY_THRESHOLD.rel_value_us)
2071  {
2073  "Task %p took %s to be scheduled\n",
2074  pos,
2076  GNUNET_TIME_absolute_get_duration (pos->start_time),
2077  GNUNET_YES));
2078  }
2079 #endif
2080  tc.reason = pos->reason;
2083  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2084  tc.fds_len = pos->fds_len;
2085  tc.fds = pos->fds;
2086  for (unsigned int i = 0; i != pos->fds_len; ++i)
2087  {
2088  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2089  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2090  {
2092  fdi->sock);
2093  }
2094  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2095  {
2097  fdi->sock);
2098  }
2099  }
2100  tc.read_ready = sh->rs;
2101  tc.write_ready = sh->ws;
2103  "Running task %p\n",
2104  pos);
2105  GNUNET_assert (NULL != pos->callback);
2106  {
2107  struct GNUNET_AsyncScopeSave old_scope;
2108  if (pos->scope.have_scope)
2109  GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2110  else
2111  GNUNET_async_scope_get (&old_scope);
2112  pos->callback (pos->callback_cls);
2113  GNUNET_async_scope_restore (&old_scope);
2114  }
2115  if (NULL != pos->fds)
2116  {
2117  int del_result = scheduler_driver->del (scheduler_driver->cls, pos);
2118  if (GNUNET_OK != del_result)
2119  {
2121  "driver could not delete task %p\n", pos);
2122  GNUNET_assert (0);
2123  }
2124  }
2125  active_task = NULL;
2126  dump_backtrace (pos);
2127  destroy_task (pos);
2128  }
2129  }
2131  if (0 == ready_count)
2132  {
2133  scheduler_driver->set_wakeup (scheduler_driver->cls,
2134  get_timeout ());
2135  return GNUNET_NO;
2136  }
2137  scheduler_driver->set_wakeup (scheduler_driver->cls,
2139  return GNUNET_YES;
2140 }
2141 
2142 
2174 struct GNUNET_SCHEDULER_Handle *
2176 {
2177  struct GNUNET_SCHEDULER_Handle *sh;
2178  const struct GNUNET_DISK_FileHandle *pr;
2179 
2180  /* scheduler must not be running */
2181  GNUNET_assert (NULL == scheduler_driver);
2182  GNUNET_assert (NULL == shutdown_pipe_handle);
2183  /* general set-up */
2184  sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle);
2185  shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO,
2186  GNUNET_NO,
2187  GNUNET_NO,
2188  GNUNET_NO);
2189  GNUNET_assert (NULL != shutdown_pipe_handle);
2190  pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
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  install_parent_control_task =
2218  NULL);
2219  shutdown_pipe_task =
2221  pr,
2223  NULL);
2225  scheduler_driver->set_wakeup (scheduler_driver->cls,
2226  get_timeout ());
2227  /* begin main event loop */
2231  return sh;
2232 }
2233 
2234 
2249 void
2251 {
2252  GNUNET_assert (NULL == pending_head);
2253  GNUNET_assert (NULL == pending_timeout_head);
2254  GNUNET_assert (NULL == shutdown_head);
2255  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2256  {
2257  GNUNET_assert (NULL == ready_head[i]);
2258  }
2261 
2262  /* uninstall signal handlers */
2265 #if (SIGTERM != GNUNET_TERM_SIG)
2266  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
2267 #endif
2271  GNUNET_DISK_pipe_close (shutdown_pipe_handle);
2272  shutdown_pipe_handle = NULL;
2273  scheduler_driver = NULL;
2274  GNUNET_free (sh);
2275 }
2276 
2277 
2278 static int
2280  struct DriverContext *context)
2281 {
2282  struct GNUNET_NETWORK_FDSet *rs;
2283  struct GNUNET_NETWORK_FDSet *ws;
2284  int select_result;
2285 
2286  GNUNET_assert (NULL != context);
2289  while ((NULL != context->scheduled_head) ||
2290  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2291  context->timeout.abs_value_us))
2292  {
2294  "select timeout = %s\n",
2296 
2299 
2300  for (struct Scheduled *pos = context->scheduled_head;
2301  NULL != pos;
2302  pos = pos->next)
2303  {
2304  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2305  {
2306  GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2307  }
2308  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2309  {
2310  GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2311  }
2312  }
2313  struct GNUNET_TIME_Relative time_remaining =
2315  if (NULL == scheduler_select)
2316  {
2317  select_result = GNUNET_NETWORK_socket_select (rs,
2318  ws,
2319  NULL,
2320  time_remaining);
2321  }
2322  else
2323  {
2324  select_result = scheduler_select (scheduler_select_cls,
2325  rs,
2326  ws,
2327  NULL,
2328  time_remaining);
2329  }
2330  if (select_result == GNUNET_SYSERR)
2331  {
2332  if (errno == EINTR)
2333  continue;
2334 
2336  "select");
2337 #if USE_LSOF
2338  char lsof[512];
2339 
2340  snprintf (lsof,
2341  sizeof(lsof),
2342  "lsof -p %d",
2343  getpid ());
2344  (void) close (1);
2345  (void) dup2 (2, 1);
2346  if (0 != system (lsof))
2348  "system");
2349 #endif
2350 #if DEBUG_FDS
2351  for (struct Scheduled *s = context->scheduled_head;
2352  NULL != s;
2353  s = s->next)
2354  {
2355  int flags = fcntl (s->fdi->sock,
2356  F_GETFD);
2357 
2358  if ((flags == -1) &&
2359  (EBADF == errno))
2360  {
2362  "Got invalid file descriptor %d!\n",
2363  s->fdi->sock);
2364 #if EXECINFO
2365  dump_backtrace (s->task);
2366 #endif
2367  }
2368  }
2369 #endif
2370  GNUNET_assert (0);
2373  return GNUNET_SYSERR;
2374  }
2375  if (select_result > 0)
2376  {
2377  for (struct Scheduled *pos = context->scheduled_head;
2378  NULL != pos;
2379  pos = pos->next)
2380  {
2381  int is_ready = GNUNET_NO;
2382 
2383  if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2384  (GNUNET_YES ==
2386  pos->fdi->sock)) )
2387  {
2388  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2389  is_ready = GNUNET_YES;
2390  }
2391  if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2392  (GNUNET_YES ==
2394  pos->fdi->sock)) )
2395  {
2396  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2397  is_ready = GNUNET_YES;
2398  }
2399  if (GNUNET_YES == is_ready)
2400  {
2401  GNUNET_SCHEDULER_task_ready (pos->task,
2402  pos->fdi);
2403  }
2404  }
2405  }
2407  {
2409  "scheduler has more tasks ready!\n");
2410  }
2411  }
2414  return GNUNET_OK;
2415 }
2416 
2417 
2418 static int
2419 select_add (void *cls,
2420  struct GNUNET_SCHEDULER_Task *task,
2421  struct GNUNET_SCHEDULER_FdInfo *fdi)
2422 {
2423  struct DriverContext *context = cls;
2424 
2425  GNUNET_assert (NULL != context);
2426  GNUNET_assert (NULL != task);
2427  GNUNET_assert (NULL != fdi);
2428  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2429  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2430 
2431  if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2432  {
2433  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2434  return GNUNET_SYSERR;
2435  }
2436 
2437  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2438  scheduled->task = task;
2439  scheduled->fdi = fdi;
2440  scheduled->et = fdi->et;
2441 
2443  context->scheduled_tail,
2444  scheduled);
2445  return GNUNET_OK;
2446 }
2447 
2448 
2449 static int
2450 select_del (void *cls,
2451  struct GNUNET_SCHEDULER_Task *task)
2452 {
2453  struct DriverContext *context;
2454  struct Scheduled *pos;
2455  int ret;
2456 
2457  GNUNET_assert (NULL != cls);
2458 
2459  context = cls;
2460  ret = GNUNET_SYSERR;
2461  pos = context->scheduled_head;
2462  while (NULL != pos)
2463  {
2464  struct Scheduled *next = pos->next;
2465  if (pos->task == task)
2466  {
2468  context->scheduled_tail,
2469  pos);
2470  GNUNET_free (pos);
2471  ret = GNUNET_OK;
2472  }
2473  pos = next;
2474  }
2475  return ret;
2476 }
2477 
2478 
2479 static void
2481  struct GNUNET_TIME_Absolute dt)
2482 {
2483  struct DriverContext *context = cls;
2484 
2485  GNUNET_assert (NULL != context);
2486  context->timeout = dt;
2487 }
2488 
2489 
2495 struct GNUNET_SCHEDULER_Driver *
2497 {
2498  struct GNUNET_SCHEDULER_Driver *select_driver;
2499 
2500  select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2501 
2502  select_driver->add = &select_add;
2503  select_driver->del = &select_del;
2504  select_driver->set_wakeup = &select_set_wakeup;
2505 
2506  return select_driver;
2507 }
2508 
2509 
2522 void
2524 {
2525  struct GNUNET_AsyncScopeSave dummy_old_scope;
2526 
2527  GNUNET_assert (NULL != active_task);
2528  /* Since we're in a task, the context will be automatically
2529  restored by the scheduler. */
2530  GNUNET_async_scope_enter (aid, &dummy_old_scope);
2531 }
2532 
2533 
2534 /* end of scheduler.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context()
Obtain the task context, giving the reason why the current task was started.
Definition: scheduler.c:747
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1080
int read_fd
Set if we only wait for reading from a single FD, otherwise -1.
Definition: scheduler.c:208
static unsigned int ready_count
Number of tasks on the ready list.
Definition: scheduler.c:390
int nsds
Maximum number of any socket descriptor in the set (plus one)
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_at_with_priority(struct GNUNET_TIME_Absolute at, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run at the specified time.
Definition: scheduler.c:1104
Information about an event relating to a file descriptor/socket.
struct GNUNET_NETWORK_FDSet * rs
Passed here to avoid constantly allocating/deallocating this element, but generally we want to get ri...
Definition: scheduler.c:88
uint64_t rel_value_us
The actual value.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static void install_parent_control_handler(void *cls)
Definition: scheduler.c:922
GNUNET_SCHEDULER_TaskCallback callback
Function to run when ready.
Definition: scheduler.c:149
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1183
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:732
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition: network.c:1137
The reading socket is ready.
Context information passed to each scheduler task.
static struct GNUNET_SCHEDULER_Task * shutdown_tail
Tail of list of tasks waiting for shutdown.
Definition: scheduler.c:331
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1300
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
The prerequisite task is done.
static GNUNET_SCHEDULER_select scheduler_select
Function to use as a select() in the scheduler.
Definition: scheduler.c:413
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition: scheduler.c:1032
static void sighandler_shutdown()
Wait for a short time.
Definition: scheduler.c:661
struct GNUNET_SCHEDULER_Task * prev
This is a linked list.
Definition: scheduler.c:144
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:418
Run with the same priority as the current job.
struct GNUNET_SCHEDULER_Handle * GNUNET_SCHEDULER_driver_init(const struct GNUNET_SCHEDULER_Driver *driver)
Function called by external event loop implementations to initialize the scheduler.
Definition: scheduler.c:2175
struct GNUNET_SIGNAL_Context * shc_term
context of the SIGTERM handler
Definition: scheduler.c:105
int GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to, int nfd)
Test native fd in a set.
Definition: network.c:1155
const struct GNUNET_NETWORK_FDSet * write_ready
Set of file descriptors ready for writing; note that additional bits may be set that were not in the ...
static pid_t my_pid
Process ID of this process at the time we installed the various signal handlers.
Definition: scheduler.c:627
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:1557
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:717
int on_shutdown
Is this task run on shutdown?
Definition: scheduler.c:224
static struct GNUNET_SCHEDULER_Task * pending_timeout_tail
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:349
API an external event loop has to implement for GNUNET_SCHEDULER_driver_init.
static struct GNUNET_DISK_PipeHandle * shutdown_pipe_handle
Pipe used to communicate shutdown via signal.
Definition: scheduler.c:621
#define GNUNET_NO
Definition: gnunet_common.h:78
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:1669
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:1636
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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:464
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal hander.
Definition: signal.c:77
const struct GNUNET_NETWORK_FDSet * read_ready
Set of file descriptors ready for reading; note that additional bits may be set that were not in the ...
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct Scheduled * scheduled_head
the head of a DLL containing information about the events the select driver is waiting for ...
Definition: scheduler.c:288
Identifier for an asynchronous execution context.
static struct GNUNET_SCHEDULER_Task * pending_head
Head of list of tasks waiting for an event.
Definition: scheduler.c:316
static struct GNUNET_SCHEDULER_Task * t
Main task.
GNUNET_SCHEDULER_Priority
Valid task priorities.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_file_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_DISK_FileHandle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready...
Definition: scheduler.c:1705
static struct GNUNET_SCHEDULER_Task * active_task
ID of the task that is running right now.
Definition: scheduler.c:360
void GNUNET_SCHEDULER_shutdown()
Request the shutdown of a scheduler.
Definition: scheduler.c:526
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:1728
uint64_t abs_value_us
The actual value.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority and to be run after the specified delay or wh...
Definition: scheduler.c:1520
static struct GNUNET_SCHEDULER_Task * install_parent_control_task
Task for installing parent control handlers (it might happen that the scheduler is shutdown before th...
Definition: scheduler.c:379
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
int GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:192
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition: disk.c:1753
static struct GNUNET_SCHEDULER_Task * pending_timeout_last
Last inserted task waiting ONLY for a timeout event.
Definition: scheduler.c:355
static pa_context * context
Pulseaudio context.
void(* GNUNET_SCHEDULER_TaskCallback)(void *cls)
Signature of the main function of a task.
struct GNUNET_SCHEDULER_Driver * GNUNET_SCHEDULER_driver_select()
Obtain the driver for using select() as the event loop.
Definition: scheduler.c:2496
We are shutting down and are running all shutdown-related tasks.
int write_fd
Set if we only wait for writing to a single FD, otherwise -1.
Definition: scheduler.c:213
void GNUNET_SCHEDULER_add_with_reason_and_priority(GNUNET_SCHEDULER_TaskCallback task, void *task_cls, enum GNUNET_SCHEDULER_Reason reason, enum GNUNET_SCHEDULER_Priority priority)
Continue the current execution with the given function.
Definition: scheduler.c:1060
const struct GNUNET_SCHEDULER_FdInfo * fds
Array of length fds_len with information about ready FDs.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
void GNUNET_async_scope_enter(const struct GNUNET_AsyncScopeId *aid, struct GNUNET_AsyncScopeSave *old_scope)
Set the async scope for the current thread.
Driver context used by GNUNET_SCHEDULER_run.
Definition: scheduler.c:282
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now_with_lifeness(int lifeness, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible with the (transitive) ignore-shutdown flag either e...
Definition: scheduler.c:1347
GNUNET_SCHEDULER_Reason
Reasons why the schedule may have triggered the task now.
void GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
Only free memory of a socket, keep the file descriptor untouched.
Definition: network.c:622
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1266
unsigned int fds_len
Length of the following array.
struct GNUNET_SCHEDULER_FdInfo * fdi
information about the network socket / file descriptor where the event is expected to occur ...
Definition: scheduler.c:269
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition: scheduler.c:2450
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition: scheduler.c:2480
static struct GNUNET_SCHEDULER_Task * pending_tail
Tail of list of tasks waiting for an event.
Definition: scheduler.c:321
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1253
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1250
void GNUNET_SCHEDULER_set_select(GNUNET_SCHEDULER_select new_select, void *new_select_cls)
Sets the select function to use in the scheduler (scheduler_select).
Definition: scheduler.c:434
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:1207
static struct GNUNET_SCHEDULER_Task * ready_tail[GNUNET_SCHEDULER_PRIORITY_COUNT]
Tail of list of tasks ready to run right now, grouped by importance.
Definition: scheduler.c:371
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_SCHEDULER_FdInfo fdx
Storage location used for fds if we want to avoid a separate malloc() call in the common case that th...
Definition: scheduler.c:166
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:820
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:82
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:1280
static enum GNUNET_NetworkType scope
Which network scope do we belong to?
int sock
Underlying OS handle the event was about.
static struct SolverHandle * sh
static int current_lifeness
Value of the &#39;lifeness&#39; flag for the current task.
Definition: scheduler.c:407
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:687
static struct GNUNET_SCHEDULER_Task * pending_timeout_head
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:340
collection of IO descriptors
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1810
const struct GNUNET_DISK_FileHandle * fh
GNUnet file handle the event is about, matches sock, NULL if this is about a network socket or if no ...
const struct GNUNET_NETWORK_Handle * fd
GNUnet network socket the event is about, matches sock, NULL if this is about a file handle or if no ...
static void driver_add_multiple(struct GNUNET_SCHEDULER_Task *t)
calls the given function func on each FdInfo related to t.
Definition: scheduler.c:900
static struct GNUNET_SCHEDULER_Task * ready_head[GNUNET_SCHEDULER_PRIORITY_COUNT]
Head of list of tasks ready to run right now, grouped by importance.
Definition: scheduler.c:365
struct GNUNET_SIGNAL_Context * shc_int
context of the SIGINT handler
Definition: scheduler.c:100
A struct representing an event the select driver is waiting for.
Definition: scheduler.c:254
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
static const struct GNUNET_SCHEDULER_Driver * scheduler_driver
The driver used for the event loop.
Definition: scheduler.c:311
The writing-end of a pipe.
Buffer available for writing.
The reading-end of a pipe.
static int fh
Handle to the unique file.
static struct GNUNET_SCHEDULER_Task * shutdown_pipe_task
Task for reading from a pipe that signal handlers will use to initiate shutdown.
Definition: scheduler.c:385
struct GNUNET_SIGNAL_Context * shc_hup
context of the SIGHUP handler
Definition: scheduler.c:122
static struct GNUNET_SCHEDULER_Task * add_without_sets(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, const struct GNUNET_NETWORK_Handle *read_nh, const struct GNUNET_NETWORK_Handle *write_nh, const struct GNUNET_DISK_FileHandle *read_fh, const struct GNUNET_DISK_FileHandle *write_fh, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
Definition: scheduler.c:1414
#define LOG_STRERROR(kind, syscall)
Definition: scheduler.c:33
void GNUNET_OS_install_parent_control_handler(void *cls)
Connects this process to its parent via pipe; essentially, the parent control handler will read signa...
Definition: os_priority.c:141
struct GNUNET_SCHEDULER_FdInfo * fds
Information about which FDs are ready for this task (and why).
Definition: scheduler.c:159
void GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
Get the current async scope.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static int select_add(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Definition: scheduler.c:2419
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(int blocking_read, int blocking_write, int inherit_read, int inherit_write)
Creates an interprocess channel.
Definition: disk.c:1526
static struct GNUNET_TIME_Absolute start_time
Start time of the current round; used to determine how long one iteration takes (which influences how...
void * callback_cls
Closure for the callback.
Definition: scheduler.c:154
enum GNUNET_SCHEDULER_Reason reason
Why is the task ready? Set after task is added to ready queue.
Definition: scheduler.c:198
struct GNUNET_SIGNAL_Context * GNUNET_SIGNAL_handler_install(int signal, GNUNET_SIGNAL_Handler handler)
Install a signal handler that will be run if the given signal is received.
Definition: signal.c:51
int GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, struct GNUNET_TIME_Relative timeout)
Check if sockets meet certain conditions.
Definition: network.c:1340
The writing socket is ready.
static int select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition: scheduler.c:2279
This is an internal priority level that is only used for tasks that are being triggered due to shutdo...
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
Data available for reading.
static void queue_ready_task(struct GNUNET_SCHEDULER_Task *task)
Put a task that is ready for execution into the ready queue.
Definition: scheduler.c:507
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
#define LOG(kind,...)
Definition: scheduler.c:31
Saved async scope identifier or root scope.
#define DELAY_THRESHOLD
Task that were in the queue for longer than this are reported if PROFILE_DELAYS is active...
Definition: scheduler.c:73
The specified timeout has expired.
void GNUNET_async_scope_restore(struct GNUNET_AsyncScopeSave *old_scope)
Clear the current thread&#39;s async scope.
void GNUNET_NETWORK_fdset_zero(struct GNUNET_NETWORK_FDSet *fds)
Reset FD set (clears all file descriptors).
Definition: network.c:997
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct Scheduled * prev
Definition: scheduler.c:256
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition: scheduler.c:580
static enum GNUNET_SCHEDULER_Priority current_priority
Priority of the task running right now.
Definition: scheduler.c:396
void(* set_wakeup)(void *cls, struct GNUNET_TIME_Absolute dt)
Set time at which we definitively want to get a wakeup call.
void GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_DISK_FileHandle *h)
Add a file handle to the fd set.
Definition: network.c:1171
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
int(* add)(void *cls, struct GNUNET_SCHEDULER_Task *task, struct GNUNET_SCHEDULER_FdInfo *fdi)
Add a task to be run if the conditions specified in the et field of the given fdi are satisfied...
int GNUNET_SCHEDULER_do_work(struct GNUNET_SCHEDULER_Handle *sh)
Function called by external event loop implementations to tell the scheduler to run some of the tasks...
Definition: scheduler.c:1972
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1715
enum GNUNET_SCHEDULER_EventType et
Type of the event that was generated related to sock.
struct GNUNET_SIGNAL_Context * shc_pipe
context of hte SIGPIPE handler
Definition: scheduler.c:127
#define GNUNET_array_append(arr, size, element)
Append an element to a list (growing the list by one).
unsigned int fds_len
Size of the fds array.
Definition: scheduler.c:171
struct GNUNET_TIME_Absolute timeout
the time when the select driver will wake up again (after calling select)
Definition: scheduler.c:300
int own_handles
Do we own the network and file handles referenced by the FdInfo structs in the fds array...
Definition: scheduler.c:178
static void sighandler_pipe()
Signal handler called for SIGPIPE.
Definition: scheduler.c:633
struct GNUNET_AsyncScopeId scope_id
Saved scope.
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:931
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1375
No event (useful for timeout).
struct Scheduled * scheduled_tail
the tail of a DLL containing information about the events the select driver is waiting for ...
Definition: scheduler.c:294
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:375
struct GNUNET_SCHEDULER_Task * next
This is a linked list.
Definition: scheduler.c:139
int(* GNUNET_SCHEDULER_select)(void *cls, struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, struct GNUNET_TIME_Relative timeout)
Signature of the select function used by the scheduler.
static enum GNUNET_SCHEDULER_Priority max_priority_added
Priority of the highest task added in the current select iteration.
Definition: scheduler.c:402
static enum GNUNET_SCHEDULER_Priority check_priority(enum GNUNET_SCHEDULER_Priority p)
Check that the given priority is legal (and return it).
Definition: scheduler.c:449
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:2523
This is the very first task run during startup.
void * cls
Closure to pass to the functions in this struct.
Entry in list of pending tasks.
Definition: scheduler.c:134
void init_fd_info(struct GNUNET_SCHEDULER_Task *t, const struct GNUNET_NETWORK_Handle *const *read_nh, unsigned int read_nh_len, const struct GNUNET_NETWORK_Handle *const *write_nh, unsigned int write_nh_len, const struct GNUNET_DISK_FileHandle *const *read_fh, unsigned int read_fh_len, const struct GNUNET_DISK_FileHandle *const *write_fh, unsigned int write_fh_len)
Definition: scheduler.c:782
struct GNUNET_SCHEDULER_Task * task
the task, the event is related to
Definition: scheduler.c:263
enum GNUNET_SCHEDULER_EventType et
the event types (multiple event types can be ORed) the select driver is expected to wait for ...
Definition: scheduler.c:275
handle to a socket
Definition: network.c:52
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition: scheduler.c:2250
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
struct GNUNET_TIME_Absolute timeout
Absolute timeout value for the task, or GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout".
Definition: scheduler.c:184
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:559
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:1486
enum GNUNET_SCHEDULER_Priority priority
Task priority.
Definition: scheduler.c:203
int fd
File handle on Unix-like systems.
struct GNUNET_AsyncScopeSave scope
Asynchronous scope of the task that scheduled this scope,.
Definition: scheduler.c:247
Number of priorities (must be the last priority).
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_net_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, struct GNUNET_NETWORK_Handle *fd, int on_read, int on_write, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready...
Definition: scheduler.c:1594
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:1927
static struct GNUNET_SCHEDULER_Task * shutdown_head
Head of list of tasks waiting for shutdown.
Definition: scheduler.c:326
Run with the default priority (normal P2P operations).
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:742
struct GNUNET_NETWORK_FDSet * ws
Passed here to avoid constantly allocating/deallocating this element, but generally we want to get ri...
Definition: scheduler.c:95
int in_ready_list
Is this task in the ready list?
Definition: scheduler.c:229
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native(int fd)
Box a native socket (and check that it is a socket).
Definition: network.c:636
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:242
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:1230
struct Scheduled * next
Definition: scheduler.c:258
struct GNUNET_SIGNAL_Context * shc_quit
context of the SIGQUIT handler
Definition: scheduler.c:117
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:68
Argument to be passed from the driver to GNUNET_SCHEDULER_do_work().
Definition: scheduler.c:81
int(* del)(void *cls, struct GNUNET_SCHEDULER_Task *task)
Delete a task from the set of tasks to be run.
unsigned int GNUNET_SCHEDULER_get_load(enum GNUNET_SCHEDULER_Priority p)
Get information about the current load of this scheduler.
Definition: scheduler.c:764
static void * scheduler_select_cls
Closure for scheduler_select.
Definition: scheduler.c:423
Internal DISK related helper functions.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
int lifeness
Should the existence of this task in the queue be counted as reason to not shutdown the scheduler...
Definition: scheduler.c:219
GNUNET_SCHEDULER_EventType
Possible events on FDs, used as a bitmask.
static void shutdown_if_no_lifeness()
Definition: scheduler.c:677
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966