GNUnet  0.10.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, "util-scheduler", syscall)
34 
35 
36 #if HAVE_EXECINFO_H
37 #include "execinfo.h"
38 
43 #define USE_LSOF GNUNET_NO
44 
48 #define EXECINFO GNUNET_NO
49 
53 #define DEBUG_FDS GNUNET_NO
54 
58 #define MAX_TRACE_DEPTH 50
59 #endif
60 
65 #define PROFILE_DELAYS GNUNET_NO
66 
71 #define DELAY_THRESHOLD GNUNET_TIME_UNIT_SECONDS
72 
73 
80 {
87 
94 
99 
104 
105 #if (SIGTERM != GNUNET_TERM_SIG)
106 
109  struct GNUNET_SIGNAL_Context *shc_gterm;
110 #endif
111 
112 #ifndef MINGW
113 
117 
122 
127 #endif
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 
251 
255 struct Scheduled
256 {
257  struct Scheduled *prev;
258 
259  struct Scheduled *next;
260 
265 
271 
277 };
278 
279 
284 {
290 
296 
302 };
303 
304 
313 
318 
323 
328 
333 
342 
351 
357 
362 
367 
372 
379 
385 
389 static unsigned int ready_count;
390 
396 
402 
406 static int current_lifeness;
407 
413 
418 
422 static void *scheduler_select_cls;
423 
424 
432 void
434  void *new_select_cls)
435 {
436  scheduler_select = new_select;
437  scheduler_select_cls = new_select_cls;
438 }
439 
440 
447 static enum GNUNET_SCHEDULER_Priority
449 {
450  if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
451  return p;
452  GNUNET_assert (0);
453  return 0; /* make compiler happy */
454 }
455 
456 
464 {
465  struct GNUNET_SCHEDULER_Task *pos;
466  struct GNUNET_TIME_Absolute now;
467  struct GNUNET_TIME_Absolute timeout;
468 
469  pos = pending_timeout_head;
470  now = GNUNET_TIME_absolute_get ();
472  if (NULL != pos)
473  {
474  if (0 != pos->reason)
475  {
476  return now;
477  }
478  else
479  {
480  timeout = pos->timeout;
481  }
482  }
483  for (pos = pending_head; NULL != pos; pos = pos->next)
484  {
485  if (0 != pos->reason)
486  {
487  return now;
488  }
489  else if ((pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
490  (timeout.abs_value_us > pos->timeout.abs_value_us))
491  {
492  timeout = pos->timeout;
493  }
494  }
495  return timeout;
496 }
497 
498 
504 static void
506 {
508 
509  GNUNET_CONTAINER_DLL_insert (ready_head[p],
510  ready_tail[p],
511  task);
512  task->in_ready_list = GNUNET_YES;
513  ready_count++;
514 }
515 
516 
523 void
525 {
526  struct GNUNET_SCHEDULER_Task *pos;
527 
529  "GNUNET_SCHEDULER_shutdown\n");
530  if (NULL != install_parent_control_task)
531  {
532  GNUNET_SCHEDULER_cancel (install_parent_control_task);
533  install_parent_control_task = NULL;
534  }
535  if (NULL != shutdown_pipe_task)
536  {
537  GNUNET_SCHEDULER_cancel (shutdown_pipe_task);
538  shutdown_pipe_task = NULL;
539  }
540  while (NULL != (pos = shutdown_head))
541  {
542  GNUNET_CONTAINER_DLL_remove (shutdown_head,
543  shutdown_tail,
544  pos);
546  queue_ready_task (pos);
547  }
548 }
549 
550 
556 static void
558 {
559 #if EXECINFO
560  for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
562  "Task %p trace %u: %s\n",
563  t,
564  i,
565  t->backtrace_strings[i]);
566 #else
567  (void) t;
568 #endif
569 }
570 
571 
577 static void
579 {
580  unsigned int i;
581 
583  "destroying task %p\n",
584  t);
585 
586  if (GNUNET_YES == t->own_handles)
587  {
588  for (i = 0; i != t->fds_len; ++i)
589  {
590  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
591  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
592  if (fd)
593  {
595  }
596  if (fh)
597  {
598  // FIXME: on WIN32 this is not enough! A function
599  // GNUNET_DISK_file_free_memory_only would be nice
600  GNUNET_free ((void *) fh);
601  }
602  }
603  }
604  if (t->fds_len > 1)
605  {
606  GNUNET_array_grow (t->fds, t->fds_len, 0);
607  }
608 #if EXECINFO
609  GNUNET_free (t->backtrace_strings);
610 #endif
611  GNUNET_free (t);
612 }
613 
614 
619 
624 static pid_t my_pid;
625 
629 #ifndef MINGW
630 static void
632 {
633  return;
634 }
635 #endif
636 
637 
639 // * Wait for a short time.
640 // * Sleeps for @a ms ms (as that should be long enough for virtually all
641 // * modern systems to context switch and allow another process to do
642 // * some 'real' work).
643 // *
644 // * @param ms how many ms to wait
645 // */
646 //static void
647 //short_wait (unsigned int ms)
648 //{
649 // struct GNUNET_TIME_Relative timeout;
650 //
651 // timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms);
652 // (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
653 //}
654 
655 
659 static void
661 {
662  static char c;
663  int old_errno = errno; /* backup errno */
664 
665  if (getpid () != my_pid)
666  _exit (1); /* we have fork'ed since the signal handler was created,
667  * ignore the signal, see https://gnunet.org/vfork discussion */
669  (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE),
670  &c, sizeof (c));
671  errno = old_errno;
672 }
673 
674 
675 static void
677 {
678  struct GNUNET_SCHEDULER_Task *t;
679 
680  if (ready_count > 0)
681  return;
682  for (t = pending_head; NULL != t; t = t->next)
683  if (GNUNET_YES == t->lifeness)
684  return;
685  for (t = shutdown_head; NULL != t; t = t->next)
686  if (GNUNET_YES == t->lifeness)
687  return;
688  for (t = pending_timeout_head; NULL != t; t = t->next)
689  if (GNUNET_YES == t->lifeness)
690  return;
691  /* No lifeness! */
693 }
694 
695 
696 static int
698  struct DriverContext *context);
699 
700 
715 void
717  void *task_cls)
718 {
719  struct GNUNET_SCHEDULER_Handle *sh;
720  struct GNUNET_SCHEDULER_Driver *driver;
721  struct DriverContext context = {.scheduled_head = NULL,
722  .scheduled_tail = NULL,
723  .timeout = GNUNET_TIME_absolute_get ()};
724 
725  driver = GNUNET_SCHEDULER_driver_select ();
726  driver->cls = &context;
727  sh = GNUNET_SCHEDULER_driver_init (driver);
729  task_cls,
732  select_loop (sh,
733  &context);
735  GNUNET_free (driver);
736 }
737 
738 
745 const struct GNUNET_SCHEDULER_TaskContext *
747 {
748  GNUNET_assert (NULL != active_task);
749  return &tc;
750 }
751 
752 
762 unsigned int
764 {
765  struct GNUNET_SCHEDULER_Task *pos;
766  unsigned int ret;
767 
768  GNUNET_assert (NULL != active_task);
770  return ready_count;
772  p = current_priority;
773  ret = 0;
774  for (pos = ready_head[check_priority (p)]; NULL != pos; pos = pos->next)
775  ret++;
776  return ret;
777 }
778 
779 
780 void
782  const struct GNUNET_NETWORK_Handle *const *read_nh,
783  unsigned int read_nh_len,
784  const struct GNUNET_NETWORK_Handle *const *write_nh,
785  unsigned int write_nh_len,
786  const struct GNUNET_DISK_FileHandle *const *read_fh,
787  unsigned int read_fh_len,
788  const struct GNUNET_DISK_FileHandle *const *write_fh,
789  unsigned int write_fh_len)
790 {
791  // FIXME: if we have exactly two network handles / exactly two file handles
792  // and they are equal, we can make one FdInfo with both
793  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
794  struct GNUNET_SCHEDULER_FdInfo *fdi;
795 
796  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
797  if (1 == t->fds_len)
798  {
799  fdi = &t->fdx;
800  t->fds = fdi;
801  if (1 == read_nh_len)
802  {
803  GNUNET_assert (NULL != read_nh);
804  GNUNET_assert (NULL != *read_nh);
805  fdi->fd = *read_nh;
806  fdi->et = GNUNET_SCHEDULER_ET_IN;
807  fdi->sock = GNUNET_NETWORK_get_fd (*read_nh);
808  t->read_fd = fdi->sock;
809  t->write_fd = -1;
810  }
811  else if (1 == write_nh_len)
812  {
813  GNUNET_assert (NULL != write_nh);
814  GNUNET_assert (NULL != *write_nh);
815  fdi->fd = *write_nh;
817  fdi->sock = GNUNET_NETWORK_get_fd (*write_nh);
818  t->read_fd = -1;
819  t->write_fd = fdi->sock;
820  }
821  else if (1 == read_fh_len)
822  {
823  GNUNET_assert (NULL != read_fh);
824  GNUNET_assert (NULL != *read_fh);
825  fdi->fh = *read_fh;
826  fdi->et = GNUNET_SCHEDULER_ET_IN;
827  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
828  t->read_fd = fdi->sock;
829  t->write_fd = -1;
830  }
831  else
832  {
833  GNUNET_assert (NULL != write_fh);
834  GNUNET_assert (NULL != *write_fh);
835  fdi->fh = *write_fh;
837  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
838  t->read_fd = -1;
839  t->write_fd = fdi->sock;
840  }
841  }
842  else
843  {
845  t->fds = fdi;
846  t->read_fd = -1;
847  t->write_fd = -1;
848  unsigned int i;
849  for (i = 0; i != read_nh_len; ++i)
850  {
851  fdi->fd = read_nh[i];
852  GNUNET_assert (NULL != fdi->fd);
853  fdi->et = GNUNET_SCHEDULER_ET_IN;
854  fdi->sock = GNUNET_NETWORK_get_fd (read_nh[i]);
855  ++fdi;
856  }
857  for (i = 0; i != write_nh_len; ++i)
858  {
859  fdi->fd = write_nh[i];
860  GNUNET_assert (NULL != fdi->fd);
862  fdi->sock = GNUNET_NETWORK_get_fd (write_nh[i]);
863  ++fdi;
864  }
865  for (i = 0; i != read_fh_len; ++i)
866  {
867  fdi->fh = read_fh[i];
868  GNUNET_assert (NULL != fdi->fh);
869  fdi->et = GNUNET_SCHEDULER_ET_IN;
870  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
871  ++fdi;
872  }
873  for (i = 0; i != write_fh_len; ++i)
874  {
875  fdi->fh = write_fh[i];
876  GNUNET_assert (NULL != fdi->fh);
878  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
879  ++fdi;
880  }
881  }
882 }
883 
884 
898 static void
900 {
901  struct GNUNET_SCHEDULER_FdInfo *fdi;
902  int success = GNUNET_YES;
903 
904  for (unsigned int i = 0; i != t->fds_len; ++i)
905  {
906  fdi = &t->fds[i];
907  success = scheduler_driver->add (scheduler_driver->cls,
908  t,
909  fdi) && success;
911  }
912  if (GNUNET_YES != success)
913  {
915  "driver could not add task\n");
916  }
917 }
918 
919 
920 static void
922 {
923  (void) cls;
924  install_parent_control_task = NULL;
926 }
927 
928 
929 static void
930 shutdown_pipe_cb (void *cls)
931 {
932  char c;
933  const struct GNUNET_DISK_FileHandle *pr;
934 
935  (void) cls;
936  shutdown_pipe_task = NULL;
937  pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
940  /* consume the signal */
941  GNUNET_DISK_file_read (pr, &c, sizeof (c));
942  /* mark all active tasks as ready due to shutdown */
944  shutdown_pipe_task =
946  pr,
948  NULL);
949 }
950 
951 
964 void *
966 {
968  int is_fd_task;
969  void *ret;
970 
972  "canceling task %p\n",
973  task);
974 
975  /* scheduler must be running */
976  GNUNET_assert (NULL != scheduler_driver);
977  is_fd_task = (NULL != task->fds);
978  if (is_fd_task)
979  {
980  int del_result = scheduler_driver->del (scheduler_driver->cls, task);
981  if (GNUNET_OK != del_result)
982  {
984  "driver could not delete task\n");
985  GNUNET_assert (0);
986  }
987  }
988  if (! task->in_ready_list)
989  {
990  if (is_fd_task)
991  {
992  GNUNET_CONTAINER_DLL_remove (pending_head,
993  pending_tail,
994  task);
995  }
996  else if (GNUNET_YES == task->on_shutdown)
997  {
998  GNUNET_CONTAINER_DLL_remove (shutdown_head,
999  shutdown_tail,
1000  task);
1001  }
1002  else
1003  {
1004  GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
1005  pending_timeout_tail,
1006  task);
1007  if (pending_timeout_last == task)
1008  pending_timeout_last = NULL;
1009  }
1010  }
1011  else
1012  {
1013  p = check_priority (task->priority);
1014  GNUNET_CONTAINER_DLL_remove (ready_head[p],
1015  ready_tail[p],
1016  task);
1017  ready_count--;
1018  }
1019  ret = task->callback_cls;
1020  destroy_task (task);
1021  return ret;
1022 }
1023 
1024 
1030 static void
1032 {
1033 #if EXECINFO
1034  void *backtrace_array[MAX_TRACE_DEPTH];
1035 
1036  t->num_backtrace_strings
1037  = backtrace (backtrace_array, MAX_TRACE_DEPTH);
1038  t->backtrace_strings =
1039  backtrace_symbols (backtrace_array,
1040  t->num_backtrace_strings);
1041  dump_backtrace (t);
1042 #else
1043  (void) t;
1044 #endif
1045 }
1046 
1047 
1058 void
1060  void *task_cls,
1061  enum GNUNET_SCHEDULER_Reason reason,
1062  enum GNUNET_SCHEDULER_Priority priority)
1063 {
1064  struct GNUNET_SCHEDULER_Task *t;
1065 
1066  /* scheduler must be running */
1067  GNUNET_assert (NULL != scheduler_driver);
1068  GNUNET_assert (NULL != task);
1069  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1070  t->read_fd = -1;
1071  t->write_fd = -1;
1072  t->callback = task;
1073  t->callback_cls = task_cls;
1074 #if PROFILE_DELAYS
1075  t->start_time = GNUNET_TIME_absolute_get ();
1076 #endif
1077  t->reason = reason;
1078  t->priority = check_priority (priority);
1081  "Adding continuation task %p\n",
1082  t);
1083  init_backtrace (t);
1084  queue_ready_task (t);
1085 }
1086 
1087 
1099 struct GNUNET_SCHEDULER_Task *
1103  void *task_cls)
1104 {
1105  struct GNUNET_SCHEDULER_Task *t;
1106  struct GNUNET_SCHEDULER_Task *pos;
1107  struct GNUNET_SCHEDULER_Task *prev;
1108 
1109  /* scheduler must be running */
1110  GNUNET_assert (NULL != scheduler_driver);
1111  GNUNET_assert (NULL != task);
1112  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1114  t->callback = task;
1115  t->callback_cls = task_cls;
1116  t->read_fd = -1;
1117  t->write_fd = -1;
1118 #if PROFILE_DELAYS
1119  t->start_time = GNUNET_TIME_absolute_get ();
1120 #endif
1121  t->timeout = at;
1122  t->priority = check_priority (priority);
1124  /* try tail first (optimization in case we are
1125  * appending to a long list of tasks with timeouts) */
1126  if ( (NULL == pending_timeout_head) ||
1127  (at.abs_value_us < pending_timeout_head->timeout.abs_value_us) )
1128  {
1129  GNUNET_CONTAINER_DLL_insert (pending_timeout_head,
1130  pending_timeout_tail,
1131  t);
1132  }
1133  else
1134  {
1135  /* first move from heuristic start backwards to before start time */
1136  prev = pending_timeout_last;
1137  while ( (NULL != prev) &&
1138  (prev->timeout.abs_value_us > t->timeout.abs_value_us) )
1139  prev = prev->prev;
1140  /* now, move from heuristic start (or head of list) forward to insertion point */
1141  if (NULL == prev)
1142  pos = pending_timeout_head;
1143  else
1144  pos = prev->next;
1145  while ((NULL != pos) && (pos->timeout.abs_value_us <= t->timeout.abs_value_us))
1146  {
1147  prev = pos;
1148  pos = pos->next;
1149  }
1150  GNUNET_CONTAINER_DLL_insert_after (pending_timeout_head,
1151  pending_timeout_tail,
1152  prev,
1153  t);
1154  }
1155  /* finally, update heuristic insertion point to last insertion... */
1156  pending_timeout_last = t;
1157 
1159  "Adding task %p\n",
1160  t);
1161  init_backtrace (t);
1162  return t;
1163 }
1164 
1165 
1177 struct GNUNET_SCHEDULER_Task *
1181  void *task_cls)
1182 {
1184  priority,
1185  task,
1186  task_cls);
1187 }
1188 
1189 
1199 struct GNUNET_SCHEDULER_Task *
1202  void *task_cls)
1203 {
1205  prio,
1206  task,
1207  task_cls);
1208 }
1209 
1210 
1222 struct GNUNET_SCHEDULER_Task *
1225  void *task_cls)
1226 {
1229  task,
1230  task_cls);
1231 }
1232 
1233 
1245 struct GNUNET_SCHEDULER_Task *
1248  void *task_cls)
1249 {
1252  task,
1253  task_cls);
1254 }
1255 
1256 
1272 struct GNUNET_SCHEDULER_Task *
1274  void *task_cls)
1275 {
1277  task,
1278  task_cls);
1279 }
1280 
1281 
1292 struct GNUNET_SCHEDULER_Task *
1294  void *task_cls)
1295 {
1296  struct GNUNET_SCHEDULER_Task *t;
1297 
1298  /* scheduler must be running */
1299  GNUNET_assert (NULL != scheduler_driver);
1300  GNUNET_assert (NULL != task);
1301  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1303  t->callback = task;
1304  t->callback_cls = task_cls;
1305  t->read_fd = -1;
1306  t->write_fd = -1;
1307 #if PROFILE_DELAYS
1308  t->start_time = GNUNET_TIME_absolute_get ();
1309 #endif
1312  t->on_shutdown = GNUNET_YES;
1313  t->lifeness = GNUNET_NO;
1314  GNUNET_CONTAINER_DLL_insert (shutdown_head,
1315  shutdown_tail,
1316  t);
1318  "Adding shutdown task %p\n",
1319  t);
1320  init_backtrace (t);
1321  return t;
1322 }
1323 
1324 
1339 struct GNUNET_SCHEDULER_Task *
1342  void *task_cls)
1343 {
1344  struct GNUNET_SCHEDULER_Task *ret;
1345 
1346  ret = GNUNET_SCHEDULER_add_now (task, task_cls);
1347  ret->lifeness = lifeness;
1348  return ret;
1349 }
1350 
1351 
1352 #if DEBUG_FDS
1353 
1359 void
1360 check_fd (struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1361 {
1362  if (-1 != raw_fd)
1363  {
1364  int flags = fcntl (raw_fd, F_GETFD);
1365 
1366  if ((flags == -1) && (errno == EBADF))
1367  {
1369  "Got invalid file descriptor %d!\n",
1370  raw_fd);
1371  init_backtrace (t);
1372  GNUNET_assert (0);
1373  }
1374  }
1375 }
1376 #endif
1377 
1378 
1404 #ifndef MINGW
1405 static struct GNUNET_SCHEDULER_Task *
1408  const struct GNUNET_NETWORK_Handle *read_nh,
1409  const struct GNUNET_NETWORK_Handle *write_nh,
1410  const struct GNUNET_DISK_FileHandle *read_fh,
1411  const struct GNUNET_DISK_FileHandle *write_fh,
1413  void *task_cls)
1414 {
1415  struct GNUNET_SCHEDULER_Task *t;
1416 
1417  /* scheduler must be running */
1418  GNUNET_assert (NULL != scheduler_driver);
1419  GNUNET_assert (NULL != task);
1420  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1422  init_fd_info (t,
1423  &read_nh,
1424  read_nh ? 1 : 0,
1425  &write_nh,
1426  write_nh ? 1 : 0,
1427  &read_fh,
1428  read_fh ? 1 : 0,
1429  &write_fh,
1430  write_fh ? 1 : 0);
1431  t->callback = task;
1432  t->callback_cls = task_cls;
1433 #if DEBUG_FDS
1434  check_fd (t, NULL != read_nh ? GNUNET_NETWORK_get_fd (read_nh) : -1);
1435  check_fd (t, NULL != write_nh ? GNUNET_NETWORK_get_fd (write_nh) : -1);
1436  check_fd (t, NULL != read_fh ? read_fh->fd : -1);
1437  check_fd (t, NULL != write_fh ? write_fh->fd : -1);
1438 #endif
1439 #if PROFILE_DELAYS
1440  t->start_time = GNUNET_TIME_absolute_get ();
1441 #endif
1443  t->priority = check_priority ((priority == GNUNET_SCHEDULER_PRIORITY_KEEP) ? current_priority : priority);
1445  GNUNET_CONTAINER_DLL_insert (pending_head,
1446  pending_tail,
1447  t);
1448  driver_add_multiple (t);
1450  t->priority);
1451  init_backtrace (t);
1452  return t;
1453 }
1454 #endif
1455 
1456 
1477 struct GNUNET_SCHEDULER_Task *
1479  struct GNUNET_NETWORK_Handle *rfd,
1481  void *task_cls)
1482 {
1485  rfd, task, task_cls);
1486 }
1487 
1488 
1511 struct GNUNET_SCHEDULER_Task *
1514  struct GNUNET_NETWORK_Handle *rfd,
1516  void *task_cls)
1517 {
1518  return GNUNET_SCHEDULER_add_net_with_priority (delay, priority,
1519  rfd,
1520  GNUNET_YES,
1521  GNUNET_NO,
1522  task, task_cls);
1523 }
1524 
1525 
1547 struct GNUNET_SCHEDULER_Task *
1549  struct GNUNET_NETWORK_Handle *wfd,
1551  void *task_cls)
1552 {
1555  wfd,
1557  task, task_cls);
1558 }
1559 
1583 struct GNUNET_SCHEDULER_Task *
1586  struct GNUNET_NETWORK_Handle *fd,
1587  int on_read,
1588  int on_write,
1590  void *task_cls)
1591 {
1592  /* scheduler must be running */
1593  GNUNET_assert (NULL != scheduler_driver);
1594 
1595 #if MINGW
1596  struct GNUNET_NETWORK_FDSet *s;
1597  struct GNUNET_SCHEDULER_Task * ret;
1598 
1599  GNUNET_assert (NULL != fd);
1601  GNUNET_NETWORK_fdset_set (s, fd);
1603  priority, delay,
1604  on_read ? s : NULL,
1605  on_write ? s : NULL,
1606  task, task_cls);
1608  return ret;
1609 #else
1610  GNUNET_assert (on_read || on_write);
1612  return add_without_sets (delay, priority,
1613  on_read ? fd : NULL,
1614  on_write ? fd : NULL,
1615  NULL,
1616  NULL,
1617  task, task_cls);
1618 #endif
1619 }
1620 
1621 
1642 struct GNUNET_SCHEDULER_Task *
1644  const struct GNUNET_DISK_FileHandle *rfd,
1645  GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
1646 {
1649  rfd, GNUNET_YES, GNUNET_NO,
1650  task, task_cls);
1651 }
1652 
1653 
1674 struct GNUNET_SCHEDULER_Task *
1676  const struct GNUNET_DISK_FileHandle *wfd,
1677  GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
1678 {
1681  wfd, GNUNET_NO, GNUNET_YES,
1682  task, task_cls);
1683 }
1684 
1685 
1709 struct GNUNET_SCHEDULER_Task *
1712  const struct GNUNET_DISK_FileHandle *fd,
1713  int on_read, int on_write,
1714  GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
1715 {
1716  /* scheduler must be running */
1717  GNUNET_assert (NULL != scheduler_driver);
1718 
1719 #if MINGW
1720  struct GNUNET_NETWORK_FDSet *s;
1721  struct GNUNET_SCHEDULER_Task * ret;
1722 
1723  GNUNET_assert (NULL != fd);
1727  priority, delay,
1728  on_read ? s : NULL,
1729  on_write ? s : NULL,
1730  task, task_cls);
1732  return ret;
1733 #else
1734  GNUNET_assert (on_read || on_write);
1735  GNUNET_assert (fd->fd >= 0);
1736  return add_without_sets (delay, priority,
1737  NULL,
1738  NULL,
1739  on_read ? fd : NULL,
1740  on_write ? fd : NULL,
1741  task, task_cls);
1742 #endif
1743 }
1744 
1745 
1746 void
1748  const struct GNUNET_NETWORK_Handle ***ntarget,
1749  unsigned int *extracted_nhandles,
1750  const struct GNUNET_DISK_FileHandle ***ftarget,
1751  unsigned int *extracted_fhandles)
1752 {
1753  // FIXME: this implementation only works for unix, for WIN32 the file handles
1754  // in fdset must be handled separately
1755  const struct GNUNET_NETWORK_Handle **nhandles;
1756  const struct GNUNET_DISK_FileHandle **fhandles;
1757  unsigned int nhandles_len;
1758  unsigned int fhandles_len;
1759 
1760  nhandles = NULL;
1761  fhandles = NULL;
1762  nhandles_len = 0;
1763  fhandles_len = 0;
1764  for (int sock = 0; sock != fdset->nsds; ++sock)
1765  {
1766  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (fdset, sock))
1767  {
1768  struct GNUNET_NETWORK_Handle *nhandle;
1769  struct GNUNET_DISK_FileHandle *fhandle;
1770 
1771  nhandle = GNUNET_NETWORK_socket_box_native (sock);
1772  if (NULL != nhandle)
1773  {
1774  GNUNET_array_append (nhandles, nhandles_len, nhandle);
1775  }
1776  else
1777  {
1778  fhandle = GNUNET_DISK_get_handle_from_int_fd (sock);
1779  if (NULL != fhandle)
1780  {
1781  GNUNET_array_append (fhandles, fhandles_len, fhandle);
1782  }
1783  else
1784  {
1785  GNUNET_assert (0);
1786  }
1787  }
1788  }
1789  }
1790  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1791  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1792  *extracted_nhandles = nhandles_len;
1793  *extracted_fhandles = fhandles_len;
1794 }
1795 
1796 
1828 struct GNUNET_SCHEDULER_Task *
1830  struct GNUNET_TIME_Relative delay,
1831  const struct GNUNET_NETWORK_FDSet *rs,
1832  const struct GNUNET_NETWORK_FDSet *ws,
1834  void *task_cls)
1835 {
1836  struct GNUNET_SCHEDULER_Task *t;
1837  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1838  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1839  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1840  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1841  unsigned int read_nhandles_len = 0;
1842  unsigned int write_nhandles_len = 0;
1843  unsigned int read_fhandles_len = 0;
1844  unsigned int write_fhandles_len = 0;
1845 
1846  /* scheduler must be running */
1847  GNUNET_assert (NULL != scheduler_driver);
1848  GNUNET_assert (NULL != task);
1849  int no_rs = (NULL == rs);
1850  int no_ws = (NULL == ws);
1851  int empty_rs = (NULL != rs) && (0 == rs->nsds);
1852  int empty_ws = (NULL != ws) && (0 == ws->nsds);
1853  int no_fds = (no_rs && no_ws) ||
1854  (empty_rs && empty_ws) ||
1855  (no_rs && empty_ws) ||
1856  (no_ws && empty_rs);
1857  if (! no_fds)
1858  {
1859  if (NULL != rs)
1860  {
1861  extract_handles (rs,
1862  &read_nhandles,
1863  &read_nhandles_len,
1864  &read_fhandles,
1865  &read_fhandles_len);
1866  }
1867  if (NULL != ws)
1868  {
1869  extract_handles (ws,
1870  &write_nhandles,
1871  &write_nhandles_len,
1872  &write_fhandles,
1873  &write_fhandles_len);
1874  }
1875  }
1883  int no_fds_extracted = (0 == read_nhandles_len) &&
1884  (0 == read_fhandles_len) &&
1885  (0 == write_nhandles_len) &&
1886  (0 == write_fhandles_len);
1887  if (no_fds || no_fds_extracted)
1889  prio,
1890  task,
1891  task_cls);
1892  t = GNUNET_new (struct GNUNET_SCHEDULER_Task);
1894  init_fd_info (t,
1895  read_nhandles,
1896  read_nhandles_len,
1897  write_nhandles,
1898  write_nhandles_len,
1899  read_fhandles,
1900  read_fhandles_len,
1901  write_fhandles,
1902  write_fhandles_len);
1903  t->callback = task;
1904  t->callback_cls = task_cls;
1905  t->own_handles = GNUNET_YES;
1906  /* free the arrays of pointers to network / file handles, the actual
1907  * handles will be freed in destroy_task */
1908  GNUNET_array_grow (read_nhandles, read_nhandles_len, 0);
1909  GNUNET_array_grow (write_nhandles, write_nhandles_len, 0);
1910  GNUNET_array_grow (read_fhandles, read_fhandles_len, 0);
1911  GNUNET_array_grow (write_fhandles, write_fhandles_len, 0);
1912 #if PROFILE_DELAYS
1913  t->start_time = GNUNET_TIME_absolute_get ();
1914 #endif
1916  t->priority =
1917  check_priority ((prio ==
1919  prio);
1921  GNUNET_CONTAINER_DLL_insert (pending_head,
1922  pending_tail,
1923  t);
1924  driver_add_multiple (t);
1926  t->priority);
1928  "Adding task %p\n",
1929  t);
1930  init_backtrace (t);
1931  return t;
1932 }
1933 
1934 
1946 void
1948  struct GNUNET_SCHEDULER_FdInfo *fdi)
1949 {
1950  enum GNUNET_SCHEDULER_Reason reason;
1951 
1952  reason = task->reason;
1953  if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1954  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) )
1956  if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1957  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) )
1960  task->reason = reason;
1961  if (GNUNET_NO == task->in_ready_list)
1962  {
1963  GNUNET_CONTAINER_DLL_remove (pending_head,
1964  pending_tail,
1965  task);
1966  queue_ready_task (task);
1967  }
1968 }
1969 
1970 
1991 int
1993 {
1995  struct GNUNET_SCHEDULER_Task *pos;
1996  struct GNUNET_TIME_Absolute now;
1997 
1998  /* check for tasks that reached the timeout! */
1999  now = GNUNET_TIME_absolute_get ();
2000  pos = pending_timeout_head;
2001  while (NULL != pos)
2002  {
2003  struct GNUNET_SCHEDULER_Task *next = pos->next;
2004  if (now.abs_value_us >= pos->timeout.abs_value_us)
2006  if (0 == pos->reason)
2007  break;
2008  GNUNET_CONTAINER_DLL_remove (pending_timeout_head,
2009  pending_timeout_tail,
2010  pos);
2011  if (pending_timeout_last == pos)
2012  pending_timeout_last = NULL;
2013  queue_ready_task (pos);
2014  pos = next;
2015  }
2016  pos = pending_head;
2017  while (NULL != pos)
2018  {
2019  struct GNUNET_SCHEDULER_Task *next = pos->next;
2020  if (now.abs_value_us >= pos->timeout.abs_value_us)
2021  {
2023  GNUNET_CONTAINER_DLL_remove (pending_head,
2024  pending_tail,
2025  pos);
2026  queue_ready_task (pos);
2027  }
2028  pos = next;
2029  }
2030 
2031  if (0 == ready_count)
2032  {
2033  struct GNUNET_TIME_Absolute timeout = get_timeout ();
2034 
2035  if (timeout.abs_value_us > now.abs_value_us)
2036  {
2051  "GNUNET_SCHEDULER_do_work did not find any ready "
2052  "tasks and timeout has not been reached yet.\n");
2053  }
2054  else
2055  {
2060  GNUNET_assert (0);
2061  }
2062  }
2063  else
2064  {
2065  /* find out which task priority level we are going to
2066  process this time */
2068  GNUNET_assert (NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]);
2069  /* yes, p>0 is correct, 0 is "KEEP" which should
2070  * always be an empty queue (see assertion)! */
2071  for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--)
2072  {
2073  pos = ready_head[p];
2074  if (NULL != pos)
2075  break;
2076  }
2077  GNUNET_assert (NULL != pos); /* ready_count wrong? */
2078 
2079  /* process all tasks at this priority level, then yield */
2080  while (NULL != (pos = ready_head[p]))
2081  {
2082  GNUNET_CONTAINER_DLL_remove (ready_head[p],
2083  ready_tail[p],
2084  pos);
2085  ready_count--;
2086  current_priority = pos->priority;
2087  current_lifeness = pos->lifeness;
2088  active_task = pos;
2089 #if PROFILE_DELAYS
2090  if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value_us >
2091  DELAY_THRESHOLD.rel_value_us)
2092  {
2094  "Task %p took %s to be scheduled\n",
2095  pos,
2097  GNUNET_YES));
2098  }
2099 #endif
2100  tc.reason = pos->reason;
2103  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2104  tc.fds_len = pos->fds_len;
2105  tc.fds = pos->fds;
2106  for (unsigned int i = 0; i != pos->fds_len; ++i)
2107  {
2108  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2109  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2110  {
2112  fdi->sock);
2113  }
2114  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2115  {
2117  fdi->sock);
2118  }
2119  }
2120  tc.read_ready = sh->rs;
2121  tc.write_ready = sh->ws;
2123  "Running task %p\n",
2124  pos);
2125  GNUNET_assert (NULL != pos->callback);
2126  {
2127  struct GNUNET_AsyncScopeSave old_scope;
2128  if (pos->scope.have_scope)
2129  GNUNET_async_scope_enter (&pos->scope.scope_id, &old_scope);
2130  else
2131  GNUNET_async_scope_get (&old_scope);
2132  pos->callback (pos->callback_cls);
2133  GNUNET_async_scope_restore (&old_scope);
2134  }
2135  if (NULL != pos->fds)
2136  {
2137  int del_result = scheduler_driver->del (scheduler_driver->cls, pos);
2138  if (GNUNET_OK != del_result)
2139  {
2141  "driver could not delete task %p\n", pos);
2142  GNUNET_assert (0);
2143  }
2144  }
2145  active_task = NULL;
2146  dump_backtrace (pos);
2147  destroy_task (pos);
2148  }
2149  }
2151  if (0 == ready_count)
2152  {
2153  scheduler_driver->set_wakeup (scheduler_driver->cls,
2154  get_timeout ());
2155  return GNUNET_NO;
2156  }
2157  scheduler_driver->set_wakeup (scheduler_driver->cls,
2159  return GNUNET_YES;
2160 }
2161 
2162 
2194 struct GNUNET_SCHEDULER_Handle *
2196 {
2197  struct GNUNET_SCHEDULER_Handle *sh;
2198  const struct GNUNET_DISK_FileHandle *pr;
2199 
2200  /* scheduler must not be running */
2201  GNUNET_assert (NULL == scheduler_driver);
2202  GNUNET_assert (NULL == shutdown_pipe_handle);
2203  /* general set-up */
2204  sh = GNUNET_new (struct GNUNET_SCHEDULER_Handle);
2205  shutdown_pipe_handle = GNUNET_DISK_pipe (GNUNET_NO,
2206  GNUNET_NO,
2207  GNUNET_NO,
2208  GNUNET_NO);
2209  GNUNET_assert (NULL != shutdown_pipe_handle);
2210  pr = GNUNET_DISK_pipe_handle (shutdown_pipe_handle,
2212  my_pid = getpid ();
2213  scheduler_driver = driver;
2214 
2215  /* install signal handlers */
2217  "Registering signal handlers\n");
2218  sh->shc_int = GNUNET_SIGNAL_handler_install (SIGINT,
2220  sh->shc_term = GNUNET_SIGNAL_handler_install (SIGTERM,
2222 #if (SIGTERM != GNUNET_TERM_SIG)
2225 #endif
2226 #ifndef MINGW
2227  sh->shc_pipe = GNUNET_SIGNAL_handler_install (SIGPIPE,
2228  &sighandler_pipe);
2229  sh->shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT,
2231  sh->shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP,
2233 #endif
2234 
2235  /* Setup initial tasks */
2238  install_parent_control_task =
2240  NULL);
2241  shutdown_pipe_task =
2243  pr,
2245  NULL);
2247  scheduler_driver->set_wakeup (scheduler_driver->cls,
2248  get_timeout ());
2249  /* begin main event loop */
2253  return sh;
2254 }
2255 
2256 
2271 void
2273 {
2274  GNUNET_assert (NULL == pending_head);
2275  GNUNET_assert (NULL == pending_timeout_head);
2276  GNUNET_assert (NULL == shutdown_head);
2277  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2278  {
2279  GNUNET_assert (NULL == ready_head[i]);
2280  }
2283 
2284  /* uninstall signal handlers */
2287 #if (SIGTERM != GNUNET_TERM_SIG)
2288  GNUNET_SIGNAL_handler_uninstall (sh->shc_gterm);
2289 #endif
2290 #ifndef MINGW
2294 #endif
2295  GNUNET_DISK_pipe_close (shutdown_pipe_handle);
2296  shutdown_pipe_handle = NULL;
2297  scheduler_driver = NULL;
2298  GNUNET_free (sh);
2299 }
2300 
2301 
2302 static int
2304  struct DriverContext *context)
2305 {
2306  struct GNUNET_NETWORK_FDSet *rs;
2307  struct GNUNET_NETWORK_FDSet *ws;
2308  int select_result;
2309 
2310  GNUNET_assert (NULL != context);
2313  while ( (NULL != context->scheduled_head) ||
2314  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != context->timeout.abs_value_us) )
2315  {
2317  "select timeout = %s\n",
2319 
2322 
2323  for (struct Scheduled *pos = context->scheduled_head;
2324  NULL != pos;
2325  pos = pos->next)
2326  {
2327  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2328  {
2329  GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock);
2330  }
2331  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2332  {
2333  GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock);
2334  }
2335  }
2336  struct GNUNET_TIME_Relative time_remaining =
2338  if (NULL == scheduler_select)
2339  {
2340  select_result = GNUNET_NETWORK_socket_select (rs,
2341  ws,
2342  NULL,
2343  time_remaining);
2344  }
2345  else
2346  {
2347  select_result = scheduler_select (scheduler_select_cls,
2348  rs,
2349  ws,
2350  NULL,
2351  time_remaining);
2352  }
2353  if (select_result == GNUNET_SYSERR)
2354  {
2355  if (errno == EINTR)
2356  continue;
2357 
2359  "select");
2360 #ifndef MINGW
2361 #if USE_LSOF
2362  char lsof[512];
2363 
2364  snprintf (lsof,
2365  sizeof (lsof),
2366  "lsof -p %d",
2367  getpid ());
2368  (void) close (1);
2369  (void) dup2 (2, 1);
2370  if (0 != system (lsof))
2372  "system");
2373 #endif
2374 #endif
2375 #if DEBUG_FDS
2376  for (struct Scheduled *s = context->scheduled_head;
2377  NULL != s;
2378  s = s->next)
2379  {
2380  int flags = fcntl (s->fdi->sock,
2381  F_GETFD);
2382 
2383  if ( (flags == -1) &&
2384  (EBADF == errno) )
2385  {
2387  "Got invalid file descriptor %d!\n",
2388  s->fdi->sock);
2389 #if EXECINFO
2390  dump_backtrace (s->task);
2391 #endif
2392  }
2393  }
2394 #endif
2395  GNUNET_assert (0);
2398  return GNUNET_SYSERR;
2399  }
2400  if (select_result > 0)
2401  {
2402  for (struct Scheduled *pos = context->scheduled_head;
2403  NULL != pos;
2404  pos = pos->next)
2405  {
2406  int is_ready = GNUNET_NO;
2407 
2408  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et) &&
2409  GNUNET_YES ==
2411  pos->fdi->sock))
2412  {
2413  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2414  is_ready = GNUNET_YES;
2415  }
2416  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et) &&
2417  GNUNET_YES ==
2419  pos->fdi->sock))
2420  {
2421  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2422  is_ready = GNUNET_YES;
2423  }
2424  if (GNUNET_YES == is_ready)
2425  {
2426  GNUNET_SCHEDULER_task_ready (pos->task,
2427  pos->fdi);
2428  }
2429  }
2430  }
2432  {
2434  "scheduler has more tasks ready!\n");
2435  }
2436  }
2439  return GNUNET_OK;
2440 }
2441 
2442 
2443 static int
2444 select_add (void *cls,
2445  struct GNUNET_SCHEDULER_Task *task,
2446  struct GNUNET_SCHEDULER_FdInfo *fdi)
2447 {
2448  struct DriverContext *context = cls;
2449  GNUNET_assert (NULL != context);
2450  GNUNET_assert (NULL != task);
2451  GNUNET_assert (NULL != fdi);
2452  GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2453  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2454 
2455  if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2456  {
2457  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2458  return GNUNET_SYSERR;
2459  }
2460 
2461  struct Scheduled *scheduled = GNUNET_new (struct Scheduled);
2462  scheduled->task = task;
2463  scheduled->fdi = fdi;
2464  scheduled->et = fdi->et;
2465 
2467  context->scheduled_tail,
2468  scheduled);
2469  return GNUNET_OK;
2470 }
2471 
2472 
2473 static int
2474 select_del (void *cls,
2475  struct GNUNET_SCHEDULER_Task *task)
2476 {
2477  struct DriverContext *context;
2478  struct Scheduled *pos;
2479  int ret;
2480 
2481  GNUNET_assert (NULL != cls);
2482 
2483  context = cls;
2484  ret = GNUNET_SYSERR;
2485  pos = context->scheduled_head;
2486  while (NULL != pos)
2487  {
2488  struct Scheduled *next = pos->next;
2489  if (pos->task == task)
2490  {
2492  context->scheduled_tail,
2493  pos);
2494  GNUNET_free (pos);
2495  ret = GNUNET_OK;
2496  }
2497  pos = next;
2498  }
2499  return ret;
2500 }
2501 
2502 
2503 static void
2505  struct GNUNET_TIME_Absolute dt)
2506 {
2507  struct DriverContext *context = cls;
2508 
2509  GNUNET_assert (NULL != context);
2510  context->timeout = dt;
2511 }
2512 
2513 
2519 struct GNUNET_SCHEDULER_Driver *
2521 {
2522  struct GNUNET_SCHEDULER_Driver *select_driver;
2523  select_driver = GNUNET_new (struct GNUNET_SCHEDULER_Driver);
2524 
2525  select_driver->add = &select_add;
2526  select_driver->del = &select_del;
2527  select_driver->set_wakeup = &select_set_wakeup;
2528 
2529  return select_driver;
2530 }
2531 
2532 
2545 void
2547 {
2548  struct GNUNET_AsyncScopeSave dummy_old_scope;
2549 
2550  GNUNET_assert (NULL != active_task);
2551  /* Since we're in a task, the context will be automatically
2552  restored by the scheduler. */
2553  GNUNET_async_scope_enter (aid, &dummy_old_scope);
2554 }
2555 
2556 
2557 /* 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:746
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1268
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:389
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:1100
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:86
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:921
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:1178
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:881
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition: network.c:1325
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:332
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:1293
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:245
#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:412
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition: scheduler.c:1031
static void sighandler_shutdown()
Wait for a short time.
Definition: scheduler.c:660
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:417
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:2195
struct GNUNET_SIGNAL_Context * shc_term
context of the SIGTERM handler
Definition: scheduler.c:103
int GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to, int nfd)
Test native fd in a set.
Definition: network.c:1343
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:624
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:1548
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:716
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:350
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:618
#define GNUNET_NO
Definition: gnunet_common.h:81
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:1675
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:1643
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:463
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal hander.
Definition: signal.c:99
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:289
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:317
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:1710
static struct GNUNET_SCHEDULER_Task * active_task
ID of the task that is running right now.
Definition: scheduler.c:361
void GNUNET_SCHEDULER_shutdown()
Request the shutdown of a scheduler.
Definition: scheduler.c:524
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:1747
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:1512
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:378
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:191
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:2641
static struct GNUNET_SCHEDULER_Task * pending_timeout_last
Last inserted task waiting ONLY for a timeout event.
Definition: scheduler.c:356
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:2520
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:1059
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:283
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:1340
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:680
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1554
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:270
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition: scheduler.c:2474
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition: scheduler.c:2504
static struct GNUNET_SCHEDULER_Task * pending_tail
Tail of list of tasks waiting for an event.
Definition: scheduler.c:322
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:1246
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1538
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:433
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:1200
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
User defined timestamp for completing operations.
Definition: gnunet-arm.c:114
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:1049
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native(SOCKTYPE fd)
Box a native socket (and check that it is a socket).
Definition: network.c:694
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:85
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:1273
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:406
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:727
static struct GNUNET_SCHEDULER_Task * pending_timeout_head
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:341
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:1829
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:899
static struct GNUNET_SCHEDULER_Task * ready_head[GNUNET_SCHEDULER_PRIORITY_COUNT]
Head of list of tasks ready to run right now, grouped by importance.
Definition: scheduler.c:366
struct GNUNET_SIGNAL_Context * shc_int
context of the SIGINT handler
Definition: scheduler.c:98
A struct representing an event the select driver is waiting for.
Definition: scheduler.c:255
#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:312
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:384
struct GNUNET_SIGNAL_Context * shc_hup
context of the SIGHUP handler
Definition: scheduler.c:121
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:1406
#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:150
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:2444
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:2289
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:59
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:1812
The writing socket is ready.
static int select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition: scheduler.c:2303
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:79
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:505
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:71
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:1146
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct Scheduled * prev
Definition: scheduler.c:257
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition: scheduler.c:578
static enum GNUNET_SCHEDULER_Priority current_priority
Priority of the task running right now.
Definition: scheduler.c:395
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:1359
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
void GNUNET_NETWORK_fdset_set(struct GNUNET_NETWORK_FDSet *fds, const struct GNUNET_NETWORK_Handle *desc)
Add a socket to the FD set.
Definition: network.c:1163
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:1992
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:2603
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:126
#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:301
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:631
struct GNUNET_AsyncScopeId scope_id
Saved scope.
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:930
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1937
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:295
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:373
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:401
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:448
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:2546
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:781
struct GNUNET_SCHEDULER_Task * task
the task, the event is related to
Definition: scheduler.c:264
enum GNUNET_SCHEDULER_EventType et
the event types (multiple event types can be ORed) the select driver is expected to wait for ...
Definition: scheduler.c:276
handle to a socket
Definition: network.c:46
void GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
Counter-part of GNUNET_SCHEDULER_driver_init.
Definition: scheduler.c:2272
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:80
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:557
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:1478
enum GNUNET_SCHEDULER_Priority priority
Task priority.
Definition: scheduler.c:203
int fd
File handle on other OSes.
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:1584
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:1947
static struct GNUNET_SCHEDULER_Task * shutdown_head
Head of list of tasks waiting for shutdown.
Definition: scheduler.c:327
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:792
struct GNUNET_NETWORK_FDSet * ws
Passed here to avoid constantly allocating/deallocating this element, but generally we want to get ri...
Definition: scheduler.c:93
int in_ready_list
Is this task in the ready list?
Definition: scheduler.c:229
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:282
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:1223
struct Scheduled * next
Definition: scheduler.c:259
struct GNUNET_SIGNAL_Context * shc_quit
context of the SIGQUIT handler
Definition: scheduler.c:116
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:66
Argument to be passed from the driver to GNUNET_SCHEDULER_do_work().
Definition: scheduler.c:79
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:763
static void * scheduler_select_cls
Closure for scheduler_select.
Definition: scheduler.c:422
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:676
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965