aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlurchi <lurchi@strangeplace.net>2017-08-18 16:17:28 +0200
committerlurchi <lurchi@strangeplace.net>2017-08-18 16:17:28 +0200
commite29921e503d8da33f0b9b15302288c5572ec9bf4 (patch)
tree0bf5efe2ea136fd292ffc6699214b2800cd09ef4 /src
parent59837ecc5f54c39322cc5afba2dfc9fed154a8fe (diff)
downloadgnunet-e29921e503d8da33f0b9b15302288c5572ec9bf4.tar.gz
gnunet-e29921e503d8da33f0b9b15302288c5572ec9bf4.zip
implement bookkeeping about which FDs related to a tasks have been marked ready (required API change in GNUNET_SCHEDULER_task_ready)
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_scheduler_lib.h4
-rw-r--r--src/util/scheduler.c139
2 files changed, 86 insertions, 57 deletions
diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h
index dea0a006a..5f9389726 100644
--- a/src/include/gnunet_scheduler_lib.h
+++ b/src/include/gnunet_scheduler_lib.h
@@ -222,11 +222,11 @@ struct GNUNET_SCHEDULER_TaskContext
222 * that the task is ready (with the respective priority). 222 * that the task is ready (with the respective priority).
223 * 223 *
224 * @param task the task that is ready 224 * @param task the task that is ready
225 * @param et information about why the task is ready 225 * @param fdi information about the related FD
226 */ 226 */
227void 227void
228GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, 228GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
229 enum GNUNET_SCHEDULER_EventType et); 229 struct GNUNET_SCHEDULER_FdInfo *fdi);
230 230
231 231
232/** 232/**
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 19ec4efeb..33aba9ad6 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -148,6 +148,24 @@ struct GNUNET_SCHEDULER_Task
148 * Absolute timeout value for the task, or 148 * Absolute timeout value for the task, or
149 * #GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout". 149 * #GNUNET_TIME_UNIT_FOREVER_ABS for "no timeout".
150 */ 150 */
151
152 /**
153 * Size of the @e fds array.
154 */
155 unsigned int fds_len;
156
157 /**
158 * if this task is related to multiple FDs this array contains
159 * all FdInfo structs that were marked as ready by calling
160 * #GNUNET_SCHEDULER_task_ready
161 */
162 struct GNUNET_SCHEDULER_FdInfo *ready_fds;
163
164 /**
165 * Size of the @e ready_fds array
166 */
167 unsigned int ready_fds_len;
168
151 struct GNUNET_TIME_Absolute timeout; 169 struct GNUNET_TIME_Absolute timeout;
152 170
153#if PROFILE_DELAYS 171#if PROFILE_DELAYS
@@ -158,11 +176,6 @@ struct GNUNET_SCHEDULER_Task
158#endif 176#endif
159 177
160 /** 178 /**
161 * Size of the @e fds array.
162 */
163 unsigned int fds_len;
164
165 /**
166 * Why is the task ready? Set after task is added to ready queue. 179 * Why is the task ready? Set after task is added to ready queue.
167 * Initially set to zero. All reasons that have already been 180 * Initially set to zero. All reasons that have already been
168 * satisfied (i.e. read or write ready) will be set over time. 181 * satisfied (i.e. read or write ready) will be set over time.
@@ -476,6 +489,29 @@ GNUNET_SCHEDULER_shutdown ()
476} 489}
477 490
478 491
492static void
493destroy_fd_info_list (struct GNUNET_SCHEDULER_FdInfo *fds, unsigned int fds_len)
494{
495 unsigned int i;
496 for (i = 0; i != fds_len; ++i)
497 {
498 const struct GNUNET_SCHEDULER_FdInfo *fdi = fds + i;
499 if (fdi->fd)
500 {
501 GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fdi->fd);
502 }
503 if (fdi->fh)
504 {
505 // FIXME: on WIN32 this is not enough! A function
506 // GNUNET_DISK_file_free_memory_only would be nice
507 GNUNET_free ((void *) fdi->fh);
508 }
509 }
510 /* free the array */
511 GNUNET_array_grow (fds, fds_len, 0);
512}
513
514
479/** 515/**
480 * Destroy a task (release associated resources) 516 * Destroy a task (release associated resources)
481 * 517 *
@@ -484,31 +520,16 @@ GNUNET_SCHEDULER_shutdown ()
484static void 520static void
485destroy_task (struct GNUNET_SCHEDULER_Task *t) 521destroy_task (struct GNUNET_SCHEDULER_Task *t)
486{ 522{
487 // FIXME: destroy fds!
488 if (t->fds_len > 1) 523 if (t->fds_len > 1)
489 { 524 {
490 size_t i; 525 destroy_fd_info_list ((struct GNUNET_SCHEDULER_FdInfo *) t->fds,
491 for (i = 0; i != t->fds_len; ++i) 526 t->fds_len);
492 { 527 }
493 const struct GNUNET_SCHEDULER_FdInfo *fdi = t->fds + i; 528 if (t->ready_fds_len > 0)
494 if (fdi->fd) 529 {
495 { 530 destroy_fd_info_list ((struct GNUNET_SCHEDULER_FdInfo *) t->ready_fds,
496 GNUNET_NETWORK_socket_free_memory_only_ ((struct GNUNET_NETWORK_Handle *) fdi->fd); 531 t->ready_fds_len);
497 }
498 if (fdi->fh)
499 {
500 // FIXME: on WIN32 this is not enough! A function
501 // GNUNET_DISK_file_free_memory_only would be nice
502 GNUNET_free ((void *) fdi->fh);
503 }
504 }
505 /* free the array */
506 GNUNET_array_grow (t->fds, t->fds_len, 0);
507 } 532 }
508 //if (NULL != t->read_set)
509 // GNUNET_NETWORK_fdset_destroy (t->read_set);
510 //if (NULL != t->write_set)
511 // GNUNET_NETWORK_fdset_destroy (t->write_set);
512#if EXECINFO 533#if EXECINFO
513 GNUNET_free (t->backtrace_strings); 534 GNUNET_free (t->backtrace_strings);
514#endif 535#endif
@@ -1318,11 +1339,6 @@ add_without_sets (struct GNUNET_TIME_Relative delay,
1318 read_fh ? 1 : 0, 1339 read_fh ? 1 : 0,
1319 &write_fh, 1340 &write_fh,
1320 write_fh ? 1 : 0); 1341 write_fh ? 1 : 0);
1321
1322 //int read_fds[2] = {GNUNET_NETWORK_get_fd (read_nh), read_fh->fd};
1323 //int write_fds[2] = {GNUNET_NETWORK_get_fd (write_nh), write_fh->fd};
1324 //init_fd_info (t, read_fds, 2, write_fds, 2);
1325 //init_fd_info (t, read_nh, write_nh, read_fh, write_fh);
1326 t->callback = task; 1342 t->callback = task;
1327 t->callback_cls = task_cls; 1343 t->callback_cls = task_cls;
1328#if DEBUG_FDS 1344#if DEBUG_FDS
@@ -1826,11 +1842,11 @@ GNUNET_SCHEDULER_add_select (enum GNUNET_SCHEDULER_Priority prio,
1826 * that the task is ready (with the respective priority). 1842 * that the task is ready (with the respective priority).
1827 * 1843 *
1828 * @param task the task that is ready, NULL for wake up calls 1844 * @param task the task that is ready, NULL for wake up calls
1829 * @param et information about why the task is ready 1845 * @param fdi information about the related FD
1830 */ 1846 */
1831void 1847void
1832GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task, 1848GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1833 enum GNUNET_SCHEDULER_EventType et) 1849 struct GNUNET_SCHEDULER_FdInfo *fdi)
1834{ 1850{
1835 enum GNUNET_SCHEDULER_Reason reason; 1851 enum GNUNET_SCHEDULER_Reason reason;
1836 struct GNUNET_TIME_Absolute now; 1852 struct GNUNET_TIME_Absolute now;
@@ -1840,24 +1856,24 @@ GNUNET_SCHEDULER_task_ready (struct GNUNET_SCHEDULER_Task *task,
1840 if (now.abs_value_us >= task->timeout.abs_value_us) 1856 if (now.abs_value_us >= task->timeout.abs_value_us)
1841 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; 1857 reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
1842 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) && 1858 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
1843 (0 != (GNUNET_SCHEDULER_ET_IN & et)) ) 1859 (0 != (GNUNET_SCHEDULER_ET_IN & fdi->et)) )
1844 reason |= GNUNET_SCHEDULER_REASON_READ_READY; 1860 reason |= GNUNET_SCHEDULER_REASON_READ_READY;
1845 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) && 1861 if ( (0 == (reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) &&
1846 (0 != (GNUNET_SCHEDULER_ET_OUT & et)) ) 1862 (0 != (GNUNET_SCHEDULER_ET_OUT & fdi->et)) )
1847 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY; 1863 reason |= GNUNET_SCHEDULER_REASON_WRITE_READY;
1848 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE; 1864 reason |= GNUNET_SCHEDULER_REASON_PREREQ_DONE;
1849
1850
1851
1852
1853 task->reason = reason; 1865 task->reason = reason;
1854 task->fds = &task->fdx; // FIXME: if task contains a list of fds, this is wrong! 1866 if (task->fds_len > 1)
1855 task->fdx.et = et; 1867 {
1856 task->fds_len = 1; 1868 GNUNET_array_append (task->ready_fds, task->ready_fds_len, *fdi);
1857 GNUNET_CONTAINER_DLL_remove (pending_head, 1869 }
1858 pending_tail, 1870 if (GNUNET_NO == task->in_ready_list)
1859 task); 1871 {
1860 queue_ready_task (task); 1872 GNUNET_CONTAINER_DLL_remove (pending_head,
1873 pending_tail,
1874 task);
1875 queue_ready_task (task);
1876 }
1861} 1877}
1862 1878
1863 1879
@@ -1884,6 +1900,7 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1884 enum GNUNET_SCHEDULER_Priority p; 1900 enum GNUNET_SCHEDULER_Priority p;
1885 struct GNUNET_SCHEDULER_Task *pos; 1901 struct GNUNET_SCHEDULER_Task *pos;
1886 struct GNUNET_TIME_Absolute now; 1902 struct GNUNET_TIME_Absolute now;
1903 int i;
1887 1904
1888 /* check for tasks that reached the timeout! */ 1905 /* check for tasks that reached the timeout! */
1889 now = GNUNET_TIME_absolute_get (); 1906 now = GNUNET_TIME_absolute_get ();
@@ -1942,20 +1959,32 @@ GNUNET_SCHEDULER_run_from_driver (struct GNUNET_SCHEDULER_Handle *sh)
1942 tc.reason = pos->reason; 1959 tc.reason = pos->reason;
1943 GNUNET_NETWORK_fdset_zero (sh->rs); 1960 GNUNET_NETWORK_fdset_zero (sh->rs);
1944 GNUNET_NETWORK_fdset_zero (sh->ws); 1961 GNUNET_NETWORK_fdset_zero (sh->ws);
1945 tc.fds_len = pos->fds_len; 1962 tc.fds_len = pos->ready_fds_len;
1946 tc.fds = pos->fds; 1963 tc.fds = pos->ready_fds;
1947 //tc.read_ready = (NULL == pos->read_set) ? sh->rs : pos->read_set; 1964 for (i = 0; i != pos->ready_fds_len; ++i)
1948 tc.read_ready = sh->rs; 1965 {
1966 struct GNUNET_SCHEDULER_FdInfo *fdi = pos->ready_fds + i;
1967 if (GNUNET_SCHEDULER_ET_IN == fdi->et)
1968 {
1969 GNUNET_NETWORK_fdset_set_native (sh->rs,
1970 fdi->sock);
1971 }
1972 else if (GNUNET_SCHEDULER_ET_OUT == fdi->et)
1973 {
1974 GNUNET_NETWORK_fdset_set_native (sh->ws,
1975 fdi->sock);
1976 }
1977 }
1949 if ( (-1 != pos->read_fd) && 1978 if ( (-1 != pos->read_fd) &&
1950 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) ) 1979 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_READ_READY)) )
1951 GNUNET_NETWORK_fdset_set_native (sh->rs, 1980 GNUNET_NETWORK_fdset_set_native (sh->rs,
1952 pos->read_fd); 1981 pos->read_fd);
1953 //tc.write_ready = (NULL == pos->write_set) ? sh->ws : pos->write_set;
1954 tc.write_ready = sh->ws;
1955 if ( (-1 != pos->write_fd) && 1982 if ( (-1 != pos->write_fd) &&
1956 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ) 1983 (0 != (pos->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) )
1957 GNUNET_NETWORK_fdset_set_native (sh->ws, 1984 GNUNET_NETWORK_fdset_set_native (sh->ws,
1958 pos->write_fd); 1985 pos->write_fd);
1986 tc.read_ready = sh->rs;
1987 tc.write_ready = sh->ws;
1959 LOG (GNUNET_ERROR_TYPE_DEBUG, 1988 LOG (GNUNET_ERROR_TYPE_DEBUG,
1960 "Running task %p\n", 1989 "Running task %p\n",
1961 pos); 1990 pos);
@@ -2309,7 +2338,7 @@ select_loop (void *cls,
2309 GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head, 2338 GNUNET_CONTAINER_DLL_remove (context->scheduled_in_head,
2310 context->scheduled_in_tail, 2339 context->scheduled_in_tail,
2311 pos); 2340 pos);
2312 GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_IN); 2341 GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi);
2313 } 2342 }
2314 } 2343 }
2315 for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next) 2344 for (pos = context->scheduled_out_head; NULL != pos; pos = pos->next)
@@ -2319,7 +2348,7 @@ select_loop (void *cls,
2319 GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head, 2348 GNUNET_CONTAINER_DLL_remove (context->scheduled_out_head,
2320 context->scheduled_out_tail, 2349 context->scheduled_out_tail,
2321 pos); 2350 pos);
2322 GNUNET_SCHEDULER_task_ready (pos->task, GNUNET_SCHEDULER_ET_OUT); 2351 GNUNET_SCHEDULER_task_ready (pos->task, pos->fdi);
2323 } 2352 }
2324 } 2353 }
2325 int tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh); 2354 int tasks_ready = GNUNET_SCHEDULER_run_from_driver (sh);