aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlurchi <lurchi@strangeplace.net>2017-08-23 15:44:52 +0200
committerlurchi <lurchi@strangeplace.net>2017-08-23 15:44:52 +0200
commit357181530f9089ee30ba88c55ed429ec58505357 (patch)
tree4a4b36ae19130ed67ff293d3635796217e77b9f5 /src
parent863211feb62023e37cad3f57cc72b2bb30262383 (diff)
downloadgnunet-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.c346
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 */
238struct DriverContext 242struct 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 */
488static void
489dump_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 */
531static void
532dump_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 */
550static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle; 550static struct GNUNET_DISK_PipeHandle *shutdown_pipe_handle;
@@ -645,6 +645,34 @@ GNUNET_SCHEDULER_check_lifeness ()
645} 645}
646 646
647 647
648void
649shutdown_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
821void 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 */
863void 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
843void 891void
844shutdown_task (void *cls) 892shutdown_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,
1858int 1898int
1859GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh) 1899GNUNET_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,