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 
86 
93 
98 
103 
104 #if (SIGTERM != GNUNET_TERM_SIG)
105 
108  struct GNUNET_SIGNAL_Context *shc_gterm;
109 #endif
110 
115 
120 
125 };
126 
127 
136 
141 
146 
151 
156 
163 
167  unsigned int fds_len;
168 
175 
181 
182 #if PROFILE_DELAYS
183 
187 #endif
188 
195 
200 
204  int read_fd;
205 
209  int write_fd;
210 
215  int lifeness;
216 
221 
226 
227 #if EXECINFO
228 
232  char **backtrace_strings;
233 
237  int num_backtrace_strings;
238 #endif
239 
244 };
245 
246 
250 struct Scheduled {
251  struct Scheduled *prev;
252 
253  struct Scheduled *next;
254 
259 
265 
271 };
272 
273 
283 
289 
295 };
296 
297 
306 
311 
316 
321 
326 
335 
344 
350 
355 
360 
365 
372 
378 
382 static unsigned int ready_count;
383 
389 
395 
399 static int current_lifeness;
400 
406 
411 
415 static void *scheduler_select_cls;
416 
417 
425 void
427  void *new_select_cls)
428 {
429  scheduler_select = new_select;
430  scheduler_select_cls = new_select_cls;
431 }
432 
433 
440 static enum GNUNET_SCHEDULER_Priority
442 {
443  if ((p >= 0) && (p < GNUNET_SCHEDULER_PRIORITY_COUNT))
444  return p;
445  GNUNET_assert(0);
446  return 0; /* make compiler happy */
447 }
448 
449 
457 {
458  struct GNUNET_SCHEDULER_Task *pos;
459  struct GNUNET_TIME_Absolute now;
460  struct GNUNET_TIME_Absolute timeout;
461 
462  pos = pending_timeout_head;
463  now = GNUNET_TIME_absolute_get();
465  if (NULL != pos)
466  {
467  if (0 != pos->reason)
468  {
469  return now;
470  }
471  else
472  {
473  timeout = pos->timeout;
474  }
475  }
476  for (pos = pending_head; NULL != pos; pos = pos->next)
477  {
478  if (0 != pos->reason)
479  {
480  return now;
481  }
482  else if ((pos->timeout.abs_value_us != GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) &&
483  (timeout.abs_value_us > pos->timeout.abs_value_us))
484  {
485  timeout = pos->timeout;
486  }
487  }
488  return timeout;
489 }
490 
491 
497 static void
499 {
501 
502  GNUNET_CONTAINER_DLL_insert(ready_head[p],
503  ready_tail[p],
504  task);
505  task->in_ready_list = GNUNET_YES;
506  ready_count++;
507 }
508 
509 
516 void
518 {
519  struct GNUNET_SCHEDULER_Task *pos;
520 
522  "GNUNET_SCHEDULER_shutdown\n");
523  if (NULL != install_parent_control_task)
524  {
525  GNUNET_SCHEDULER_cancel(install_parent_control_task);
526  install_parent_control_task = NULL;
527  }
528  if (NULL != shutdown_pipe_task)
529  {
530  GNUNET_SCHEDULER_cancel(shutdown_pipe_task);
531  shutdown_pipe_task = NULL;
532  }
533  while (NULL != (pos = shutdown_head))
534  {
535  GNUNET_CONTAINER_DLL_remove(shutdown_head,
536  shutdown_tail,
537  pos);
539  queue_ready_task(pos);
540  }
541 }
542 
543 
549 static void
551 {
552 #if EXECINFO
553  for (unsigned int i = 0; i < t->num_backtrace_strings; i++)
555  "Task %p trace %u: %s\n",
556  t,
557  i,
558  t->backtrace_strings[i]);
559 #else
560  (void)t;
561 #endif
562 }
563 
564 
570 static void
572 {
573  unsigned int i;
574 
576  "destroying task %p\n",
577  t);
578 
579  if (GNUNET_YES == t->own_handles)
580  {
581  for (i = 0; i != t->fds_len; ++i)
582  {
583  const struct GNUNET_NETWORK_Handle *fd = t->fds[i].fd;
584  const struct GNUNET_DISK_FileHandle *fh = t->fds[i].fh;
585  if (fd)
586  {
588  }
589  if (fh)
590  {
591  // FIXME: on WIN32 this is not enough! A function
592  // GNUNET_DISK_file_free_memory_only would be nice
593  GNUNET_free((void *)fh);
594  }
595  }
596  }
597  if (t->fds_len > 1)
598  {
599  GNUNET_array_grow(t->fds, t->fds_len, 0);
600  }
601 #if EXECINFO
602  GNUNET_free(t->backtrace_strings);
603 #endif
604  GNUNET_free(t);
605 }
606 
607 
612 
617 static pid_t my_pid;
618 
622 static void
624 {
625  return;
626 }
627 
628 
630 // * Wait for a short time.
631 // * Sleeps for @a ms ms (as that should be long enough for virtually all
632 // * modern systems to context switch and allow another process to do
633 // * some 'real' work).
634 // *
635 // * @param ms how many ms to wait
636 // */
637 //static void
638 //short_wait (unsigned int ms)
639 //{
640 // struct GNUNET_TIME_Relative timeout;
641 //
642 // timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, ms);
643 // (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
644 //}
645 
646 
650 static void
652 {
653  static char c;
654  int old_errno = errno; /* backup errno */
655 
656  if (getpid() != my_pid)
657  _exit(1); /* we have fork'ed since the signal handler was created,
658  * ignore the signal, see https://gnunet.org/vfork discussion */
660  (shutdown_pipe_handle, GNUNET_DISK_PIPE_END_WRITE),
661  &c, sizeof(c));
662  errno = old_errno;
663 }
664 
665 
666 static void
668 {
669  struct GNUNET_SCHEDULER_Task *t;
670 
671  if (ready_count > 0)
672  return;
673  for (t = pending_head; NULL != t; t = t->next)
674  if (GNUNET_YES == t->lifeness)
675  return;
676  for (t = shutdown_head; NULL != t; t = t->next)
677  if (GNUNET_YES == t->lifeness)
678  return;
679  for (t = pending_timeout_head; NULL != t; t = t->next)
680  if (GNUNET_YES == t->lifeness)
681  return;
682  /* No lifeness! */
684 }
685 
686 
687 static int
689  struct DriverContext *context);
690 
691 
706 void
708  void *task_cls)
709 {
710  struct GNUNET_SCHEDULER_Handle *sh;
711  struct GNUNET_SCHEDULER_Driver *driver;
712  struct DriverContext context = { .scheduled_head = NULL,
713  .scheduled_tail = NULL,
714  .timeout = GNUNET_TIME_absolute_get() };
715 
717  driver->cls = &context;
718  sh = GNUNET_SCHEDULER_driver_init(driver);
720  task_cls,
723  select_loop(sh,
724  &context);
726  GNUNET_free(driver);
727 }
728 
729 
736 const struct GNUNET_SCHEDULER_TaskContext *
738 {
739  GNUNET_assert(NULL != active_task);
740  return &tc;
741 }
742 
743 
753 unsigned int
755 {
756  struct GNUNET_SCHEDULER_Task *pos;
757  unsigned int ret;
758 
759  GNUNET_assert(NULL != active_task);
761  return ready_count;
763  p = current_priority;
764  ret = 0;
765  for (pos = ready_head[check_priority(p)]; NULL != pos; pos = pos->next)
766  ret++;
767  return ret;
768 }
769 
770 
771 void
773  const struct GNUNET_NETWORK_Handle *const *read_nh,
774  unsigned int read_nh_len,
775  const struct GNUNET_NETWORK_Handle *const *write_nh,
776  unsigned int write_nh_len,
777  const struct GNUNET_DISK_FileHandle *const *read_fh,
778  unsigned int read_fh_len,
779  const struct GNUNET_DISK_FileHandle *const *write_fh,
780  unsigned int write_fh_len)
781 {
782  // FIXME: if we have exactly two network handles / exactly two file handles
783  // and they are equal, we can make one FdInfo with both
784  // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set.
785  struct GNUNET_SCHEDULER_FdInfo *fdi;
786 
787  t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len;
788  if (1 == t->fds_len)
789  {
790  fdi = &t->fdx;
791  t->fds = fdi;
792  if (1 == read_nh_len)
793  {
794  GNUNET_assert(NULL != read_nh);
795  GNUNET_assert(NULL != *read_nh);
796  fdi->fd = *read_nh;
797  fdi->et = GNUNET_SCHEDULER_ET_IN;
798  fdi->sock = GNUNET_NETWORK_get_fd(*read_nh);
799  t->read_fd = fdi->sock;
800  t->write_fd = -1;
801  }
802  else if (1 == write_nh_len)
803  {
804  GNUNET_assert(NULL != write_nh);
805  GNUNET_assert(NULL != *write_nh);
806  fdi->fd = *write_nh;
808  fdi->sock = GNUNET_NETWORK_get_fd(*write_nh);
809  t->read_fd = -1;
810  t->write_fd = fdi->sock;
811  }
812  else if (1 == read_fh_len)
813  {
814  GNUNET_assert(NULL != read_fh);
815  GNUNET_assert(NULL != *read_fh);
816  fdi->fh = *read_fh;
817  fdi->et = GNUNET_SCHEDULER_ET_IN;
818  fdi->sock = (*read_fh)->fd; // FIXME: does not work under WIN32
819  t->read_fd = fdi->sock;
820  t->write_fd = -1;
821  }
822  else
823  {
824  GNUNET_assert(NULL != write_fh);
825  GNUNET_assert(NULL != *write_fh);
826  fdi->fh = *write_fh;
828  fdi->sock = (*write_fh)->fd; // FIXME: does not work under WIN32
829  t->read_fd = -1;
830  t->write_fd = fdi->sock;
831  }
832  }
833  else
834  {
836  t->fds = fdi;
837  t->read_fd = -1;
838  t->write_fd = -1;
839  unsigned int i;
840  for (i = 0; i != read_nh_len; ++i)
841  {
842  fdi->fd = read_nh[i];
843  GNUNET_assert(NULL != fdi->fd);
844  fdi->et = GNUNET_SCHEDULER_ET_IN;
845  fdi->sock = GNUNET_NETWORK_get_fd(read_nh[i]);
846  ++fdi;
847  }
848  for (i = 0; i != write_nh_len; ++i)
849  {
850  fdi->fd = write_nh[i];
851  GNUNET_assert(NULL != fdi->fd);
853  fdi->sock = GNUNET_NETWORK_get_fd(write_nh[i]);
854  ++fdi;
855  }
856  for (i = 0; i != read_fh_len; ++i)
857  {
858  fdi->fh = read_fh[i];
859  GNUNET_assert(NULL != fdi->fh);
860  fdi->et = GNUNET_SCHEDULER_ET_IN;
861  fdi->sock = (read_fh[i])->fd; // FIXME: does not work under WIN32
862  ++fdi;
863  }
864  for (i = 0; i != write_fh_len; ++i)
865  {
866  fdi->fh = write_fh[i];
867  GNUNET_assert(NULL != fdi->fh);
869  fdi->sock = (write_fh[i])->fd; // FIXME: does not work under WIN32
870  ++fdi;
871  }
872  }
873 }
874 
875 
889 static void
891 {
892  struct GNUNET_SCHEDULER_FdInfo *fdi;
893  int success = GNUNET_YES;
894 
895  for (unsigned int i = 0; i != t->fds_len; ++i)
896  {
897  fdi = &t->fds[i];
898  success = scheduler_driver->add(scheduler_driver->cls,
899  t,
900  fdi) && success;
902  }
903  if (GNUNET_YES != success)
904  {
906  "driver could not add task\n");
907  }
908 }
909 
910 
911 static void
913 {
914  (void)cls;
915  install_parent_control_task = NULL;
917 }
918 
919 
920 static void
922 {
923  char c;
924  const struct GNUNET_DISK_FileHandle *pr;
925 
926  (void)cls;
927  shutdown_pipe_task = NULL;
928  pr = GNUNET_DISK_pipe_handle(shutdown_pipe_handle,
931  /* consume the signal */
932  GNUNET_DISK_file_read(pr, &c, sizeof(c));
933  /* mark all active tasks as ready due to shutdown */
935  shutdown_pipe_task =
937  pr,
939  NULL);
940 }
941 
942 
955 void *
957 {
959  int is_fd_task;
960  void *ret;
961 
963  "canceling task %p\n",
964  task);
965 
966  /* scheduler must be running */
967  GNUNET_assert(NULL != scheduler_driver);
968  is_fd_task = (NULL != task->fds);
969  if (is_fd_task)
970  {
971  int del_result = scheduler_driver->del(scheduler_driver->cls, task);
972  if (GNUNET_OK != del_result)
973  {
975  "driver could not delete task\n");
976  GNUNET_assert(0);
977  }
978  }
979  if (!task->in_ready_list)
980  {
981  if (is_fd_task)
982  {
983  GNUNET_CONTAINER_DLL_remove(pending_head,
984  pending_tail,
985  task);
986  }
987  else if (GNUNET_YES == task->on_shutdown)
988  {
989  GNUNET_CONTAINER_DLL_remove(shutdown_head,
990  shutdown_tail,
991  task);
992  }
993  else
994  {
995  GNUNET_CONTAINER_DLL_remove(pending_timeout_head,
996  pending_timeout_tail,
997  task);
998  if (pending_timeout_last == task)
999  pending_timeout_last = NULL;
1000  }
1001  }
1002  else
1003  {
1004  p = check_priority(task->priority);
1005  GNUNET_CONTAINER_DLL_remove(ready_head[p],
1006  ready_tail[p],
1007  task);
1008  ready_count--;
1009  }
1010  ret = task->callback_cls;
1011  destroy_task(task);
1012  return ret;
1013 }
1014 
1015 
1021 static void
1023 {
1024 #if EXECINFO
1025  void *backtrace_array[MAX_TRACE_DEPTH];
1026 
1027  t->num_backtrace_strings
1028  = backtrace(backtrace_array, MAX_TRACE_DEPTH);
1029  t->backtrace_strings =
1030  backtrace_symbols(backtrace_array,
1031  t->num_backtrace_strings);
1032  dump_backtrace(t);
1033 #else
1034  (void)t;
1035 #endif
1036 }
1037 
1038 
1049 void
1051  void *task_cls,
1052  enum GNUNET_SCHEDULER_Reason reason,
1053  enum GNUNET_SCHEDULER_Priority priority)
1054 {
1055  struct GNUNET_SCHEDULER_Task *t;
1056 
1057  /* scheduler must be running */
1058  GNUNET_assert(NULL != scheduler_driver);
1059  GNUNET_assert(NULL != task);
1060  t = GNUNET_new(struct GNUNET_SCHEDULER_Task);
1061  t->read_fd = -1;
1062  t->write_fd = -1;
1063  t->callback = task;
1064  t->callback_cls = task_cls;
1065 #if PROFILE_DELAYS
1066  t->start_time = GNUNET_TIME_absolute_get();
1067 #endif
1068  t->reason = reason;
1069  t->priority = check_priority(priority);
1072  "Adding continuation task %p\n",
1073  t);
1074  init_backtrace(t);
1075  queue_ready_task(t);
1076 }
1077 
1078 
1090 struct GNUNET_SCHEDULER_Task *
1094  void *task_cls)
1095 {
1096  struct GNUNET_SCHEDULER_Task *t;
1097  struct GNUNET_SCHEDULER_Task *pos;
1098  struct GNUNET_SCHEDULER_Task *prev;
1099 
1100  /* scheduler must be running */
1101  GNUNET_assert(NULL != scheduler_driver);
1102  GNUNET_assert(NULL != task);
1103  t = GNUNET_new(struct GNUNET_SCHEDULER_Task);
1105  t->callback = task;
1106  t->callback_cls = task_cls;
1107  t->read_fd = -1;
1108  t->write_fd = -1;
1109 #if PROFILE_DELAYS
1110  t->start_time = GNUNET_TIME_absolute_get();
1111 #endif
1112  t->timeout = at;
1113  t->priority = check_priority(priority);
1115  /* try tail first (optimization in case we are
1116  * appending to a long list of tasks with timeouts) */
1117  if ((NULL == pending_timeout_head) ||
1118  (at.abs_value_us < pending_timeout_head->timeout.abs_value_us))
1119  {
1120  GNUNET_CONTAINER_DLL_insert(pending_timeout_head,
1121  pending_timeout_tail,
1122  t);
1123  }
1124  else
1125  {
1126  /* first move from heuristic start backwards to before start time */
1127  prev = pending_timeout_last;
1128  while ((NULL != prev) &&
1130  prev = prev->prev;
1131  /* now, move from heuristic start (or head of list) forward to insertion point */
1132  if (NULL == prev)
1133  pos = pending_timeout_head;
1134  else
1135  pos = prev->next;
1136  while ((NULL != pos) && (pos->timeout.abs_value_us <= t->timeout.abs_value_us))
1137  {
1138  prev = pos;
1139  pos = pos->next;
1140  }
1141  GNUNET_CONTAINER_DLL_insert_after(pending_timeout_head,
1142  pending_timeout_tail,
1143  prev,
1144  t);
1145  }
1146  /* finally, update heuristic insertion point to last insertion... */
1147  pending_timeout_last = t;
1148 
1150  "Adding task %p\n",
1151  t);
1152  init_backtrace(t);
1153  return t;
1154 }
1155 
1156 
1168 struct GNUNET_SCHEDULER_Task *
1172  void *task_cls)
1173 {
1175  priority,
1176  task,
1177  task_cls);
1178 }
1179 
1180 
1190 struct GNUNET_SCHEDULER_Task *
1193  void *task_cls)
1194 {
1196  prio,
1197  task,
1198  task_cls);
1199 }
1200 
1201 
1213 struct GNUNET_SCHEDULER_Task *
1216  void *task_cls)
1217 {
1220  task,
1221  task_cls);
1222 }
1223 
1224 
1236 struct GNUNET_SCHEDULER_Task *
1239  void *task_cls)
1240 {
1243  task,
1244  task_cls);
1245 }
1246 
1247 
1263 struct GNUNET_SCHEDULER_Task *
1265  void *task_cls)
1266 {
1268  task,
1269  task_cls);
1270 }
1271 
1272 
1283 struct GNUNET_SCHEDULER_Task *
1285  void *task_cls)
1286 {
1287  struct GNUNET_SCHEDULER_Task *t;
1288 
1289  /* scheduler must be running */
1290  GNUNET_assert(NULL != scheduler_driver);
1291  GNUNET_assert(NULL != task);
1292  t = GNUNET_new(struct GNUNET_SCHEDULER_Task);
1294  t->callback = task;
1295  t->callback_cls = task_cls;
1296  t->read_fd = -1;
1297  t->write_fd = -1;
1298 #if PROFILE_DELAYS
1299  t->start_time = GNUNET_TIME_absolute_get();
1300 #endif
1303  t->on_shutdown = GNUNET_YES;
1304  t->lifeness = GNUNET_NO;
1305  GNUNET_CONTAINER_DLL_insert(shutdown_head,
1306  shutdown_tail,
1307  t);
1309  "Adding shutdown task %p\n",
1310  t);
1311  init_backtrace(t);
1312  return t;
1313 }
1314 
1315 
1330 struct GNUNET_SCHEDULER_Task *
1333  void *task_cls)
1334 {
1335  struct GNUNET_SCHEDULER_Task *ret;
1336 
1337  ret = GNUNET_SCHEDULER_add_now(task, task_cls);
1338  ret->lifeness = lifeness;
1339  return ret;
1340 }
1341 
1342 
1343 #if DEBUG_FDS
1344 
1350 void
1351 check_fd(struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1352 {
1353  if (-1 != raw_fd)
1354  {
1355  int flags = fcntl(raw_fd, F_GETFD);
1356 
1357  if ((flags == -1) && (errno == EBADF))
1358  {
1360  "Got invalid file descriptor %d!\n",
1361  raw_fd);
1362  init_backtrace(t);
1363  GNUNET_assert(0);
1364  }
1365  }
1366 }
1367 #endif
1368 
1369 
1395 static struct GNUNET_SCHEDULER_Task *
1398  const struct GNUNET_NETWORK_Handle *read_nh,
1399  const struct GNUNET_NETWORK_Handle *write_nh,
1400  const struct GNUNET_DISK_FileHandle *read_fh,
1401  const struct GNUNET_DISK_FileHandle *write_fh,
1403  void *task_cls)
1404 {
1405  struct GNUNET_SCHEDULER_Task *t;
1406 
1407  /* scheduler must be running */
1408  GNUNET_assert(NULL != scheduler_driver);
1409  GNUNET_assert(NULL != task);
1410  t = GNUNET_new(struct GNUNET_SCHEDULER_Task);
1412  init_fd_info(t,
1413  &read_nh,
1414  read_nh ? 1 : 0,
1415  &write_nh,
1416  write_nh ? 1 : 0,
1417  &read_fh,
1418  read_fh ? 1 : 0,
1419  &write_fh,
1420  write_fh ? 1 : 0);
1421  t->callback = task;
1422  t->callback_cls = task_cls;
1423 #if DEBUG_FDS
1424  check_fd(t, NULL != read_nh ? GNUNET_NETWORK_get_fd(read_nh) : -1);
1425  check_fd(t, NULL != write_nh ? GNUNET_NETWORK_get_fd(write_nh) : -1);
1426  check_fd(t, NULL != read_fh ? read_fh->fd : -1);
1427  check_fd(t, NULL != write_fh ? write_fh->fd : -1);
1428 #endif
1429 #if PROFILE_DELAYS
1430  t->start_time = GNUNET_TIME_absolute_get();
1431 #endif
1435  GNUNET_CONTAINER_DLL_insert(pending_head,
1436  pending_tail,
1437  t);
1440  t->priority);
1441  init_backtrace(t);
1442  return t;
1443 }
1444 
1445 
1466 struct GNUNET_SCHEDULER_Task *
1468  struct GNUNET_NETWORK_Handle *rfd,
1470  void *task_cls)
1471 {
1474  rfd, task, task_cls);
1475 }
1476 
1477 
1500 struct GNUNET_SCHEDULER_Task *
1503  struct GNUNET_NETWORK_Handle *rfd,
1505  void *task_cls)
1506 {
1507  return GNUNET_SCHEDULER_add_net_with_priority(delay, priority,
1508  rfd,
1509  GNUNET_YES,
1510  GNUNET_NO,
1511  task, task_cls);
1512 }
1513 
1514 
1536 struct GNUNET_SCHEDULER_Task *
1538  struct GNUNET_NETWORK_Handle *wfd,
1540  void *task_cls)
1541 {
1544  wfd,
1546  task, task_cls);
1547 }
1548 
1572 struct GNUNET_SCHEDULER_Task *
1575  struct GNUNET_NETWORK_Handle *fd,
1576  int on_read,
1577  int on_write,
1579  void *task_cls)
1580 {
1581  /* scheduler must be running */
1582  GNUNET_assert(NULL != scheduler_driver);
1583  GNUNET_assert(on_read || on_write);
1585  return add_without_sets(delay, priority,
1586  on_read ? fd : NULL,
1587  on_write ? fd : NULL,
1588  NULL,
1589  NULL,
1590  task, task_cls);
1591 }
1592 
1593 
1614 struct GNUNET_SCHEDULER_Task *
1616  const struct GNUNET_DISK_FileHandle *rfd,
1617  GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
1618 {
1621  rfd, GNUNET_YES, GNUNET_NO,
1622  task, task_cls);
1623 }
1624 
1625 
1646 struct GNUNET_SCHEDULER_Task *
1648  const struct GNUNET_DISK_FileHandle *wfd,
1649  GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
1650 {
1653  wfd, GNUNET_NO, GNUNET_YES,
1654  task, task_cls);
1655 }
1656 
1657 
1681 struct GNUNET_SCHEDULER_Task *
1684  const struct GNUNET_DISK_FileHandle *fd,
1685  int on_read, int on_write,
1686  GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
1687 {
1688  /* scheduler must be running */
1689  GNUNET_assert(NULL != scheduler_driver);
1690  GNUNET_assert(on_read || on_write);
1691  GNUNET_assert(fd->fd >= 0);
1692  return add_without_sets(delay, priority,
1693  NULL,
1694  NULL,
1695  on_read ? fd : NULL,
1696  on_write ? fd : NULL,
1697  task, task_cls);
1698 }
1699 
1700 
1701 void
1703  const struct GNUNET_NETWORK_Handle ***ntarget,
1704  unsigned int *extracted_nhandles,
1705  const struct GNUNET_DISK_FileHandle ***ftarget,
1706  unsigned int *extracted_fhandles)
1707 {
1708  // FIXME: this implementation only works for unix, for WIN32 the file handles
1709  // in fdset must be handled separately
1710  const struct GNUNET_NETWORK_Handle **nhandles;
1711  const struct GNUNET_DISK_FileHandle **fhandles;
1712  unsigned int nhandles_len;
1713  unsigned int fhandles_len;
1714 
1715  nhandles = NULL;
1716  fhandles = NULL;
1717  nhandles_len = 0;
1718  fhandles_len = 0;
1719  for (int sock = 0; sock != fdset->nsds; ++sock)
1720  {
1721  if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native(fdset, sock))
1722  {
1723  struct GNUNET_NETWORK_Handle *nhandle;
1724  struct GNUNET_DISK_FileHandle *fhandle;
1725 
1726  nhandle = GNUNET_NETWORK_socket_box_native(sock);
1727  if (NULL != nhandle)
1728  {
1729  GNUNET_array_append(nhandles, nhandles_len, nhandle);
1730  }
1731  else
1732  {
1733  fhandle = GNUNET_DISK_get_handle_from_int_fd(sock);
1734  if (NULL != fhandle)
1735  {
1736  GNUNET_array_append(fhandles, fhandles_len, fhandle);
1737  }
1738  else
1739  {
1740  GNUNET_assert(0);
1741  }
1742  }
1743  }
1744  }
1745  *ntarget = nhandles_len > 0 ? nhandles : NULL;
1746  *ftarget = fhandles_len > 0 ? fhandles : NULL;
1747  *extracted_nhandles = nhandles_len;
1748  *extracted_fhandles = fhandles_len;
1749 }
1750 
1751 
1783 struct GNUNET_SCHEDULER_Task *
1785  struct GNUNET_TIME_Relative delay,
1786  const struct GNUNET_NETWORK_FDSet *rs,
1787  const struct GNUNET_NETWORK_FDSet *ws,
1789  void *task_cls)
1790 {
1791  struct GNUNET_SCHEDULER_Task *t;
1792  const struct GNUNET_NETWORK_Handle **read_nhandles = NULL;
1793  const struct GNUNET_NETWORK_Handle **write_nhandles = NULL;
1794  const struct GNUNET_DISK_FileHandle **read_fhandles = NULL;
1795  const struct GNUNET_DISK_FileHandle **write_fhandles = NULL;
1796  unsigned int read_nhandles_len = 0;
1797  unsigned int write_nhandles_len = 0;
1798  unsigned int read_fhandles_len = 0;
1799  unsigned int write_fhandles_len = 0;
1800 
1801  /* scheduler must be running */
1802  GNUNET_assert(NULL != scheduler_driver);
1803  GNUNET_assert(NULL != task);
1804  int no_rs = (NULL == rs);
1805  int no_ws = (NULL == ws);
1806  int empty_rs = (NULL != rs) && (0 == rs->nsds);
1807  int empty_ws = (NULL != ws) && (0 == ws->nsds);
1808  int no_fds = (no_rs && no_ws) ||
1809  (empty_rs && empty_ws) ||
1810  (no_rs && empty_ws) ||
1811  (no_ws && empty_rs);
1812  if (!no_fds)
1813  {
1814  if (NULL != rs)
1815  {
1816  extract_handles(rs,
1817  &read_nhandles,
1818  &read_nhandles_len,
1819  &read_fhandles,
1820  &read_fhandles_len);
1821  }
1822  if (NULL != ws)
1823  {
1824  extract_handles(ws,
1825  &write_nhandles,
1826  &write_nhandles_len,
1827  &write_fhandles,
1828  &write_fhandles_len);
1829  }
1830  }
1838  int no_fds_extracted = (0 == read_nhandles_len) &&
1839  (0 == read_fhandles_len) &&
1840  (0 == write_nhandles_len) &&
1841  (0 == write_fhandles_len);
1842  if (no_fds || no_fds_extracted)
1844  prio,
1845  task,
1846  task_cls);
1847  t = GNUNET_new(struct GNUNET_SCHEDULER_Task);
1849  init_fd_info(t,
1850  read_nhandles,
1851  read_nhandles_len,
1852  write_nhandles,
1853  write_nhandles_len,
1854  read_fhandles,
1855  read_fhandles_len,
1856  write_fhandles,
1857  write_fhandles_len);
1858  t->callback = task;
1859  t->callback_cls = task_cls;
1860  t->own_handles = GNUNET_YES;
1861  /* free the arrays of pointers to network / file handles, the actual
1862  * handles will be freed in destroy_task */
1863  GNUNET_array_grow(read_nhandles, read_nhandles_len, 0);
1864  GNUNET_array_grow(write_nhandles, write_nhandles_len, 0);
1865  GNUNET_array_grow(read_fhandles, read_fhandles_len, 0);
1866  GNUNET_array_grow(write_fhandles, write_fhandles_len, 0);
1867 #if PROFILE_DELAYS
1868  t->start_time = GNUNET_TIME_absolute_get();
1869 #endif
1871  t->priority =
1872  check_priority((prio ==
1874  prio);
1876  GNUNET_CONTAINER_DLL_insert(pending_head,
1877  pending_tail,
1878  t);
1881  t->priority);
1883  "Adding task %p\n",
1884  t);
1885  init_backtrace(t);
1886  return t;
1887 }
1888 
1889 
1901 void
1903  struct GNUNET_SCHEDULER_FdInfo *fdi)
1904 {
1905  enum GNUNET_SCHEDULER_Reason reason;
1906 
1907  reason = task->reason;
1908  if ((0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1909  (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)))
1911  if ((0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1912  (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)))
1915  task->reason = reason;
1916  if (GNUNET_NO == task->in_ready_list)
1917  {
1918  GNUNET_CONTAINER_DLL_remove(pending_head,
1919  pending_tail,
1920  task);
1921  queue_ready_task(task);
1922  }
1923 }
1924 
1925 
1946 int
1948 {
1950  struct GNUNET_SCHEDULER_Task *pos;
1951  struct GNUNET_TIME_Absolute now;
1952 
1953  /* check for tasks that reached the timeout! */
1954  now = GNUNET_TIME_absolute_get();
1955  pos = pending_timeout_head;
1956  while (NULL != pos)
1957  {
1958  struct GNUNET_SCHEDULER_Task *next = pos->next;
1959  if (now.abs_value_us >= pos->timeout.abs_value_us)
1961  if (0 == pos->reason)
1962  break;
1963  GNUNET_CONTAINER_DLL_remove(pending_timeout_head,
1964  pending_timeout_tail,
1965  pos);
1966  if (pending_timeout_last == pos)
1967  pending_timeout_last = NULL;
1968  queue_ready_task(pos);
1969  pos = next;
1970  }
1971  pos = pending_head;
1972  while (NULL != pos)
1973  {
1974  struct GNUNET_SCHEDULER_Task *next = pos->next;
1975  if (now.abs_value_us >= pos->timeout.abs_value_us)
1976  {
1978  GNUNET_CONTAINER_DLL_remove(pending_head,
1979  pending_tail,
1980  pos);
1981  queue_ready_task(pos);
1982  }
1983  pos = next;
1984  }
1985 
1986  if (0 == ready_count)
1987  {
1988  struct GNUNET_TIME_Absolute timeout = get_timeout();
1989 
1990  if (timeout.abs_value_us > now.abs_value_us)
1991  {
2006  "GNUNET_SCHEDULER_do_work did not find any ready "
2007  "tasks and timeout has not been reached yet.\n");
2008  }
2009  else
2010  {
2015  GNUNET_assert(0);
2016  }
2017  }
2018  else
2019  {
2020  /* find out which task priority level we are going to
2021  process this time */
2023  GNUNET_assert(NULL == ready_head[GNUNET_SCHEDULER_PRIORITY_KEEP]);
2024  /* yes, p>0 is correct, 0 is "KEEP" which should
2025  * always be an empty queue (see assertion)! */
2026  for (p = GNUNET_SCHEDULER_PRIORITY_COUNT - 1; p > 0; p--)
2027  {
2028  pos = ready_head[p];
2029  if (NULL != pos)
2030  break;
2031  }
2032  GNUNET_assert(NULL != pos); /* ready_count wrong? */
2033 
2034  /* process all tasks at this priority level, then yield */
2035  while (NULL != (pos = ready_head[p]))
2036  {
2037  GNUNET_CONTAINER_DLL_remove(ready_head[p],
2038  ready_tail[p],
2039  pos);
2040  ready_count--;
2041  current_priority = pos->priority;
2042  current_lifeness = pos->lifeness;
2043  active_task = pos;
2044 #if PROFILE_DELAYS
2045  if (GNUNET_TIME_absolute_get_duration(pos->start_time).rel_value_us >
2046  DELAY_THRESHOLD.rel_value_us)
2047  {
2049  "Task %p took %s to be scheduled\n",
2050  pos,
2052  GNUNET_YES));
2053  }
2054 #endif
2055  tc.reason = pos->reason;
2058  // FIXME: do we have to remove FdInfos from fds if they are not ready?
2059  tc.fds_len = pos->fds_len;
2060  tc.fds = pos->fds;
2061  for (unsigned int i = 0; i != pos->fds_len; ++i)
2062  {
2063  struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i];
2064  if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et))
2065  {
2067  fdi->sock);
2068  }
2069  if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et))
2070  {
2072  fdi->sock);
2073  }
2074  }
2075  tc.read_ready = sh->rs;
2076  tc.write_ready = sh->ws;
2078  "Running task %p\n",
2079  pos);
2080  GNUNET_assert(NULL != pos->callback);
2081  {
2082  struct GNUNET_AsyncScopeSave old_scope;
2083  if (pos->scope.have_scope)
2084  GNUNET_async_scope_enter(&pos->scope.scope_id, &old_scope);
2085  else
2086  GNUNET_async_scope_get(&old_scope);
2087  pos->callback(pos->callback_cls);
2088  GNUNET_async_scope_restore(&old_scope);
2089  }
2090  if (NULL != pos->fds)
2091  {
2092  int del_result = scheduler_driver->del(scheduler_driver->cls, pos);
2093  if (GNUNET_OK != del_result)
2094  {
2096  "driver could not delete task %p\n", pos);
2097  GNUNET_assert(0);
2098  }
2099  }
2100  active_task = NULL;
2101  dump_backtrace(pos);
2102  destroy_task(pos);
2103  }
2104  }
2106  if (0 == ready_count)
2107  {
2108  scheduler_driver->set_wakeup(scheduler_driver->cls,
2109  get_timeout());
2110  return GNUNET_NO;
2111  }
2112  scheduler_driver->set_wakeup(scheduler_driver->cls,
2114  return GNUNET_YES;
2115 }
2116 
2117 
2149 struct GNUNET_SCHEDULER_Handle *
2151 {
2152  struct GNUNET_SCHEDULER_Handle *sh;
2153  const struct GNUNET_DISK_FileHandle *pr;
2154 
2155  /* scheduler must not be running */
2156  GNUNET_assert(NULL == scheduler_driver);
2157  GNUNET_assert(NULL == shutdown_pipe_handle);
2158  /* general set-up */
2159  sh = GNUNET_new(struct GNUNET_SCHEDULER_Handle);
2160  shutdown_pipe_handle = GNUNET_DISK_pipe(GNUNET_NO,
2161  GNUNET_NO,
2162  GNUNET_NO,
2163  GNUNET_NO);
2164  GNUNET_assert(NULL != shutdown_pipe_handle);
2165  pr = GNUNET_DISK_pipe_handle(shutdown_pipe_handle,
2167  my_pid = getpid();
2168  scheduler_driver = driver;
2169 
2170  /* install signal handlers */
2172  "Registering signal handlers\n");
2177 #if (SIGTERM != GNUNET_TERM_SIG)
2180 #endif
2182  &sighandler_pipe);
2187 
2188  /* Setup initial tasks */
2191  install_parent_control_task =
2193  NULL);
2194  shutdown_pipe_task =
2196  pr,
2198  NULL);
2200  scheduler_driver->set_wakeup(scheduler_driver->cls,
2201  get_timeout());
2202  /* begin main event loop */
2206  return sh;
2207 }
2208 
2209 
2224 void
2226 {
2227  GNUNET_assert(NULL == pending_head);
2228  GNUNET_assert(NULL == pending_timeout_head);
2229  GNUNET_assert(NULL == shutdown_head);
2230  for (int i = 0; i != GNUNET_SCHEDULER_PRIORITY_COUNT; ++i)
2231  {
2232  GNUNET_assert(NULL == ready_head[i]);
2233  }
2236 
2237  /* uninstall signal handlers */
2240 #if (SIGTERM != GNUNET_TERM_SIG)
2241  GNUNET_SIGNAL_handler_uninstall(sh->shc_gterm);
2242 #endif
2246  GNUNET_DISK_pipe_close(shutdown_pipe_handle);
2247  shutdown_pipe_handle = NULL;
2248  scheduler_driver = NULL;
2249  GNUNET_free(sh);
2250 }
2251 
2252 
2253 static int
2255  struct DriverContext *context)
2256 {
2257  struct GNUNET_NETWORK_FDSet *rs;
2258  struct GNUNET_NETWORK_FDSet *ws;
2259  int select_result;
2260 
2261  GNUNET_assert(NULL != context);
2264  while ((NULL != context->scheduled_head) ||
2265  (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us != context->timeout.abs_value_us))
2266  {
2268  "select timeout = %s\n",
2270 
2273 
2274  for (struct Scheduled *pos = context->scheduled_head;
2275  NULL != pos;
2276  pos = pos->next)
2277  {
2278  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et))
2279  {
2280  GNUNET_NETWORK_fdset_set_native(rs, pos->fdi->sock);
2281  }
2282  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et))
2283  {
2284  GNUNET_NETWORK_fdset_set_native(ws, pos->fdi->sock);
2285  }
2286  }
2287  struct GNUNET_TIME_Relative time_remaining =
2289  if (NULL == scheduler_select)
2290  {
2291  select_result = GNUNET_NETWORK_socket_select(rs,
2292  ws,
2293  NULL,
2294  time_remaining);
2295  }
2296  else
2297  {
2298  select_result = scheduler_select(scheduler_select_cls,
2299  rs,
2300  ws,
2301  NULL,
2302  time_remaining);
2303  }
2304  if (select_result == GNUNET_SYSERR)
2305  {
2306  if (errno == EINTR)
2307  continue;
2308 
2310  "select");
2311 #if USE_LSOF
2312  char lsof[512];
2313 
2314  snprintf(lsof,
2315  sizeof(lsof),
2316  "lsof -p %d",
2317  getpid());
2318  (void)close(1);
2319  (void)dup2(2, 1);
2320  if (0 != system(lsof))
2322  "system");
2323 #endif
2324 #if DEBUG_FDS
2325  for (struct Scheduled *s = context->scheduled_head;
2326  NULL != s;
2327  s = s->next)
2328  {
2329  int flags = fcntl(s->fdi->sock,
2330  F_GETFD);
2331 
2332  if ((flags == -1) &&
2333  (EBADF == errno))
2334  {
2336  "Got invalid file descriptor %d!\n",
2337  s->fdi->sock);
2338 #if EXECINFO
2339  dump_backtrace(s->task);
2340 #endif
2341  }
2342  }
2343 #endif
2344  GNUNET_assert(0);
2347  return GNUNET_SYSERR;
2348  }
2349  if (select_result > 0)
2350  {
2351  for (struct Scheduled *pos = context->scheduled_head;
2352  NULL != pos;
2353  pos = pos->next)
2354  {
2355  int is_ready = GNUNET_NO;
2356 
2357  if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et) &&
2358  GNUNET_YES ==
2360  pos->fdi->sock))
2361  {
2362  pos->fdi->et |= GNUNET_SCHEDULER_ET_IN;
2363  is_ready = GNUNET_YES;
2364  }
2365  if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et) &&
2366  GNUNET_YES ==
2368  pos->fdi->sock))
2369  {
2370  pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT;
2371  is_ready = GNUNET_YES;
2372  }
2373  if (GNUNET_YES == is_ready)
2374  {
2375  GNUNET_SCHEDULER_task_ready(pos->task,
2376  pos->fdi);
2377  }
2378  }
2379  }
2381  {
2383  "scheduler has more tasks ready!\n");
2384  }
2385  }
2388  return GNUNET_OK;
2389 }
2390 
2391 
2392 static int
2393 select_add(void *cls,
2394  struct GNUNET_SCHEDULER_Task *task,
2395  struct GNUNET_SCHEDULER_FdInfo *fdi)
2396 {
2397  struct DriverContext *context = cls;
2398 
2399  GNUNET_assert(NULL != context);
2400  GNUNET_assert(NULL != task);
2401  GNUNET_assert(NULL != fdi);
2402  GNUNET_assert(0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) ||
2403  0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et));
2404 
2405  if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0))
2406  {
2407  /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */
2408  return GNUNET_SYSERR;
2409  }
2410 
2411  struct Scheduled *scheduled = GNUNET_new(struct Scheduled);
2412  scheduled->task = task;
2413  scheduled->fdi = fdi;
2414  scheduled->et = fdi->et;
2415 
2417  context->scheduled_tail,
2418  scheduled);
2419  return GNUNET_OK;
2420 }
2421 
2422 
2423 static int
2424 select_del(void *cls,
2425  struct GNUNET_SCHEDULER_Task *task)
2426 {
2427  struct DriverContext *context;
2428  struct Scheduled *pos;
2429  int ret;
2430 
2431  GNUNET_assert(NULL != cls);
2432 
2433  context = cls;
2434  ret = GNUNET_SYSERR;
2435  pos = context->scheduled_head;
2436  while (NULL != pos)
2437  {
2438  struct Scheduled *next = pos->next;
2439  if (pos->task == task)
2440  {
2442  context->scheduled_tail,
2443  pos);
2444  GNUNET_free(pos);
2445  ret = GNUNET_OK;
2446  }
2447  pos = next;
2448  }
2449  return ret;
2450 }
2451 
2452 
2453 static void
2455  struct GNUNET_TIME_Absolute dt)
2456 {
2457  struct DriverContext *context = cls;
2458 
2459  GNUNET_assert(NULL != context);
2460  context->timeout = dt;
2461 }
2462 
2463 
2469 struct GNUNET_SCHEDULER_Driver *
2471 {
2472  struct GNUNET_SCHEDULER_Driver *select_driver;
2473 
2474  select_driver = GNUNET_new(struct GNUNET_SCHEDULER_Driver);
2475 
2476  select_driver->add = &select_add;
2477  select_driver->del = &select_del;
2478  select_driver->set_wakeup = &select_set_wakeup;
2479 
2480  return select_driver;
2481 }
2482 
2483 
2496 void
2498 {
2499  struct GNUNET_AsyncScopeSave dummy_old_scope;
2500 
2501  GNUNET_assert(NULL != active_task);
2502  /* Since we're in a task, the context will be automatically
2503  restored by the scheduler. */
2504  GNUNET_async_scope_enter(aid, &dummy_old_scope);
2505 }
2506 
2507 
2508 /* 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:737
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1068
int read_fd
Set if we only wait for reading from a single FD, otherwise -1.
Definition: scheduler.c:204
static unsigned int ready_count
Number of tasks on the ready list.
Definition: scheduler.c:382
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:1091
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:85
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:912
GNUNET_SCHEDULER_TaskCallback callback
Function to run when ready.
Definition: scheduler.c:145
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:1169
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:729
void GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to, int nfd)
Set a native fd in a set.
Definition: network.c:1125
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:325
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:1284
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:405
static void init_backtrace(struct GNUNET_SCHEDULER_Task *t)
Initialize backtrace data for task t.
Definition: scheduler.c:1022
static void sighandler_shutdown()
Wait for a short time.
Definition: scheduler.c:651
struct GNUNET_SCHEDULER_Task * prev
This is a linked list.
Definition: scheduler.c:140
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition: scheduler.c:410
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:2150
struct GNUNET_SIGNAL_Context * shc_term
context of the SIGTERM handler
Definition: scheduler.c:102
int GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to, int nfd)
Test native fd in a set.
Definition: network.c:1143
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:617
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:1537
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:707
int on_shutdown
Is this task run on shutdown?
Definition: scheduler.c:220
static struct GNUNET_SCHEDULER_Task * pending_timeout_tail
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:343
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:611
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1647
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:1615
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct GNUNET_TIME_Absolute get_timeout()
chooses the nearest timeout from all pending tasks, to be used to tell the driver the next wakeup tim...
Definition: scheduler.c:456
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal hander.
Definition: signal.c:75
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:282
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:310
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:1682
static struct GNUNET_SCHEDULER_Task * active_task
ID of the task that is running right now.
Definition: scheduler.c:354
void GNUNET_SCHEDULER_shutdown()
Request the shutdown of a scheduler.
Definition: scheduler.c:517
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:1702
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:1501
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:371
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:190
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:1744
static struct GNUNET_SCHEDULER_Task * pending_timeout_last
Last inserted task waiting ONLY for a timeout event.
Definition: scheduler.c:349
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:2470
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:209
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:1050
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:277
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:1331
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:610
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
Definition: network.c:1254
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:264
static int select_del(void *cls, struct GNUNET_SCHEDULER_Task *task)
Definition: scheduler.c:2424
static void select_set_wakeup(void *cls, struct GNUNET_TIME_Absolute dt)
Definition: scheduler.c:2454
static struct GNUNET_SCHEDULER_Task * pending_tail
Tail of list of tasks waiting for an event.
Definition: scheduler.c:315
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:1237
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
Definition: network.c:1238
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:426
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:1191
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:364
#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:162
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:817
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:624
#define GNUNET_MAX(a, b)
Definition: gnunet_common.h:82
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
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:399
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:686
static struct GNUNET_SCHEDULER_Task * pending_timeout_head
List of tasks waiting ONLY for a timeout event.
Definition: scheduler.c:334
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:1784
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:890
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:359
struct GNUNET_SIGNAL_Context * shc_int
context of the SIGINT handler
Definition: scheduler.c:97
A struct representing an event the select driver is waiting for.
Definition: scheduler.c:250
#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:305
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:377
struct GNUNET_SIGNAL_Context * shc_hup
context of the SIGHUP handler
Definition: scheduler.c:119
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:1396
#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:140
struct GNUNET_SCHEDULER_FdInfo * fds
Information about which FDs are ready for this task (and why).
Definition: scheduler.c:155
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:2393
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:1518
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:150
enum GNUNET_SCHEDULER_Reason reason
Why is the task ready? Set after task is added to ready queue.
Definition: scheduler.c:194
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:50
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:1328
The writing socket is ready.
static int select_loop(struct GNUNET_SCHEDULER_Handle *sh, struct DriverContext *context)
Definition: scheduler.c:2254
This is an internal priority level that is only used for tasks that are being triggered due to shutdo...
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
Data available for reading.
static void queue_ready_task(struct GNUNET_SCHEDULER_Task *task)
Put a task that is ready for execution into the ready queue.
Definition: scheduler.c:498
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:985
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct Scheduled * prev
Definition: scheduler.c:251
static void destroy_task(struct GNUNET_SCHEDULER_Task *t)
Destroy a task (release associated resources)
Definition: scheduler.c:571
static enum GNUNET_SCHEDULER_Priority current_priority
Priority of the task running right now.
Definition: scheduler.c:388
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:1159
#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:1947
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1706
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:124
#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:167
struct GNUNET_TIME_Absolute timeout
the time when the select driver will wake up again (after calling select)
Definition: scheduler.c:294
int own_handles
Do we own the network and file handles referenced by the FdInfo structs in the fds array...
Definition: scheduler.c:174
static void sighandler_pipe()
Signal handler called for SIGPIPE.
Definition: scheduler.c:623
struct GNUNET_AsyncScopeId scope_id
Saved scope.
static void shutdown_pipe_cb(void *cls)
Definition: scheduler.c:921
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1369
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:288
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:135
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:394
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:441
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:2497
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:131
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:772
struct GNUNET_SCHEDULER_Task * task
the task, the event is related to
Definition: scheduler.c:258
enum GNUNET_SCHEDULER_EventType et
the event types (multiple event types can be ORed) the select driver is expected to wait for ...
Definition: scheduler.c:270
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:2225
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:180
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
static void dump_backtrace(struct GNUNET_SCHEDULER_Task *t)
Output stack trace of task t.
Definition: scheduler.c:550
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:1467
enum GNUNET_SCHEDULER_Priority priority
Task priority.
Definition: scheduler.c:199
int fd
File handle on Unix-like systems.
struct GNUNET_AsyncScopeSave scope
Asynchronous scope of the task that scheduled this scope,.
Definition: scheduler.c:243
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:1573
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:1902
static struct GNUNET_SCHEDULER_Task * shutdown_head
Head of list of tasks waiting for shutdown.
Definition: scheduler.c:320
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:741
struct GNUNET_NETWORK_FDSet * ws
Passed here to avoid constantly allocating/deallocating this element, but generally we want to get ri...
Definition: scheduler.c:92
int in_ready_list
Is this task in the ready list?
Definition: scheduler.c:225
#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:1214
struct Scheduled * next
Definition: scheduler.c:253
struct GNUNET_SIGNAL_Context * shc_quit
context of the SIGQUIT handler
Definition: scheduler.c:114
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: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:754
static void * scheduler_select_cls
Closure for scheduler_select.
Definition: scheduler.c:415
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:215
GNUNET_SCHEDULER_EventType
Possible events on FDs, used as a bitmask.
static void shutdown_if_no_lifeness()
Definition: scheduler.c:667
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956