diff options
author | lurchi <lurchi@strangeplace.net> | 2017-08-23 15:44:52 +0200 |
---|---|---|
committer | lurchi <lurchi@strangeplace.net> | 2017-08-23 15:44:52 +0200 |
commit | 357181530f9089ee30ba88c55ed429ec58505357 (patch) | |
tree | 4a4b36ae19130ed67ff293d3635796217e77b9f5 /src | |
parent | 863211feb62023e37cad3f57cc72b2bb30262383 (diff) | |
download | gnunet-357181530f9089ee30ba88c55ed429ec58505357.tar.gz gnunet-357181530f9089ee30ba88c55ed429ec58505357.zip |
tasks in the pending queue must be be checked for reached timeouts, too; allow multiple event types per FdInfo
Diffstat (limited to 'src')
-rw-r--r-- | src/util/scheduler.c | 346 |
1 files changed, 193 insertions, 153 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 71a3bd956..084ca43df 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c | |||
@@ -120,7 +120,7 @@ struct GNUNET_SCHEDULER_Task | |||
120 | /** | 120 | /** |
121 | * Information about which FDs are ready for this task (and why). | 121 | * Information about which FDs are ready for this task (and why). |
122 | */ | 122 | */ |
123 | const struct GNUNET_SCHEDULER_FdInfo *fds; | 123 | struct GNUNET_SCHEDULER_FdInfo *fds; |
124 | 124 | ||
125 | /** | 125 | /** |
126 | * Storage location used for @e fds if we want to avoid | 126 | * Storage location used for @e fds if we want to avoid |
@@ -229,6 +229,10 @@ struct Scheduled | |||
229 | struct GNUNET_SCHEDULER_Task *task; | 229 | struct GNUNET_SCHEDULER_Task *task; |
230 | 230 | ||
231 | struct GNUNET_SCHEDULER_FdInfo *fdi; | 231 | struct GNUNET_SCHEDULER_FdInfo *fdi; |
232 | |||
233 | enum GNUNET_SCHEDULER_EventType et; | ||
234 | |||
235 | int is_ready; | ||
232 | }; | 236 | }; |
233 | 237 | ||
234 | 238 | ||
@@ -237,13 +241,9 @@ struct Scheduled | |||
237 | */ | 241 | */ |
238 | struct DriverContext | 242 | struct DriverContext |
239 | { | 243 | { |
240 | struct Scheduled *scheduled_in_head; | 244 | struct Scheduled *scheduled_head; |
241 | |||
242 | struct Scheduled *scheduled_in_tail; | ||
243 | 245 | ||
244 | struct Scheduled *scheduled_out_head; | 246 | struct Scheduled *scheduled_tail; |
245 | |||
246 | struct Scheduled *scheduled_out_tail; | ||
247 | 247 | ||
248 | struct GNUNET_TIME_Relative timeout; | 248 | struct GNUNET_TIME_Relative timeout; |
249 | }; | 249 | }; |
@@ -481,6 +481,27 @@ GNUNET_SCHEDULER_shutdown () | |||
481 | 481 | ||
482 | 482 | ||
483 | /** | 483 | /** |
484 | * Output stack trace of task @a t. | ||
485 | * | ||
486 | * @param t task to dump stack trace of | ||
487 | */ | ||
488 | static void | ||
489 | dump_backtrace (struct GNUNET_SCHEDULER_Task *t) | ||
490 | { | ||
491 | #if EXECINFO | ||
492 | unsigned int i; | ||
493 | |||
494 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
495 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
496 | "Task %p trace %u: %s\n", | ||
497 | t, | ||
498 | i, | ||
499 | t->backtrace_strings[i]); | ||
500 | #endif | ||
501 | } | ||
502 | |||
503 | |||
504 | /** | ||
484 | * Destroy a task (release associated resources) | 505 | * Destroy a task (release associated resources) |
485 | * | 506 | * |
486 | * @param t task to destroy | 507 | * @param t task to destroy |
@@ -524,27 +545,6 @@ destroy_task (struct GNUNET_SCHEDULER_Task *t) | |||
524 | 545 | ||
525 | 546 | ||
526 | /** | 547 | /** |
527 | * Output stack trace of task @a t. | ||
528 | * | ||
529 | * @param t task to dump stack trace of | ||
530 | */ | ||
531 | static void | ||
532 | dump_backtrace (struct GNUNET_SCHEDULER_Task *t) | ||
533 | { | ||
534 | #if EXECINFO | ||
535 | unsigned int i; | ||
536 | |||
537 | for (i = 0; i < t->num_backtrace_strings; i++) | ||
538 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
539 | "Task %p trace %u: %s\n", | ||
540 | t, | ||
541 | i, | ||
542 | t->backtrace_strings[i]); | ||
543 | #endif | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Pipe used to communicate shutdown via signal. | 548 | * Pipe used to communicate shutdown via signal. |
549 | */ | 549 | */ |
550 | static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle; | 550 | static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle; |
@@ -645,6 +645,34 @@ GNUNET_SCHEDULER_check_lifeness () | |||
645 | } | 645 | } |
646 | 646 | ||
647 | 647 | ||
648 | void | ||
649 | shutdown_if_no_lifeness () | ||
650 | { | ||
651 | struct GNUNET_SCHEDULER_Task *t; | ||
652 | |||
653 | if (ready_count > 0) | ||
654 | return; | ||
655 | for (t = pending_head; NULL != t; t = t->next) | ||
656 | if (GNUNET_YES == t->lifeness) | ||
657 | return; | ||
658 | for (t = shutdown_head; NULL != t; t = t->next) | ||
659 | if (GNUNET_YES == t->lifeness) | ||
660 | return; | ||
661 | for (t = pending_timeout_head; NULL != t; t = t->next) | ||
662 | if (GNUNET_YES == t->lifeness) | ||
663 | return; | ||
664 | /* No lifeness! Cancel all pending tasks the driver knows about and shutdown */ | ||
665 | t = pending_head; | ||
666 | while (NULL != t) | ||
667 | { | ||
668 | struct GNUNET_SCHEDULER_Task *next = t->next; | ||
669 | GNUNET_SCHEDULER_cancel (t); | ||
670 | t = next; | ||
671 | } | ||
672 | GNUNET_SCHEDULER_shutdown (); | ||
673 | } | ||
674 | |||
675 | |||
648 | /** | 676 | /** |
649 | * Initialize and run scheduler. This function will return when all | 677 | * Initialize and run scheduler. This function will return when all |
650 | * tasks have completed. On systems with signals, receiving a SIGTERM | 678 | * tasks have completed. On systems with signals, receiving a SIGTERM |
@@ -664,10 +692,8 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_TaskCallback task, | |||
664 | void *task_cls) | 692 | void *task_cls) |
665 | { | 693 | { |
666 | struct GNUNET_SCHEDULER_Driver *driver; | 694 | struct GNUNET_SCHEDULER_Driver *driver; |
667 | struct DriverContext context = {.scheduled_in_head = NULL, | 695 | struct DriverContext context = {.scheduled_head = NULL, |
668 | .scheduled_in_tail = NULL, | 696 | .scheduled_tail = NULL, |
669 | .scheduled_out_head = NULL, | ||
670 | .scheduled_out_tail = NULL, | ||
671 | .timeout = GNUNET_TIME_UNIT_FOREVER_REL}; | 697 | .timeout = GNUNET_TIME_UNIT_FOREVER_REL}; |
672 | 698 | ||
673 | driver = GNUNET_SCHEDULER_driver_select (); | 699 | driver = GNUNET_SCHEDULER_driver_select (); |
@@ -731,6 +757,9 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, | |||
731 | const struct GNUNET_DISK_FileHandle *const *write_fh, | 757 | const struct GNUNET_DISK_FileHandle *const *write_fh, |
732 | unsigned int write_fh_len) | 758 | unsigned int write_fh_len) |
733 | { | 759 | { |
760 | // FIXME: if we have exactly two network handles / exactly two file handles | ||
761 | // and they are equal, we can make one FdInfo with both | ||
762 | // GNUNET_SCHEDULER_ET_IN and GNUNET_SCHEDULER_ET_OUT set. | ||
734 | struct GNUNET_SCHEDULER_FdInfo *fdi; | 763 | struct GNUNET_SCHEDULER_FdInfo *fdi; |
735 | 764 | ||
736 | t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len; | 765 | t->fds_len = read_nh_len + write_nh_len + read_fh_len + write_fh_len; |
@@ -818,20 +847,39 @@ init_fd_info (struct GNUNET_SCHEDULER_Task *t, | |||
818 | } | 847 | } |
819 | 848 | ||
820 | 849 | ||
821 | void scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver_func)()) | 850 | /** |
851 | * calls the given function @a func on each FdInfo related to @a t. | ||
852 | * Optionally updates the event type field in each FdInfo after calling | ||
853 | * @a func. | ||
854 | * | ||
855 | * @param t the task | ||
856 | * @param driver_func the function to call with each FdInfo contained in | ||
857 | * in @a t | ||
858 | * @param if_not_ready only call @a driver_func on FdInfos that are not | ||
859 | * ready | ||
860 | * @param et the event type to be set in each FdInfo after calling | ||
861 | * @a driver_func on it, or -1 if no updating not desired. | ||
862 | */ | ||
863 | void scheduler_multi_function_call (struct GNUNET_SCHEDULER_Task *t, | ||
864 | int (*driver_func)(), | ||
865 | int if_not_ready, | ||
866 | enum GNUNET_SCHEDULER_EventType et) | ||
822 | { | 867 | { |
868 | struct GNUNET_SCHEDULER_FdInfo *fdi; | ||
823 | int success = GNUNET_YES; | 869 | int success = GNUNET_YES; |
824 | if (t->fds_len > 1) | 870 | |
871 | for (int i = 0; i != t->fds_len; ++i) | ||
825 | { | 872 | { |
826 | for (int i = 0; i < t->fds_len;i++) | 873 | fdi = &t->fds[i]; |
874 | if ((GNUNET_NO == if_not_ready) || (GNUNET_SCHEDULER_ET_NONE == fdi->et)) | ||
827 | { | 875 | { |
828 | success = driver_func (scheduler_driver->cls, t , t->fds+i) && success; | 876 | success = driver_func (scheduler_driver->cls, t, fdi) && success; |
877 | if (et != -1) | ||
878 | { | ||
879 | fdi->et = et; | ||
880 | } | ||
829 | } | 881 | } |
830 | } | 882 | } |
831 | else | ||
832 | { | ||
833 | success = driver_func (scheduler_driver->cls, t , t->fds); | ||
834 | } | ||
835 | if (GNUNET_YES != success) | 883 | if (GNUNET_YES != success) |
836 | { | 884 | { |
837 | LOG (GNUNET_ERROR_TYPE_ERROR, | 885 | LOG (GNUNET_ERROR_TYPE_ERROR, |
@@ -841,7 +889,7 @@ void scheduler_multi_function_call(struct GNUNET_SCHEDULER_Task *t, int (*driver | |||
841 | 889 | ||
842 | 890 | ||
843 | void | 891 | void |
844 | shutdown_task (void *cls) | 892 | shutdown_cb (void *cls) |
845 | { | 893 | { |
846 | char c; | 894 | char c; |
847 | const struct GNUNET_DISK_FileHandle *pr; | 895 | const struct GNUNET_DISK_FileHandle *pr; |
@@ -900,7 +948,7 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) | |||
900 | GNUNET_CONTAINER_DLL_remove (pending_head, | 948 | GNUNET_CONTAINER_DLL_remove (pending_head, |
901 | pending_tail, | 949 | pending_tail, |
902 | task); | 950 | task); |
903 | scheduler_multi_function_call(task, scheduler_driver->del); | 951 | scheduler_multi_function_call(task, scheduler_driver->del, GNUNET_NO, -1); |
904 | } | 952 | } |
905 | } | 953 | } |
906 | else | 954 | else |
@@ -911,9 +959,6 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Task *task) | |||
911 | task); | 959 | task); |
912 | ready_count--; | 960 | ready_count--; |
913 | } | 961 | } |
914 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
915 | "Canceling task %p\n", | ||
916 | task); | ||
917 | ret = task->callback_cls; | 962 | ret = task->callback_cls; |
918 | destroy_task (task); | 963 | destroy_task (task); |
919 | return ret; | 964 | return ret; |
@@ -1307,11 +1352,10 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1307 | void *task_cls) | 1352 | void *task_cls) |
1308 | { | 1353 | { |
1309 | struct GNUNET_SCHEDULER_Task *t; | 1354 | struct GNUNET_SCHEDULER_Task *t; |
1310 | 1355 | ||
1311 | GNUNET_assert (NULL != active_task); | 1356 | GNUNET_assert (NULL != active_task); |
1312 | GNUNET_assert (NULL != task); | 1357 | GNUNET_assert (NULL != task); |
1313 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); | 1358 | t = GNUNET_new (struct GNUNET_SCHEDULER_Task); |
1314 | |||
1315 | init_fd_info (t, | 1359 | init_fd_info (t, |
1316 | &read_nh, | 1360 | &read_nh, |
1317 | read_nh ? 1 : 0, | 1361 | read_nh ? 1 : 0, |
@@ -1338,7 +1382,7 @@ add_without_sets (struct GNUNET_TIME_Relative delay, | |||
1338 | GNUNET_CONTAINER_DLL_insert (pending_head, | 1382 | GNUNET_CONTAINER_DLL_insert (pending_head, |
1339 | pending_tail, | 1383 | pending_tail, |
1340 | t); | 1384 | t); |
1341 | scheduler_multi_function_call (t, scheduler_driver->add); | 1385 | scheduler_multi_function_call (t, scheduler_driver->add, GNUNET_NO, GNUNET_SCHEDULER_ET_NONE); |
1342 | max_priority_added = GNUNET_MAX (max_priority_added, | 1386 | max_priority_added = GNUNET_MAX (max_priority_added, |
1343 | t->priority); | 1387 | t->priority); |
1344 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1388 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1785,7 +1829,7 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio, | |||
1785 | GNUNET_CONTAINER_DLL_insert (pending_head, | 1829 | GNUNET_CONTAINER_DLL_insert (pending_head, |
1786 | pending_tail, | 1830 | pending_tail, |
1787 | t); | 1831 | t); |
1788 | scheduler_multi_function_call (t, scheduler_driver->add); | 1832 | scheduler_multi_function_call (t, scheduler_driver->add, GNUNET_NO, GNUNET_SCHEDULER_ET_NONE); |
1789 | max_priority_added = GNUNET_MAX (max_priority_added, | 1833 | max_priority_added = GNUNET_MAX (max_priority_added, |
1790 | t->priority); | 1834 | t->priority); |
1791 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1835 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1825,10 +1869,6 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, | |||
1825 | reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; | 1869 | reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; |
1826 | reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; | 1870 | reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; |
1827 | task->reason = reason; | 1871 | task->reason = reason; |
1828 | if (task->fds_len > 1) | ||
1829 | { | ||
1830 | GNUNET_array_append (task->ready_fds, task->ready_fds_len, *fdi); | ||
1831 | } | ||
1832 | if (GNUNET_NO == task->in_ready_list) | 1872 | if (GNUNET_NO == task->in_ready_list) |
1833 | { | 1873 | { |
1834 | GNUNET_CONTAINER_DLL_remove (pending_head, | 1874 | GNUNET_CONTAINER_DLL_remove (pending_head, |
@@ -1858,11 +1898,9 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, | |||
1858 | int | 1898 | int |
1859 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | 1899 | GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) |
1860 | { | 1900 | { |
1861 | // FIXME: call check_lifeness here! | ||
1862 | enum GNUNET_SCHEDULER_Priority p; | 1901 | enum GNUNET_SCHEDULER_Priority p; |
1863 | struct GNUNET_SCHEDULER_Task *pos; | 1902 | struct GNUNET_SCHEDULER_Task *pos; |
1864 | struct GNUNET_TIME_Absolute now; | 1903 | struct GNUNET_TIME_Absolute now; |
1865 | int i; | ||
1866 | 1904 | ||
1867 | /* check for tasks that reached the timeout! */ | 1905 | /* check for tasks that reached the timeout! */ |
1868 | now = GNUNET_TIME_absolute_get (); | 1906 | now = GNUNET_TIME_absolute_get (); |
@@ -1879,9 +1917,27 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
1879 | pending_timeout_last = NULL; | 1917 | pending_timeout_last = NULL; |
1880 | queue_ready_task (pos); | 1918 | queue_ready_task (pos); |
1881 | } | 1919 | } |
1920 | pos = pending_head; | ||
1921 | while (NULL != pos) | ||
1922 | { | ||
1923 | struct GNUNET_SCHEDULER_Task *next = pos->next; | ||
1924 | if (now.abs_value_us >= pos->timeout.abs_value_us) | ||
1925 | { | ||
1926 | pos->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; | ||
1927 | GNUNET_CONTAINER_DLL_remove (pending_head, | ||
1928 | pending_tail, | ||
1929 | pos); | ||
1930 | queue_ready_task (pos); | ||
1931 | } | ||
1932 | pos = next; | ||
1933 | } | ||
1882 | 1934 | ||
1883 | if (0 == ready_count) | 1935 | if (0 == ready_count) |
1936 | { | ||
1937 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1938 | "no tasks run!\n"); | ||
1884 | return GNUNET_NO; | 1939 | return GNUNET_NO; |
1940 | } | ||
1885 | 1941 | ||
1886 | /* find out which task priority level we are going to | 1942 | /* find out which task priority level we are going to |
1887 | process this time */ | 1943 | process this time */ |
@@ -1921,41 +1977,36 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) | |||
1921 | tc.reason = pos->reason; | 1977 | tc.reason = pos->reason; |
1922 | GNUNET_NETWORK_fdset_zero (sh->rs); | 1978 | GNUNET_NETWORK_fdset_zero (sh->rs); |
1923 | GNUNET_NETWORK_fdset_zero (sh->ws); | 1979 | GNUNET_NETWORK_fdset_zero (sh->ws); |
1924 | tc.fds_len = pos->ready_fds_len; | 1980 | // FIXME: do we have to remove FdInfos from fds if they are not ready? |
1925 | tc.fds = pos->ready_fds; | 1981 | tc.fds_len = pos->fds_len; |
1926 | for (i = 0; i != pos->ready_fds_len; ++i) | 1982 | tc.fds = pos->fds; |
1983 | for (int i = 0; i != pos->fds_len; ++i) | ||
1927 | { | 1984 | { |
1928 | struct GNUNET_SCHEDULER_FdInfo *fdi = pos->ready_fds + i; | 1985 | struct GNUNET_SCHEDULER_FdInfo *fdi = &pos->fds[i]; |
1929 | if (GNUNET_SCHEDULER_ET_IN == fdi->et) | 1986 | if (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) |
1930 | { | 1987 | { |
1931 | GNUNET_NETWORK_fdset_set_native (sh->rs, | 1988 | GNUNET_NETWORK_fdset_set_native (sh->rs, |
1932 | fdi->sock); | 1989 | fdi->sock); |
1933 | } | 1990 | } |
1934 | else if (GNUNET_SCHEDULER_ET_OUT == fdi->et) | 1991 | if (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) |
1935 | { | 1992 | { |
1936 | GNUNET_NETWORK_fdset_set_native (sh->ws, | 1993 | GNUNET_NETWORK_fdset_set_native (sh->ws, |
1937 | fdi->sock); | 1994 | fdi->sock); |
1938 | } | 1995 | } |
1939 | } | 1996 | } |
1940 | if ( (-1 != pos->read_fd) && | ||
1941 | (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) | ||
1942 | GNUNET_NETWORK_fdset_set_native (sh->rs, | ||
1943 | pos->read_fd); | ||
1944 | if ( (-1 != pos->write_fd) && | ||
1945 | (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ) | ||
1946 | GNUNET_NETWORK_fdset_set_native (sh->ws, | ||
1947 | pos->write_fd); | ||
1948 | tc.read_ready = sh->rs; | 1997 | tc.read_ready = sh->rs; |
1949 | tc.write_ready = sh->ws; | 1998 | tc.write_ready = sh->ws; |
1950 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1999 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1951 | "Running task %p\n", | 2000 | "Running task %p\n", |
1952 | pos); | 2001 | pos); |
1953 | pos->callback (pos->callback_cls); | 2002 | pos->callback (pos->callback_cls); |
2003 | scheduler_multi_function_call (pos, scheduler_driver->del, GNUNET_YES, -1); | ||
1954 | active_task = NULL; | 2004 | active_task = NULL; |
1955 | dump_backtrace (pos); | 2005 | dump_backtrace (pos); |
1956 | destroy_task (pos); | 2006 | destroy_task (pos); |
1957 | tasks_run++; | 2007 | tasks_run++; |
1958 | } | 2008 | } |
2009 | shutdown_if_no_lifeness (); | ||
1959 | if (0 == ready_count) | 2010 | if (0 == ready_count) |
1960 | { | 2011 | { |
1961 | scheduler_driver->set_wakeup (scheduler_driver->cls, | 2012 | scheduler_driver->set_wakeup (scheduler_driver->cls, |
@@ -2047,7 +2098,7 @@ GNUNET_SCHEDULER_run_with_driver (const struct GNUNET_SCHEDULER_Driver *driver, | |||
2047 | NULL); | 2098 | NULL); |
2048 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | 2099 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, |
2049 | pr, | 2100 | pr, |
2050 | &shutdown_task, | 2101 | &shutdown_cb, |
2051 | NULL); | 2102 | NULL); |
2052 | current_lifeness = GNUNET_YES; | 2103 | current_lifeness = GNUNET_YES; |
2053 | GNUNET_SCHEDULER_add_with_reason_and_priority (task, | 2104 | GNUNET_SCHEDULER_add_with_reason_and_priority (task, |
@@ -2093,8 +2144,10 @@ select_add (void *cls, | |||
2093 | GNUNET_assert (NULL != context); | 2144 | GNUNET_assert (NULL != context); |
2094 | GNUNET_assert (NULL != task); | 2145 | GNUNET_assert (NULL != task); |
2095 | GNUNET_assert (NULL != fdi); | 2146 | GNUNET_assert (NULL != fdi); |
2147 | GNUNET_assert (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et) || | ||
2148 | 0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)); | ||
2096 | 2149 | ||
2097 | if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (0 > fdi->sock)) | 2150 | if (!((NULL != fdi->fd) ^ (NULL != fdi->fh)) || (fdi->sock < 0)) |
2098 | { | 2151 | { |
2099 | /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ | 2152 | /* exactly one out of {fd, hf} must be != NULL and the OS handle must be valid */ |
2100 | return GNUNET_SYSERR; | 2153 | return GNUNET_SYSERR; |
@@ -2103,29 +2156,31 @@ select_add (void *cls, | |||
2103 | struct Scheduled *scheduled = GNUNET_new (struct Scheduled); | 2156 | struct Scheduled *scheduled = GNUNET_new (struct Scheduled); |
2104 | scheduled->task = task; | 2157 | scheduled->task = task; |
2105 | scheduled->fdi = fdi; | 2158 | scheduled->fdi = fdi; |
2106 | 2159 | scheduled->et = fdi->et; | |
2107 | switch (fdi->et) | 2160 | |
2108 | { | 2161 | GNUNET_CONTAINER_DLL_insert (context->scheduled_head, |
2109 | case GNUNET_SCHEDULER_ET_IN: | 2162 | context->scheduled_tail, |
2110 | { | 2163 | scheduled); |
2111 | GNUNET_CONTAINER_DLL_insert (context->scheduled_in_head, | 2164 | //if (0 != (GNUNET_SCHEDULER_ET_IN & scheduled->et)) |
2112 | context->scheduled_in_tail, | 2165 | //{ |
2113 | scheduled); | 2166 | // GNUNET_CONTAINER_DLL_insert (context->scheduled_in_head, |
2114 | break; | 2167 | // context->scheduled_in_tail, |
2115 | } | 2168 | // scheduled); |
2116 | case GNUNET_SCHEDULER_ET_OUT: | 2169 | //} |
2117 | { | 2170 | //if (0 != (GNUNET_SCHEDULER_ET_OUT & scheduled->et)) |
2118 | GNUNET_CONTAINER_DLL_insert (context->scheduled_out_head, | 2171 | //{ |
2119 | context->scheduled_out_tail, | 2172 | // GNUNET_CONTAINER_DLL_insert (context->scheduled_out_head, |
2120 | scheduled); | 2173 | // context->scheduled_out_tail, |
2121 | break; | 2174 | // scheduled); |
2122 | } | 2175 | //} |
2123 | default: | 2176 | //if (0 != (GNUNET_SCHEDULER_ET_HUP & scheduled->et) || |
2124 | { | 2177 | // 0 != (GNUNET_SCHEDULER_ET_ERR & scheduled->et) || |
2125 | // FIXME: other event types not implemented yet | 2178 | // 0 != (GNUNET_SCHEDULER_ET_PRI & scheduled->et) || |
2126 | GNUNET_assert (0); | 2179 | // 0 != (GNUNET_SCHEDULER_ET_NVAL & scheduled->et)) |
2127 | } | 2180 | //{ |
2128 | } | 2181 | // // FIXME: other event types not implemented yet |
2182 | // GNUNET_assert (0); | ||
2183 | //} | ||
2129 | return GNUNET_OK; | 2184 | return GNUNET_OK; |
2130 | } | 2185 | } |
2131 | 2186 | ||
@@ -2135,47 +2190,24 @@ select_del (void *cls, | |||
2135 | struct GNUNET_SCHEDULER_Task *task, | 2190 | struct GNUNET_SCHEDULER_Task *task, |
2136 | struct GNUNET_SCHEDULER_FdInfo *fdi) | 2191 | struct GNUNET_SCHEDULER_FdInfo *fdi) |
2137 | { | 2192 | { |
2138 | struct DriverContext *context = cls; | 2193 | struct DriverContext *context; |
2139 | GNUNET_assert (NULL != context); | ||
2140 | |||
2141 | int ret = GNUNET_SYSERR; | ||
2142 | struct Scheduled *pos; | 2194 | struct Scheduled *pos; |
2143 | // FIXME: are multiple ORed event types allowed? | 2195 | int ret; |
2144 | switch (fdi->et) | 2196 | |
2145 | { | 2197 | GNUNET_assert (NULL != cls); |
2146 | case GNUNET_SCHEDULER_ET_IN: | 2198 | |
2147 | { | 2199 | context = cls; |
2148 | for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) | 2200 | ret = GNUNET_SYSERR; |
2149 | { | 2201 | for (pos = context->scheduled_head; NULL != pos; pos = pos->next) |
2150 | if (pos->task == task) | ||
2151 | { | ||
2152 | GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, | ||
2153 | context->scheduled_in_tail, | ||
2154 | pos); | ||
2155 | ret = GNUNET_OK; | ||
2156 | } | ||
2157 | } | ||
2158 | break; | ||
2159 | } | ||
2160 | case GNUNET_SCHEDULER_ET_OUT: | ||
2161 | { | 2202 | { |
2162 | for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) | 2203 | if (pos->task == task && pos->fdi == fdi) |
2163 | { | 2204 | { |
2164 | if (pos->task == task) | 2205 | GNUNET_CONTAINER_DLL_remove (context->scheduled_head, |
2165 | { | 2206 | context->scheduled_tail, |
2166 | GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, | 2207 | pos); |
2167 | context->scheduled_out_tail, | 2208 | ret = GNUNET_OK; |
2168 | pos); | 2209 | break; |
2169 | ret = GNUNET_OK; | ||
2170 | } | ||
2171 | } | 2210 | } |
2172 | break; | ||
2173 | } | ||
2174 | default: | ||
2175 | { | ||
2176 | // FIXME: other event types not implemented yet | ||
2177 | GNUNET_assert (0); | ||
2178 | } | ||
2179 | } | 2211 | } |
2180 | return ret; | 2212 | return ret; |
2181 | } | 2213 | } |
@@ -2189,6 +2221,7 @@ select_loop (void *cls, | |||
2189 | struct GNUNET_NETWORK_FDSet *ws; | 2221 | struct GNUNET_NETWORK_FDSet *ws; |
2190 | struct DriverContext *context; | 2222 | struct DriverContext *context; |
2191 | int select_result; | 2223 | int select_result; |
2224 | int tasks_ready; | ||
2192 | unsigned long long last_tr; | 2225 | unsigned long long last_tr; |
2193 | unsigned int busy_wait_warning; | 2226 | unsigned int busy_wait_warning; |
2194 | 2227 | ||
@@ -2196,11 +2229,10 @@ select_loop (void *cls, | |||
2196 | GNUNET_assert (NULL != context); | 2229 | GNUNET_assert (NULL != context); |
2197 | rs = GNUNET_NETWORK_fdset_create (); | 2230 | rs = GNUNET_NETWORK_fdset_create (); |
2198 | ws = GNUNET_NETWORK_fdset_create (); | 2231 | ws = GNUNET_NETWORK_fdset_create (); |
2232 | tasks_ready = GNUNET_NO; | ||
2199 | last_tr = 0; | 2233 | last_tr = 0; |
2200 | busy_wait_warning = 0; | 2234 | busy_wait_warning = 0; |
2201 | // FIXME: remove check_lifeness, instead the condition should be: | 2235 | while (NULL != context->scheduled_head || GNUNET_YES == tasks_ready) |
2202 | // pending_in_head != NULL || pending_out_head != NULL || tasks_ready | ||
2203 | while (GNUNET_YES == GNUNET_SCHEDULER_check_lifeness ()) | ||
2204 | { | 2236 | { |
2205 | LOG (GNUNET_ERROR_TYPE_WARNING, | 2237 | LOG (GNUNET_ERROR_TYPE_WARNING, |
2206 | "[%p] timeout = %s\n", | 2238 | "[%p] timeout = %s\n", |
@@ -2210,13 +2242,16 @@ select_loop (void *cls, | |||
2210 | GNUNET_NETWORK_fdset_zero (rs); | 2242 | GNUNET_NETWORK_fdset_zero (rs); |
2211 | GNUNET_NETWORK_fdset_zero (ws); | 2243 | GNUNET_NETWORK_fdset_zero (ws); |
2212 | struct Scheduled *pos; | 2244 | struct Scheduled *pos; |
2213 | for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) | 2245 | for (pos = context->scheduled_head; NULL != pos; pos = pos->next) |
2214 | { | ||
2215 | GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock); | ||
2216 | } | ||
2217 | for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) | ||
2218 | { | 2246 | { |
2219 | GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock); | 2247 | if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et)) |
2248 | { | ||
2249 | GNUNET_NETWORK_fdset_set_native (rs, pos->fdi->sock); | ||
2250 | } | ||
2251 | if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et)) | ||
2252 | { | ||
2253 | GNUNET_NETWORK_fdset_set_native (ws, pos->fdi->sock); | ||
2254 | } | ||
2220 | } | 2255 | } |
2221 | if (NULL == scheduler_select) | 2256 | if (NULL == scheduler_select) |
2222 | { | 2257 | { |
@@ -2235,6 +2270,8 @@ select_loop (void *cls, | |||
2235 | } | 2270 | } |
2236 | if (select_result == GNUNET_SYSERR) | 2271 | if (select_result == GNUNET_SYSERR) |
2237 | { | 2272 | { |
2273 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2274 | "select_result = GNUNET_SYSERR\n"); | ||
2238 | if (errno == EINTR) | 2275 | if (errno == EINTR) |
2239 | continue; | 2276 | continue; |
2240 | 2277 | ||
@@ -2293,27 +2330,30 @@ select_loop (void *cls, | |||
2293 | //GNUNET_assert (0); | 2330 | //GNUNET_assert (0); |
2294 | short_wait (100); /* mitigate */ | 2331 | short_wait (100); /* mitigate */ |
2295 | } | 2332 | } |
2296 | for (pos = context->scheduled_in_head; NULL != pos; pos = pos->next) | 2333 | for (pos = context->scheduled_head; NULL != pos; pos = pos->next) |
2297 | { | 2334 | { |
2298 | if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, pos->fdi->sock)) | 2335 | int is_ready = GNUNET_NO; |
2336 | if (0 != (GNUNET_SCHEDULER_ET_IN & pos->et) && | ||
2337 | GNUNET_YES == GNUNET_NETWORK_fdset_test_native (rs, pos->fdi->sock)) | ||
2299 | { | 2338 | { |
2300 | GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, | 2339 | pos->fdi->et |= GNUNET_SCHEDULER_ET_IN; |
2301 | context->scheduled_in_tail, | 2340 | is_ready = GNUNET_YES; |
2302 | pos); | ||
2303 | GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); | ||
2304 | } | 2341 | } |
2305 | } | 2342 | if (0 != (GNUNET_SCHEDULER_ET_OUT & pos->et) && |
2306 | for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) | 2343 | GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, pos->fdi->sock)) |
2307 | { | 2344 | { |
2308 | if (GNUNET_YES == GNUNET_NETWORK_fdset_test_native (ws, pos->fdi->sock)) | 2345 | pos->fdi->et |= GNUNET_SCHEDULER_ET_OUT; |
2346 | is_ready = GNUNET_YES; | ||
2347 | } | ||
2348 | if (GNUNET_YES == is_ready) | ||
2309 | { | 2349 | { |
2310 | GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, | 2350 | GNUNET_CONTAINER_DLL_remove (context->scheduled_head, |
2311 | context->scheduled_out_tail, | 2351 | context->scheduled_tail, |
2312 | pos); | 2352 | pos); |
2313 | GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); | 2353 | GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi); |
2314 | } | 2354 | } |
2315 | } | 2355 | } |
2316 | int tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); | 2356 | tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); |
2317 | LOG (GNUNET_ERROR_TYPE_WARNING, | 2357 | LOG (GNUNET_ERROR_TYPE_WARNING, |
2318 | "[%p] tasks_ready: %d\n", | 2358 | "[%p] tasks_ready: %d\n", |
2319 | sh, | 2359 | sh, |