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 
413 
419 
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 
470 {
471  struct GNUNET_SCHEDULER_Task *pos;
472  struct GNUNET_TIME_Absolute now;
473  struct GNUNET_TIME_Absolute timeout;
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 
516  GNUNET_CONTAINER_DLL_insert_tail (ready_head[p],
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  {
539  GNUNET_SCHEDULER_cancel (install_parent_control_task);
540  install_parent_control_task = NULL;
541  }
542  if (NULL != shutdown_pipe_task)
543  {
544  GNUNET_SCHEDULER_cancel (shutdown_pipe_task);
545  shutdown_pipe_task = NULL;
546  }
547  while (NULL != (pos = shutdown_head))
548  {
549  GNUNET_CONTAINER_DLL_remove (shutdown_head,
550  shutdown_tail,
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 {
587  unsigned int i;
588 
590  "destroying task %p\n",
591  t);
592 
593  if (GNUNET_YES == t->own_handles)
594  {
595  for (i = 0; i != t->fds_len; ++i)
596  {
597  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
598  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
599  if (fd)
600  {
602  GNUNET_NETWORK_Handle *) fd);
603  }
604  if (fh)
605  {
606  // FIXME: on WIN32 this is not enough! A function
607  // GNUNET_DISK_file_free_memory_only would be nice
608  GNUNET_free ((void *) fh);
609  }
610  }
611  }
612  if (t->fds_len > 1)
613  {
614  GNUNET_array_grow (t->fds, t->fds_len, 0);
615  }
616 #if EXECINFO
617  GNUNET_free (t->backtrace_strings);
618 #endif
619  GNUNET_free (t);
620 }
621 
622 
627 
632 static pid_t my_pid;
633 
637 static void
639 {
640  return;
641 }
642 
643 
645 // * Wait for a short time.
646 // * Sleeps for @a ms ms (as that should be long enough for virtually all
647 // * modern systems to context switch and allow another process to do
648 // * some 'real' work).
649 // *
650 // * @param ms how many ms to wait
651 // */
652 // static void
653 // short_wait (unsigned int ms)
654 // {
655 // struct GNUNET_TIME_Relative timeout;
656 //
657 // timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms);
658 // (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
659 // }
660 
661 
665 static void
667 {
668  static char c;
669  int old_errno = errno; /* backup errno */
670 
671  if (getpid () != my_pid)
672  _exit (1); /* we have fork'ed since the signal handler was created,
673  * ignore the signal, see https://gnunet.org/vfork discussion */
675  (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE),
676  &c, sizeof(c));
677  errno = old_errno;
678 }
679 
680 
681 static void
683 {
684  struct GNUNET_SCHEDULER_Task *t;
685 
686  if (ready_count > 0)
687  return;
688  for (t = pending_head; NULL != t; t = t->next)
689  if (GNUNET_YES == t->lifeness)
690  return;
691  for (t = shutdown_head; NULL != t; t = t->next)
692  if (GNUNET_YES == t->lifeness)
693  return;
694  for (t = pending_timeout_head; NULL != t; t = t->next)
695  if (GNUNET_YES == t->lifeness)
696  return;
697  /* No lifeness! */
699 }
700 
701 
702 static int
704  struct DriverContext *context);
705 
706 
721 void
723  void *task_cls)
724 {
725  struct GNUNET_SCHEDULER_Handle *sh;
726  struct GNUNET_SCHEDULER_Driver *driver;
727  struct DriverContext context = {
728  .scheduled_head = NULL,
729  .scheduled_tail = NULL,
730  .timeout = GNUNET_TIME_absolute_get ()
731  };
732 
733  driver = GNUNET_SCHEDULER_driver_select ();
734  driver->cls = &context;
735  sh = GNUNET_SCHEDULER_driver_init (driver);
737  task_cls,
740  select_loop (sh,
741  &context);
743  GNUNET_free (driver);
744 }
745 
746 
753 const struct GNUNET_SCHEDULER_TaskContext *
755 {
756  GNUNET_assert (NULL != active_task);
757  return &tc;
758 }
759 
760 
770 unsigned int
772 {
773  unsigned int ret;
774 
775  GNUNET_assert (NULL != active_task);
777  return ready_count;
779  p = current_priority;
780  ret = 0;
781  for (struct GNUNET_SCHEDULER_Task *pos = ready_head[check_priority (p)];
782  NULL != pos;
783  pos = pos->next)
784  ret++;
785  return ret;
786 }
787 
788 
789 void
791  const struct GNUNET_NETWORK_Handle *const *read_nh,
792  unsigned int read_nh_len,
793  const struct GNUNET_NETWORK_Handle *const *write_nh,
794  unsigned int write_nh_len,
795  const struct GNUNET_DISK_FileHandle *const *read_fh,
796  unsigned int read_fh_len,
797  const struct GNUNET_DISK_FileHandle *const *write_fh,
798  unsigned int write_fh_len)
799 {
800  // FIXME: if we have exactly two network handles / exactly two file handles
801  // and they are equal, we can make one FdInfo with both
802  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
803  struct GNUNET_SCHEDULER_FdInfo *fdi;
804 
805  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
806  if (1 == t->fds_len)
807  {
808  fdi = &t->fdx;
809  t->fds = fdi;
810  if (1 == read_nh_len)
811  {
812  GNUNET_assert (NULL != read_nh);
813  GNUNET_assert (NULL != *read_nh);
814  fdi->fd = *read_nh;
815  fdi->et = GNUNET_SCHEDULER_ET_IN;
816  fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
817  t->read_fd = fdi->sock;
818  t->write_fd = -1;
819  }
820  else if (1 == write_nh_len)
821  {
822  GNUNET_assert (NULL != write_nh);
823  GNUNET_assert (NULL != *write_nh);
824  fdi->fd = *write_nh;
826  fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
827  t->read_fd = -1;
828  t->write_fd = fdi->sock;
829  }
830  else if (1 == read_fh_len)
831  {
832  GNUNET_assert (NULL != read_fh);
833  GNUNET_assert (NULL != *read_fh);
834  fdi->fh = *read_fh;
835  fdi->et = GNUNET_SCHEDULER_ET_IN;
836  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
837  t->read_fd = fdi->sock;
838  t->write_fd = -1;
839  }
840  else
841  {
842  GNUNET_assert (NULL != write_fh);
843  GNUNET_assert (NULL != *write_fh);
844  fdi->fh = *write_fh;
846  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
847  t->read_fd = -1;
848  t->write_fd = fdi->sock;
849  }
850  }
851  else
852  {
854  t->fds = fdi;
855  t->read_fd = -1;
856  t->write_fd = -1;
857  unsigned int i;
858  for (i = 0; i != read_nh_len; ++i)
859  {
860  fdi->fd = read_nh[i];
861  GNUNET_assert (NULL != fdi->fd);
862  fdi->et = GNUNET_SCHEDULER_ET_IN;
863  fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
864  ++fdi;
865  }
866  for (i = 0; i != write_nh_len; ++i)
867  {
868  fdi->fd = write_nh[i];
869  GNUNET_assert (NULL != fdi->fd);
871  fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
872  ++fdi;
873  }
874  for (i = 0; i != read_fh_len; ++i)
875  {
876  fdi->fh = read_fh[i];
877  GNUNET_assert (NULL != fdi->fh);
878  fdi->et = GNUNET_SCHEDULER_ET_IN;
879  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
880  ++fdi;
881  }
882  for (i = 0; i != write_fh_len; ++i)
883  {
884  fdi->fh = write_fh[i];
885  GNUNET_assert (NULL != fdi->fh);
887  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
888  ++fdi;
889  }
890  }
891 }
892 
893 
907 static void
909 {
910  struct GNUNET_SCHEDULER_FdInfo *fdi;
911  int success = GNUNET_YES;
912 
913  for (unsigned int i = 0; i != t->fds_len; ++i)
914  {
915  fdi = &t->fds[i];
916  success = scheduler_driver->add (scheduler_driver->cls,
917  t,
918  fdi) && success;
920  }
921  if (GNUNET_YES != success)
922  {
924  "driver could not add task\n");
925  }
926 }
927 
928 
929 static void
931 {
932  (void) cls;
933  install_parent_control_task = NULL;
935 }
936 
937 
938 static void
939 shutdown_pipe_cb (void *cls)
940 {
941  char c;
942  const struct GNUNET_DISK_FileHandle *pr;
943 
944  (void) cls;
945  shutdown_pipe_task = NULL;
946  pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
949  /* consume the signal */
950  GNUNET_DISK_file_read (pr, &c, sizeof(c));
951  /* mark all active tasks as ready due to shutdown */
953  shutdown_pipe_task =
955  pr,
957  NULL);
958 }
959 
960 
973 void *
975 {
977  int is_fd_task;
978  void *ret;
979 
981  "canceling task %p\n",
982  task);
983 
984  /* scheduler must be running */
985  GNUNET_assert (NULL != scheduler_driver);
986  is_fd_task = (NULL != task->fds);
987  if (is_fd_task)
988  {
989  int del_result = scheduler_driver->del (scheduler_driver->cls, task);
990  if (GNUNET_OK != del_result)
991  {
993  "driver could not delete task\n");
994  GNUNET_assert (0);
995  }
996  }
997  if (! task->in_ready_list)
998  {
999  if (is_fd_task)
1000  {
1001  GNUNET_CONTAINER_DLL_remove (pending_head,
1002  pending_tail,
1003  task);
1004  }
1005  else if (GNUNET_YES == task->on_shutdown)
1006  {
1007  GNUNET_CONTAINER_DLL_remove (shutdown_head,
1008  shutdown_tail,
1009  task);
1010  }
1011  else
1012  {
1013  GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
1014  pending_timeout_tail,
1015  task);
1016  if (pending_timeout_last == task)
1017  pending_timeout_last = NULL;
1018  }
1019  }
1020  else
1021  {
1022  p = check_priority (task->priority);
1023  GNUNET_CONTAINER_DLL_remove (ready_head[p],
1024  ready_tail[p],
1025  task);
1026  ready_count--;
1027  }
1028  ret = task->callback_cls;
1029  destroy_task (task);
1030  return ret;
1031 }
1032 
1033 
1039 static void
1041 {
1042 #if EXECINFO
1043  void *backtrace_array[MAX_TRACE_DEPTH];
1044 
1045  t->num_backtrace_strings
1046  = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1047  t->backtrace_strings =
1048  backtrace_symbols (backtrace_array,
1049  t->num_backtrace_strings);
1050  dump_backtrace (t);
1051 #else
1052  (void) t;
1053 #endif
1054 }
1055 
1056 
1067 void
1069  task,
1070  void *task_cls,
1072  reason,
1074  priority)
1075 {
1076  struct GNUNET_SCHEDULER_Task *t;
1077 
1078  /* scheduler must be running */
1079  GNUNET_assert (NULL != scheduler_driver);
1080  GNUNET_assert (NULL != task);
1081  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1082  t->read_fd = -1;
1083  t->write_fd = -1;
1084  t->callback = task;
1085  t->callback_cls = task_cls;
1086 #if PROFILE_DELAYS
1087  t->start_time = GNUNET_TIME_absolute_get ();
1088 #endif
1089  t->reason = reason;
1090  t->priority = check_priority (priority);
1093  "Adding continuation task %p\n",
1094  t);
1095  init_backtrace (t);
1096  queue_ready_task (t);
1097 }
1098 
1099 
1111 struct GNUNET_SCHEDULER_Task *
1115  void *task_cls)
1116 {
1117  struct GNUNET_SCHEDULER_Task *t;
1118  struct GNUNET_SCHEDULER_Task *pos;
1119  struct GNUNET_SCHEDULER_Task *prev;
1120  struct GNUNET_TIME_Relative left;
1121 
1122  /* scheduler must be running */
1123  GNUNET_assert (NULL != scheduler_driver);
1124  GNUNET_assert (NULL != task);
1125  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1127  t->callback = task;
1128  t->callback_cls = task_cls;
1129  t->read_fd = -1;
1130  t->write_fd = -1;
1131 #if PROFILE_DELAYS
1132  t->start_time = GNUNET_TIME_absolute_get ();
1133 #endif
1134  t->timeout = at;
1135  t->priority = check_priority (priority);
1137  init_backtrace (t);
1138 
1140  if (0 == left.rel_value_us)
1141  {
1142  queue_ready_task (t);
1143  if (priority > work_priority)
1144  work_priority = priority;
1145  return t;
1146  }
1147 
1148  /* try tail first (optimization in case we are
1149  * appending to a long list of tasks with timeouts) */
1150  if ((NULL == pending_timeout_head) ||
1151  (at.abs_value_us < pending_timeout_head->timeout.abs_value_us))
1152  {
1153  GNUNET_CONTAINER_DLL_insert (pending_timeout_head,
1154  pending_timeout_tail,
1155  t);
1156  }
1157  else
1158  {
1159  /* first move from heuristic start backwards to before start time */
1160  prev = pending_timeout_last;
1161  while ((NULL != prev) &&
1163  prev = prev->prev;
1164  /* now, move from heuristic start (or head of list) forward to insertion point */
1165  if (NULL == prev)
1166  pos = pending_timeout_head;
1167  else
1168  pos = prev->next;
1169  while ((NULL != pos) && (pos->timeout.abs_value_us <=
1170  t->timeout.abs_value_us))
1171  {
1172  prev = pos;
1173  pos = pos->next;
1174  }
1175  GNUNET_CONTAINER_DLL_insert_after (pending_timeout_head,
1176  pending_timeout_tail,
1177  prev,
1178  t);
1179  }
1180  /* finally, update heuristic insertion point to last insertion... */
1181  pending_timeout_last = t;
1183  "Adding task %p\n",
1184  t);
1185  return t;
1186 }
1187 
1188 
1200 struct GNUNET_SCHEDULER_Task *
1203  priority,
1205  void *task_cls)
1206 {
1209  priority,
1210  task,
1211  task_cls);
1212 }
1213 
1214 
1224 struct GNUNET_SCHEDULER_Task *
1227  void *task_cls)
1228 {
1230  prio,
1231  task,
1232  task_cls);
1233 }
1234 
1235 
1247 struct GNUNET_SCHEDULER_Task *
1250  void *task_cls)
1251 {
1254  task,
1255  task_cls);
1256 }
1257 
1258 
1270 struct GNUNET_SCHEDULER_Task *
1273  void *task_cls)
1274 {
1277  task,
1278  task_cls);
1279 }
1280 
1281 
1297 struct GNUNET_SCHEDULER_Task *
1299  void *task_cls)
1300 {
1301  struct GNUNET_SCHEDULER_Task *t;
1302 
1303  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1305  t->callback = task;
1306  t->callback_cls = task_cls;
1307  t->read_fd = -1;
1308  t->write_fd = -1;
1309 #if PROFILE_DELAYS
1310  t->start_time = GNUNET_TIME_absolute_get ();
1311 #endif
1314  t->on_shutdown = GNUNET_YES;
1316  queue_ready_task (t);
1317  init_backtrace (t);
1318  return t;
1319 }
1320 
1321 
1332 struct GNUNET_SCHEDULER_Task *
1334  void *task_cls)
1335 {
1336  struct GNUNET_SCHEDULER_Task *t;
1337 
1338  /* scheduler must be running */
1339  GNUNET_assert (NULL != scheduler_driver);
1340  GNUNET_assert (NULL != task);
1341  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1343  t->callback = task;
1344  t->callback_cls = task_cls;
1345  t->read_fd = -1;
1346  t->write_fd = -1;
1347 #if PROFILE_DELAYS
1348  t->start_time = GNUNET_TIME_absolute_get ();
1349 #endif
1352  t->on_shutdown = GNUNET_YES;
1353  t->lifeness = GNUNET_NO;
1354  GNUNET_CONTAINER_DLL_insert (shutdown_head,
1355  shutdown_tail,
1356  t);
1358  "Adding shutdown task %p\n",
1359  t);
1360  init_backtrace (t);
1361  return t;
1362 }
1363 
1364 
1379 struct GNUNET_SCHEDULER_Task *
1382  void *task_cls)
1383 {
1384  struct GNUNET_SCHEDULER_Task *ret;
1385 
1386  ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1387  ret->lifeness = lifeness;
1388  return ret;
1389 }
1390 
1391 
1392 #if DEBUG_FDS
1393 
1399 void
1400 check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1401 {
1402  if (-1 != raw_fd)
1403  {
1404  int flags = fcntl (raw_fd, F_GETFD);
1405 
1406  if ((flags == -1) && (errno == EBADF))
1407  {
1409  "Got invalid file descriptor %d!\n",
1410  raw_fd);
1411  init_backtrace (t);
1412  GNUNET_assert (0);
1413  }
1414  }
1415 }
1416 
1417 
1418 #endif
1419 
1420 
1446 static struct GNUNET_SCHEDULER_Task *
1449  const struct GNUNET_NETWORK_Handle *read_nh,
1450  const struct GNUNET_NETWORK_Handle *write_nh,
1451  const struct GNUNET_DISK_FileHandle *read_fh,
1452  const struct GNUNET_DISK_FileHandle *write_fh,
1454  void *task_cls)
1455 {
1456  struct GNUNET_SCHEDULER_Task *t;
1457 
1458  /* scheduler must be running */
1459  GNUNET_assert (NULL != scheduler_driver);
1460  GNUNET_assert (NULL != task);
1461  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1463  init_fd_info (t,
1464  &read_nh,
1465  read_nh ? 1 : 0,
1466  &write_nh,
1467  write_nh ? 1 : 0,
1468  &read_fh,
1469  read_fh ? 1 : 0,
1470  &write_fh,
1471  write_fh ? 1 : 0);
1472  t->callback = task;
1473  t->callback_cls = task_cls;
1474 #if DEBUG_FDS
1475  check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1476  check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1477  check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1478  check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1479 #endif
1480 #if PROFILE_DELAYS
1481  t->start_time = GNUNET_TIME_absolute_get ();
1482 #endif
1485  current_priority : priority);
1487  GNUNET_CONTAINER_DLL_insert (pending_head,
1488  pending_tail,
1489  t);
1490  driver_add_multiple (t);
1492  t->priority);
1493  init_backtrace (t);
1494  return t;
1495 }
1496 
1497 
1518 struct GNUNET_SCHEDULER_Task *
1520  struct GNUNET_NETWORK_Handle *rfd,
1522  void *task_cls)
1523 {
1526  rfd, task, task_cls);
1527 }
1528 
1529 
1552 struct GNUNET_SCHEDULER_Task *
1555  priority,
1556  struct GNUNET_NETWORK_Handle *rfd,
1558  void *task_cls)
1559 {
1560  return GNUNET_SCHEDULER_add_net_with_priority (delay, priority,
1561  rfd,
1562  GNUNET_YES,
1563  GNUNET_NO,
1564  task, task_cls);
1565 }
1566 
1567 
1589 struct GNUNET_SCHEDULER_Task *
1591  struct GNUNET_NETWORK_Handle *wfd,
1593  void *task_cls)
1594 {
1597  wfd,
1599  task, task_cls);
1600 }
1601 
1602 
1626 struct GNUNET_SCHEDULER_Task *
1629  struct GNUNET_NETWORK_Handle *fd,
1630  int on_read,
1631  int on_write,
1633  void *task_cls)
1634 {
1635  /* scheduler must be running */
1636  GNUNET_assert (NULL != scheduler_driver);
1637  GNUNET_assert (on_read || on_write);
1639  return add_without_sets (delay, priority,
1640  on_read ? fd : NULL,
1641  on_write ? fd : NULL,
1642  NULL,
1643  NULL,
1644  task, task_cls);
1645 }
1646 
1647 
1668 struct GNUNET_SCHEDULER_Task *
1670  const struct GNUNET_DISK_FileHandle *rfd,
1672  void *task_cls)
1673 {
1676  rfd, GNUNET_YES, GNUNET_NO,
1677  task, task_cls);
1678 }
1679 
1680 
1701 struct GNUNET_SCHEDULER_Task *
1703  const struct GNUNET_DISK_FileHandle *wfd,
1705  void *task_cls)
1706 {
1709  wfd, GNUNET_NO, GNUNET_YES,
1710  task, task_cls);
1711 }
1712 
1713 
1737 struct GNUNET_SCHEDULER_Task *
1740  priority,
1741  const struct
1743  int on_read, int on_write,
1745  void *task_cls)
1746 {
1747  /* scheduler must be running */
1748  GNUNET_assert (NULL != scheduler_driver);
1749  GNUNET_assert (on_read || on_write);
1750  GNUNET_assert (fd->fd >= 0);
1751  return add_without_sets (delay, priority,
1752  NULL,
1753  NULL,
1754  on_read ? fd : NULL,
1755  on_write ? fd : NULL,
1756  task, task_cls);
1757 }
1758 
1759 
1760 void
1762  const struct GNUNET_NETWORK_Handle ***ntarget,
1763  unsigned int *extracted_nhandles,
1764  const struct GNUNET_DISK_FileHandle ***ftarget,
1765  unsigned int *extracted_fhandles)
1766 {
1767  // FIXME: this implementation only works for unix, for WIN32 the file handles
1768  // in fdset must be handled separately
1769  const struct GNUNET_NETWORK_Handle **nhandles;
1770  const struct GNUNET_DISK_FileHandle **fhandles;
1771  unsigned int nhandles_len;
1772  unsigned int fhandles_len;
1773 
1774  nhandles = NULL;
1775  fhandles = NULL;
1776  nhandles_len = 0;
1777  fhandles_len = 0;
1778  for (int sock = 0; sock != fdset->nsds; ++sock)
1779  {
1780  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1781  {
1782  struct GNUNET_NETWORK_Handle *nhandle;
1783  struct GNUNET_DISK_FileHandle *fhandle;
1784 
1785  nhandle = GNUNET_NETWORK_socket_box_native (sock);
1786  if (NULL != nhandle)
1787  {
1788  GNUNET_array_append (nhandles, nhandles_len, nhandle);
1789  }
1790  else
1791  {
1792  fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1793  if (NULL != fhandle)
1794  {
1795  GNUNET_array_append (fhandles, fhandles_len, fhandle);
1796  }
1797  else
1798  {
1799  GNUNET_assert (0);
1800  }
1801  }
1802  }
1803  }
1804  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1805  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1806  *extracted_nhandles = nhandles_len;
1807  *extracted_fhandles = fhandles_len;
1808 }
1809 
1810 
1842 struct GNUNET_SCHEDULER_Task *
1844  struct GNUNET_TIME_Relative delay,
1845  const struct GNUNET_NETWORK_FDSet *rs,
1846  const struct GNUNET_NETWORK_FDSet *ws,
1848  void *task_cls)
1849 {
1850  struct GNUNET_SCHEDULER_Task *t;
1851  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1852  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1853  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1854  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1855  unsigned int read_nhandles_len = 0;
1856  unsigned int write_nhandles_len = 0;
1857  unsigned int read_fhandles_len = 0;
1858  unsigned int write_fhandles_len = 0;
1859 
1860  /* scheduler must be running */
1861  GNUNET_assert (NULL != scheduler_driver);
1862  GNUNET_assert (NULL != task);
1863  int no_rs = (NULL == rs);
1864  int no_ws = (NULL == ws);
1865  int empty_rs = (NULL != rs) && (0 == rs->nsds);
1866  int empty_ws = (NULL != ws) && (0 == ws->nsds);
1867  int no_fds = (no_rs && no_ws) ||
1868  (empty_rs && empty_ws) ||
1869  (no_rs && empty_ws) ||
1870  (no_ws && empty_rs);
1871  if (! no_fds)
1872  {
1873  if (NULL != rs)
1874  {
1875  extract_handles (rs,
1876  &read_nhandles,
1877  &read_nhandles_len,
1878  &read_fhandles,
1879  &read_fhandles_len);
1880  }
1881  if (NULL != ws)
1882  {
1883  extract_handles (ws,
1884  &write_nhandles,
1885  &write_nhandles_len,
1886  &write_fhandles,
1887  &write_fhandles_len);
1888  }
1889  }int no_fds_extracted = (0 == read_nhandles_len) &&
1897  (0 == read_fhandles_len) &&
1898  (0 == write_nhandles_len) &&
1899  (0 == write_fhandles_len);
1900  if (no_fds || no_fds_extracted)
1902  prio,
1903  task,
1904  task_cls);
1905  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1907  init_fd_info (t,
1908  read_nhandles,
1909  read_nhandles_len,
1910  write_nhandles,
1911  write_nhandles_len,
1912  read_fhandles,
1913  read_fhandles_len,
1914  write_fhandles,
1915  write_fhandles_len);
1916  t->callback = task;
1917  t->callback_cls = task_cls;
1918  t->own_handles = GNUNET_YES;
1919  /* free the arrays of pointers to network / file handles, the actual
1920  * handles will be freed in destroy_task */
1921  GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1922  GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1923  GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1924  GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1925 #if PROFILE_DELAYS
1926  t->start_time = GNUNET_TIME_absolute_get ();
1927 #endif
1929  t->priority =
1930  check_priority ((prio ==
1932  prio);
1934  GNUNET_CONTAINER_DLL_insert (pending_head,
1935  pending_tail,
1936  t);
1937  driver_add_multiple (t);
1939  t->priority);
1941  "Adding task %p\n",
1942  t);
1943  init_backtrace (t);
1944  return t;
1945 }
1946 
1947 
1959 void
1961  struct GNUNET_SCHEDULER_FdInfo *fdi)
1962 {
1963  enum GNUNET_SCHEDULER_Reason reason;
1964 
1965  reason = task->reason;
1966  if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1967  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1969  if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1970  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1973  task->reason = reason;
1974  if (GNUNET_NO == task->in_ready_list)
1975  {
1976  GNUNET_CONTAINER_DLL_remove (pending_head,
1977  pending_tail,
1978  task);
1979  queue_ready_task (task);
1980  }
1981 }
1982 
1983 
2004 int
2006 {
2007  struct GNUNET_SCHEDULER_Task *pos;
2008  struct GNUNET_TIME_Absolute now;
2009 
2010  /* check for tasks that reached the timeout! */
2011  now = GNUNET_TIME_absolute_get ();
2012  pos = pending_timeout_head;
2013  while (NULL != pos)
2014  {
2015  struct GNUNET_SCHEDULER_Task *next = pos->next;
2016  if (now.abs_value_us >= pos->timeout.abs_value_us)
2018  if (0 == pos->reason)
2019  break;
2020  GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
2021  pending_timeout_tail,
2022  pos);
2023  if (pending_timeout_last == pos)
2024  pending_timeout_last = NULL;
2025  queue_ready_task (pos);
2026  pos = next;
2027  }
2028  pos = pending_head;
2029  while (NULL != pos)
2030  {
2031  struct GNUNET_SCHEDULER_Task *next = pos->next;
2032  if (now.abs_value_us >= pos->timeout.abs_value_us)
2033  {
2035  GNUNET_CONTAINER_DLL_remove (pending_head,
2036  pending_tail,
2037  pos);
2038  queue_ready_task (pos);
2039  }
2040  pos = next;
2041  }
2042 
2043  if (0 == ready_count)
2044  {
2045  struct GNUNET_TIME_Absolute timeout = get_timeout ();
2046 
2047  if (timeout.abs_value_us > now.abs_value_us)
2062  "GNUNET_SCHEDULER_do_work did not find any ready "
2063  "tasks and timeout has not been reached yet.\n");
2064  }
2065  else
2066  {
2071  GNUNET_assert (0);
2072  }
2073  }
2074  else
2075  {
2076  /* find out which task priority level we are going to
2077  process this time */
2079  GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]);
2080  /* yes, p>0 is correct, 0 is "KEEP" which should
2081  * always be an empty queue (see assertion)! */
2083  work_priority > 0;
2084  work_priority--)
2085  {
2086  pos = ready_head[work_priority];
2087  if (NULL != pos)
2088  break;
2089  }
2090  GNUNET_assert (NULL != pos); /* ready_count wrong? */
2091 
2092  /* process all tasks at this priority level, then yield */
2093  while (NULL != (pos = ready_head[work_priority]))
2094  {
2095  GNUNET_CONTAINER_DLL_remove (ready_head[work_priority],
2096  ready_tail[work_priority],
2097  pos);
2098  ready_count--;
2099  current_priority = pos->priority;
2100  current_lifeness = pos->lifeness;
2101  active_task = pos;
2102 #if PROFILE_DELAYS
2103  if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2104  DELAY_THRESHOLD.rel_value_us)
2105  {
2107  "Task %p took %s to be scheduled\n",
2108  pos,
2110  GNUNET_TIME_absolute_get_duration (pos->start_time),
2111  GNUNET_YES));
2112  }
2113 #endif
2114  tc.reason = pos->reason;
2117  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2118  tc.fds_len = pos->fds_len;
2119  tc.fds = pos->fds;
2120  for (unsigned int i = 0; i != pos->fds_len; ++i)
2121  {
2122  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2123  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2124  {
2126  fdi->sock);
2127  }
2128  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2129  {
2131  fdi->sock);
2132  }
2133  }
2134  tc.read_ready = sh->rs;
2135  tc.write_ready = sh->ws;
2137  "Running task %p\n",
2138  pos);
2139  GNUNET_assert (NULL != pos->callback);
2140  {
2141  struct GNUNET_AsyncScopeSave old_scope;
2142  if (pos->scope.have_scope)
2143  GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2144  else
2145  GNUNET_async_scope_get (&old_scope);
2146  pos->callback (pos->callback_cls);
2147  GNUNET_async_scope_restore (&old_scope);
2148  }
2149  if (NULL != pos->fds)
2150  {
2151  int del_result = scheduler_driver->del (scheduler_driver->cls, pos);
2152  if (GNUNET_OK != del_result)
2153  {
2155  "driver could not delete task %p\n", pos);
2156  GNUNET_assert (0);
2157  }
2158  }
2159  active_task = NULL;
2160  dump_backtrace (pos);
2161  destroy_task (pos);
2162  }
2163  }
2165  if (0 == ready_count)
2166  {
2167  scheduler_driver->set_wakeup (scheduler_driver->cls,
2168  get_timeout ());
2169  return GNUNET_NO;
2170  }
2171  scheduler_driver->set_wakeup (scheduler_driver->cls,
2173  return GNUNET_YES;
2174 }
2175 
2176 
2208 struct GNUNET_SCHEDULER_Handle *
2210 {
2211  struct GNUNET_SCHEDULER_Handle *sh;
2212  const struct GNUNET_DISK_FileHandle *pr;
2213 
2214  /* scheduler must not be running */
2215  GNUNET_assert (NULL == scheduler_driver);
2216  GNUNET_assert (NULL == shutdown_pipe_handle);
2217  /* general set-up */
2218  sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle);
2219  shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO,
2220  GNUNET_NO,
2221  GNUNET_NO,
2222  GNUNET_NO);
2223  GNUNET_assert (NULL != shutdown_pipe_handle);
2224  pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
2226  my_pid = getpid ();
2227  scheduler_driver = driver;
2228 
2229  /* install signal handlers */
2231  "Registering signal handlers\n");
2232  sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2234  sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2236 #if (SIGTERM != GNUNET_TERM_SIG)
2239 #endif
2240  sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2241  &sighandler_pipe);
2242  sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2244  sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2246 
2247  /* Setup initial tasks */
2250  /* ensure this task runs first, by using a priority level reserved for
2251  the scheduler (not really shutdown, but start-up ;-) */
2252  install_parent_control_task =
2255  NULL);
2256  shutdown_pipe_task =
2258  pr,
2260  NULL);
2262  scheduler_driver->set_wakeup (scheduler_driver->cls,
2263  get_timeout ());
2264  /* begin main event loop */
2268  return sh;
2269 }
2270 
2271 
2286 void
2288 {
2289  GNUNET_assert (NULL == pending_head);
2290  GNUNET_assert (NULL == pending_timeout_head);
2291  GNUNET_assert (NULL == shutdown_head);
2292  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2293  {
2294  GNUNET_assert (NULL == ready_head[i]);
2295  }
2298 
2299  /* uninstall signal handlers */
2302 #if (SIGTERM != GNUNET_TERM_SIG)
2303  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
2304 #endif
2308  GNUNET_DISK_pipe_close (shutdown_pipe_handle);
2309  shutdown_pipe_handle = NULL;
2310  scheduler_driver = NULL;
2311  GNUNET_free (sh);
2312 }
2313 
2314 
2315 static int
2317  struct DriverContext *context)
2318 {
2319  struct GNUNET_NETWORK_FDSet *rs;
2320  struct GNUNET_NETWORK_FDSet *ws;
2321  int select_result;
2322 
2323  GNUNET_assert (NULL != context);
2326  while ((NULL != context->scheduled_head) ||
2327  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us !=
2328  context->timeout.abs_value_us))
2329  {
2330  struct GNUNET_TIME_Relative time_remaining;
2331 
2333  "select timeout = %s\n",
2335 
2338 
2339  for (struct Scheduled *pos = context->scheduled_head;
2340  NULL != pos;
2341  pos = pos->next)
2342  {
2343  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2344  {
2345  GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2346  }
2347  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2348  {
2349  GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2350  }
2351  }
2352  time_remaining = GNUNET_TIME_absolute_get_remaining (context->timeout);
2353  if (0 < ready_count)
2354  time_remaining = GNUNET_TIME_UNIT_ZERO;
2355  if (NULL == scheduler_select)
2356  {
2357  select_result = GNUNET_NETWORK_socket_select (rs,
2358  ws,
2359  NULL,
2360  time_remaining);
2361  }
2362  else
2363  {
2364  select_result = scheduler_select (scheduler_select_cls,
2365  rs,
2366  ws,
2367  NULL,
2368  time_remaining);
2369  }
2370  if (select_result == GNUNET_SYSERR)
2371  {
2372  if (errno == EINTR)
2373  continue;
2374 
2376  "select");
2377 #if USE_LSOF
2378  char lsof[512];
2379 
2380  snprintf (lsof,
2381  sizeof(lsof),
2382  "lsof -p %d",
2383  getpid ());
2384  (void) close (1);
2385  (void) dup2 (2, 1);
2386  if (0 != system (lsof))
2388  "system");
2389 #endif
2390 #if DEBUG_FDS
2391  for (struct Scheduled *s = context->scheduled_head;
2392  NULL != s;
2393  s = s->next)
2394  {
2395  int flags = fcntl (s->fdi->sock,
2396  F_GETFD);
2397 
2398  if ((flags == -1) &&
2399  (EBADF == errno))
2400  {
2402  "Got invalid file descriptor %d!\n",
2403  s->fdi->sock);
2404 #if EXECINFO
2405  dump_backtrace (s->task);
2406 #endif
2407  }
2408  }
2409 #endif
2410  GNUNET_assert (0);
2413  return GNUNET_SYSERR;
2414  }
2415  if (select_result > 0)
2416  {
2417  for (struct Scheduled *pos = context->scheduled_head;
2418  NULL != pos;
2419  pos = pos->next)
2420  {
2421  int is_ready = GNUNET_NO;
2422 
2423  if ((0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) &&
2424  (GNUNET_YES ==
2426  pos->fdi->sock)) )
2427  {
2428  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2429  is_ready = GNUNET_YES;
2430  }
2431  if ((0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) &&
2432  (GNUNET_YES ==
2434  pos->fdi->sock)) )
2435  {
2436  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2437  is_ready = GNUNET_YES;
2438  }
2439  if (GNUNET_YES == is_ready)
2440  {
2441  GNUNET_SCHEDULER_task_ready (pos->task,
2442  pos->fdi);
2443  }
2444  }
2445  }
2447  {
2449  "scheduler has more tasks ready!\n");
2450  }
2451  }
2454  return GNUNET_OK;
2455 }
2456 
2457 
2458 static int
2459 select_add (void *cls,
2460  struct GNUNET_SCHEDULER_Task *task,
2461  struct GNUNET_SCHEDULER_FdInfo *fdi)
2462 {
2463  struct DriverContext *context = cls;
2464 
2465  GNUNET_assert (NULL != context);
2466  GNUNET_assert (NULL != task);
2467  GNUNET_assert (NULL != fdi);
2468  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2469  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2470 
2471  if (! ((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2472  {
2473  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2474  return GNUNET_SYSERR;
2475  }
2476 
2477  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2478  scheduled->task = task;
2479  scheduled->fdi = fdi;
2480  scheduled->et = fdi->et;
2481 
2483  context->scheduled_tail,
2484  scheduled);
2485  return GNUNET_OK;
2486 }
2487 
2488 
2489 static int
2490 select_del (void *cls,
2491  struct GNUNET_SCHEDULER_Task *task)
2492 {
2493  struct DriverContext *context;
2494  struct Scheduled *pos;
2495  int ret;
2496 
2497  GNUNET_assert (NULL != cls);
2498 
2499  context = cls;
2500  ret = GNUNET_SYSERR;
2501  pos = context->scheduled_head;
2502  while (NULL != pos)
2503  {
2504  struct Scheduled *next = pos->next;
2505  if (pos->task == task)
2506  {
2508  context->scheduled_tail,
2509  pos);
2510  GNUNET_free (pos);
2511  ret = GNUNET_OK;
2512  }
2513  pos = next;
2514  }
2515  return ret;
2516 }
2517 
2518 
2519 static void
2521  struct GNUNET_TIME_Absolute dt)
2522 {
2523  struct DriverContext *context = cls;
2524 
2525  GNUNET_assert (NULL != context);
2526  context->timeout = dt;
2527 }
2528 
2529 
2535 struct GNUNET_SCHEDULER_Driver *
2537 {
2538  struct GNUNET_SCHEDULER_Driver *select_driver;
2539 
2540  select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2541 
2542  select_driver->add = &select_add;
2543  select_driver->del = &select_del;
2544  select_driver->set_wakeup = &select_set_wakeup;
2545 
2546  return select_driver;
2547 }
2548 
2549 
2562 void
2564 {
2565  struct GNUNET_AsyncScopeSave dummy_old_scope;
2566 
2567  GNUNET_assert (NULL != active_task);
2568  /* Since we're in a task, the context will be automatically
2569  restored by the scheduler. */
2570  GNUNET_async_scope_enter (aid, &dummy_old_scope);
2571 }
2572 
2573 
2574 /* 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:754
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:1112
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
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
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:930
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:1201
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:1333
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:418
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition: scheduler.c:1040
static void sighandler_shutdown()
Wait for a short time.
Definition: scheduler.c:666
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:423
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:2209
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:632
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:1590
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:722
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:626
#define GNUNET_NO
Definition: gnunet_common.h:86
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:1702
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:1669
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:83
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
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:1738
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:531
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:1761
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:1553
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:1752
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:2536
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:1068
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:1380
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:2490
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition: scheduler.c:2520
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:1271
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:439
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:1225
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:90
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:1298
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:690
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:1843
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:908
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:1447
#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:2459
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:1525
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:2316
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:84
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:512
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.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
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:585
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:2005
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1714
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 enum GNUNET_SCHEDULER_Priority work_priority
Priority used currently in GNUNET_SCHEDULER_do_work().
Definition: scheduler.c:412
static void sighandler_pipe()
Signal handler called for SIGPIPE.
Definition: scheduler.c:638
struct GNUNET_AsyncScopeId scope_id
Saved scope.
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:939
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1374
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:454
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:2563
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:790
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:2287
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:85
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:564
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:1519
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:1627
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:1960
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:745
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:1248
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:771
static void * scheduler_select_cls
Closure for scheduler_select.
Definition: scheduler.c:428
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:682
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:974