aboutsummaryrefslogtreecommitdiff
path: root/src/util/scheduler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/scheduler.c')
-rw-r--r--src/util/scheduler.c555
1 files changed, 262 insertions, 293 deletions
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 2bb356eb6..16f65b457 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -95,11 +95,6 @@ struct Task
95 */ 95 */
96 enum GNUNET_SCHEDULER_Priority priority; 96 enum GNUNET_SCHEDULER_Priority priority;
97 97
98 /**
99 * Should this task be run on shutdown?
100 */
101 int run_on_shutdown;
102
103}; 98};
104 99
105 100
@@ -135,12 +130,6 @@ struct GNUNET_SCHEDULER_Handle
135 GNUNET_SCHEDULER_TaskIdentifier lowest_pending_id; 130 GNUNET_SCHEDULER_TaskIdentifier lowest_pending_id;
136 131
137 /** 132 /**
138 * GNUNET_NO if we are running normally,
139 * GNUNET_YES if we are in shutdown mode.
140 */
141 int shutdown;
142
143 /**
144 * Number of tasks on the ready list. 133 * Number of tasks on the ready list.
145 */ 134 */
146 unsigned int ready_count; 135 unsigned int ready_count;
@@ -260,6 +249,8 @@ update_sets (struct GNUNET_SCHEDULER_Handle *sched,
260 GNUNET_NETWORK_fdset_add (rs, pos->read_set); 249 GNUNET_NETWORK_fdset_add (rs, pos->read_set);
261 if (pos->write_set != NULL) 250 if (pos->write_set != NULL)
262 GNUNET_NETWORK_fdset_add (ws, pos->write_set); 251 GNUNET_NETWORK_fdset_add (ws, pos->write_set);
252 if (pos->reason != 0)
253 *timeout = GNUNET_TIME_UNIT_ZERO;
263 pos = pos->next; 254 pos = pos->next;
264 } 255 }
265} 256}
@@ -309,12 +300,7 @@ is_ready (struct GNUNET_SCHEDULER_Handle *sched,
309 const struct GNUNET_NETWORK_FDSet *rs, 300 const struct GNUNET_NETWORK_FDSet *rs,
310 const struct GNUNET_NETWORK_FDSet *ws) 301 const struct GNUNET_NETWORK_FDSet *ws)
311{ 302{
312 if ((GNUNET_NO == task->run_on_shutdown) && (GNUNET_YES == sched->shutdown)) 303 if (now.value >= task->timeout.value)
313 return GNUNET_NO;
314 if ((GNUNET_YES == task->run_on_shutdown) &&
315 (GNUNET_YES == sched->shutdown))
316 task->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN;
317 if (now.value >= task->timeout.value)
318 task->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT; 304 task->reason |= GNUNET_SCHEDULER_REASON_TIMEOUT;
319 if ((0 == (task->reason & GNUNET_SCHEDULER_REASON_READ_READY)) && 305 if ((0 == (task->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
320 (rs != NULL) && (set_overlaps (rs, task->read_set))) 306 (rs != NULL) && (set_overlaps (rs, task->read_set)))
@@ -395,6 +381,32 @@ check_ready (struct GNUNET_SCHEDULER_Handle *handle,
395 381
396 382
397/** 383/**
384 * Request the shutdown of a scheduler. Marks all currently
385 * pending tasks as ready because of shutdown. This will
386 * cause all tasks to run (as soon as possible, respecting
387 * priorities and prerequisite tasks). Note that tasks
388 * scheduled AFTER this call may still be delayed arbitrarily.
389 *
390 * @param sched the scheduler
391 */
392void
393GNUNET_SCHEDULER_shutdown (struct GNUNET_SCHEDULER_Handle *sched)
394{
395 struct Task *pos;
396
397 pos = sched->pending;
398 while (pos != NULL)
399 {
400 pos->reason |= GNUNET_SCHEDULER_REASON_SHUTDOWN;
401 /* we don't move the task into the ready queue yet; check_ready
402 will do that later, possibly adding additional
403 readyness-factors */
404 pos = pos->next;
405 }
406}
407
408
409/**
398 * Destroy a task (release associated resources) 410 * Destroy a task (release associated resources)
399 * 411 *
400 * @param t task to destroy 412 * @param t task to destroy
@@ -415,7 +427,7 @@ destroy_task (struct Task *t)
415 * empty. Keep running tasks until we are either no longer running 427 * empty. Keep running tasks until we are either no longer running
416 * "URGENT" tasks or until we have at least one "pending" task (which 428 * "URGENT" tasks or until we have at least one "pending" task (which
417 * may become ready, hence we should select on it). Naturally, if 429 * may become ready, hence we should select on it). Naturally, if
418 * there are no more ready tasks, we also return. 430 * there are no more ready tasks, we also return.
419 * 431 *
420 * @param sched the scheduler 432 * @param sched the scheduler
421 */ 433 */
@@ -459,7 +471,7 @@ run_ready (struct GNUNET_SCHEDULER_Handle *sched)
459 while ((sched->pending == NULL) || (p == GNUNET_SCHEDULER_PRIORITY_URGENT)); 471 while ((sched->pending == NULL) || (p == GNUNET_SCHEDULER_PRIORITY_URGENT));
460} 472}
461 473
462 474#ifndef MINGW
463/** 475/**
464 * Pipe used to communicate shutdown via signal. 476 * Pipe used to communicate shutdown via signal.
465 */ 477 */
@@ -478,19 +490,25 @@ sighandler_shutdown ()
478 (sigpipe, GNUNET_DISK_PIPE_END_WRITE), &c, 490 (sigpipe, GNUNET_DISK_PIPE_END_WRITE), &c,
479 sizeof (c)); 491 sizeof (c));
480} 492}
493#endif
481 494
482 495
483/** 496/**
484 * Initialize a scheduler using this thread. This function will 497 * Initialize and run scheduler. This function will return when all
485 * return when either a shutdown was initiated (via signal) and all 498 * tasks have completed. On systems with signals, receiving a SIGTERM
486 * tasks marked to "run_on_shutdown" have been completed or when all 499 * (and other similar signals) will cause "GNUNET_SCHEDULER_shutdown"
487 * tasks in general have been completed. 500 * to be run after the active task is complete. As a result, SIGTERM
501 * causes all active tasks to be scheduled with reason
502 * "GNUNET_SCHEDULER_REASON_SHUTDOWN". (However, tasks added
503 * afterwards will execute normally!). Note that any particular signal
504 * will only shut down one scheduler; applications should always only
505 * create a single scheduler.
488 * 506 *
489 * @param task task to run immediately 507 * @param task task to run immediately
490 * @param cls closure of task 508 * @param task_cls closure of task
491 */ 509 */
492void 510void
493GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *cls) 511GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls)
494{ 512{
495 struct GNUNET_SCHEDULER_Handle sched; 513 struct GNUNET_SCHEDULER_Handle sched;
496 struct GNUNET_NETWORK_FDSet *rs; 514 struct GNUNET_NETWORK_FDSet *rs;
@@ -501,12 +519,12 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *cls)
501 struct GNUNET_SIGNAL_Context *shc_term; 519 struct GNUNET_SIGNAL_Context *shc_term;
502 struct GNUNET_SIGNAL_Context *shc_quit; 520 struct GNUNET_SIGNAL_Context *shc_quit;
503 struct GNUNET_SIGNAL_Context *shc_hup; 521 struct GNUNET_SIGNAL_Context *shc_hup;
504 struct Task *tpos;
505 unsigned long long last_tr; 522 unsigned long long last_tr;
506 unsigned int busy_wait_warning; 523 unsigned int busy_wait_warning;
507#ifndef MINGW 524#ifndef MINGW
508 const struct GNUNET_DISK_FileHandle *pr; 525 const struct GNUNET_DISK_FileHandle *pr;
509#endif 526#endif
527 char c;
510 528
511 rs = GNUNET_NETWORK_fdset_create (); 529 rs = GNUNET_NETWORK_fdset_create ();
512 ws = GNUNET_NETWORK_fdset_create (); 530 ws = GNUNET_NETWORK_fdset_create ();
@@ -516,38 +534,40 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *cls)
516 GNUNET_assert (sigpipe != NULL); 534 GNUNET_assert (sigpipe != NULL);
517 pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); 535 pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
518 GNUNET_assert (pr != NULL); 536 GNUNET_assert (pr != NULL);
519 shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); 537 shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown);
520 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown); 538 shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown);
521 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, &sighandler_shutdown); 539 shc_quit = GNUNET_SIGNAL_handler_install (SIGQUIT, &sighandler_shutdown);
522 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown); 540 shc_hup = GNUNET_SIGNAL_handler_install (SIGHUP, &sighandler_shutdown);
523#endif 541#endif
524 memset (&sched, 0, sizeof (sched)); 542 memset (&sched, 0, sizeof (sched));
525 sched.current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; 543 sched.current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
526 GNUNET_SCHEDULER_add_continuation (&sched, 544 GNUNET_SCHEDULER_add_continuation (&sched,
527 GNUNET_YES,
528 task, 545 task,
529 cls, GNUNET_SCHEDULER_REASON_STARTUP); 546 task_cls,
547 GNUNET_SCHEDULER_REASON_STARTUP);
530 last_tr = 0; 548 last_tr = 0;
531 busy_wait_warning = 0; 549 busy_wait_warning = 0;
532 while ((GNUNET_NO == sched.shutdown) && 550 while ( (sched.pending != NULL) || (sched.ready_count > 0) )
533 ((sched.pending != NULL) || (sched.ready_count > 0)))
534 { 551 {
535 GNUNET_NETWORK_fdset_zero (rs); 552 GNUNET_NETWORK_fdset_zero (rs);
536 GNUNET_NETWORK_fdset_zero (ws); 553 GNUNET_NETWORK_fdset_zero (ws);
537 timeout = GNUNET_TIME_relative_get_forever (); 554 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
538 update_sets (&sched, rs, ws, &timeout); 555 update_sets (&sched, rs, ws, &timeout);
539#ifndef MINGW
540 GNUNET_NETWORK_fdset_handle_set (rs, pr); 556 GNUNET_NETWORK_fdset_handle_set (rs, pr);
541#endif
542 if (sched.ready_count > 0) 557 if (sched.ready_count > 0)
543 { 558 {
544 /* no blocking, more work already ready! */ 559 /* no blocking, more work already ready! */
545 timeout = GNUNET_TIME_relative_get_zero (); 560 timeout = GNUNET_TIME_UNIT_ZERO;
546 } 561 }
547 ret = GNUNET_NETWORK_socket_select (rs, ws, NULL, timeout); 562 ret = GNUNET_NETWORK_socket_select (rs, ws, NULL, timeout);
548#ifndef MINGW 563#ifndef MINGW
549 if (GNUNET_NETWORK_fdset_handle_isset (rs, pr)) 564 if (GNUNET_NETWORK_fdset_handle_isset (rs, pr))
550 break; 565 {
566 /* consume the signal */
567 GNUNET_DISK_file_read (pr, &c, sizeof(c));
568 /* mark all active tasks as ready due to shutdown */
569 GNUNET_SCHEDULER_shutdown (&sched);
570 }
551#endif 571#endif
552 if (last_tr == sched.tasks_run) 572 if (last_tr == sched.tasks_run)
553 { 573 {
@@ -574,7 +594,6 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *cls)
574 check_ready (&sched, rs, ws); 594 check_ready (&sched, rs, ws);
575 run_ready (&sched); 595 run_ready (&sched);
576 } 596 }
577 sched.shutdown = GNUNET_YES;
578#ifndef MINGW 597#ifndef MINGW
579 GNUNET_SIGNAL_handler_uninstall (shc_int); 598 GNUNET_SIGNAL_handler_uninstall (shc_int);
580 GNUNET_SIGNAL_handler_uninstall (shc_term); 599 GNUNET_SIGNAL_handler_uninstall (shc_term);
@@ -583,36 +602,11 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *cls)
583 GNUNET_DISK_pipe_close (sigpipe); 602 GNUNET_DISK_pipe_close (sigpipe);
584 sigpipe = NULL; 603 sigpipe = NULL;
585#endif 604#endif
586 do
587 {
588 run_ready (&sched);
589 check_ready (&sched, NULL, NULL);
590 }
591 while (sched.ready_count > 0);
592 while (NULL != (tpos = sched.pending))
593 {
594 sched.pending = tpos->next;
595 GNUNET_free (tpos);
596 }
597 GNUNET_NETWORK_fdset_destroy (rs); 605 GNUNET_NETWORK_fdset_destroy (rs);
598 GNUNET_NETWORK_fdset_destroy (ws); 606 GNUNET_NETWORK_fdset_destroy (ws);
599} 607}
600 608
601 609
602/**
603 * Request the shutdown of a scheduler. This function can be used to
604 * stop a scheduling thread when created with the
605 * "GNUNET_SCHEDULER_init_thread" function or from within the signal
606 * handler for signals causing shutdowns.
607 *
608 * @param sched the scheduler
609 */
610void
611GNUNET_SCHEDULER_shutdown (struct GNUNET_SCHEDULER_Handle *sched)
612{
613 sched->shutdown = GNUNET_YES;
614}
615
616 610
617/** 611/**
618 * Get information about the current load of this scheduler. Use this 612 * Get information about the current load of this scheduler. Use this
@@ -715,102 +709,113 @@ GNUNET_SCHEDULER_cancel (struct GNUNET_SCHEDULER_Handle *sched,
715 * and the reason code can be specified. 709 * and the reason code can be specified.
716 * 710 *
717 * @param sched scheduler to use 711 * @param sched scheduler to use
718 * @param run_on_shutdown should this task be run if we are shutting down? 712 * @param task main function of the task
719 * @param main main function of the task 713 * @param task_cls closure for 'main'
720 * @param cls closure for 'main'
721 * @param reason reason for task invocation 714 * @param reason reason for task invocation
722 */ 715 */
723void 716void
724GNUNET_SCHEDULER_add_continuation (struct GNUNET_SCHEDULER_Handle *sched, 717GNUNET_SCHEDULER_add_continuation (struct GNUNET_SCHEDULER_Handle *sched,
725 int run_on_shutdown, 718 GNUNET_SCHEDULER_Task task,
726 GNUNET_SCHEDULER_Task main, 719 void *task_cls,
727 void *cls,
728 enum GNUNET_SCHEDULER_Reason reason) 720 enum GNUNET_SCHEDULER_Reason reason)
729{ 721{
730 struct Task *task; 722 struct Task *t;
731 723
732 task = GNUNET_malloc (sizeof (struct Task)); 724 t = GNUNET_malloc (sizeof (struct Task));
733 task->callback = main; 725 t->callback = task;
734 task->callback_cls = cls; 726 t->callback_cls = task_cls;
735 task->id = ++sched->last_id; 727 t->id = ++sched->last_id;
736 task->reason = reason; 728 t->reason = reason;
737 task->priority = sched->current_priority; 729 t->priority = sched->current_priority;
738 task->run_on_shutdown = run_on_shutdown;
739#if DEBUG_TASKS 730#if DEBUG_TASKS
740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 731 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
741 "Adding continuation task: %llu / %p\n", 732 "Adding continuation task: %llu / %p\n",
742 task->id, task->callback_cls); 733 t->id, t->callback_cls);
743#endif 734#endif
744 queue_ready_task (sched, task); 735 queue_ready_task (sched, t);
745} 736}
746 737
747 738
739
748/** 740/**
749 * Schedule a new task to be run after the specified 741 * Schedule a new task to be run after the specified prerequisite task
750 * prerequisite task has completed. 742 * has completed. It will be run with the priority of the calling
743 * task.
751 * 744 *
752 * @param sched scheduler to use 745 * @param sched scheduler to use
753 * @param run_on_shutdown run on shutdown?
754 * @param prio how important is this task?
755 * @param prerequisite_task run this task after the task with the given 746 * @param prerequisite_task run this task after the task with the given
756 * task identifier completes (and any of our other 747 * task identifier completes (and any of our other
757 * conditions, such as delay, read or write-readyness 748 * conditions, such as delay, read or write-readyness
758 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency 749 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
759 * on completion of other tasks. 750 * on completion of other tasks (this will cause the task to run as
760 * @param main main function of the task 751 * soon as possible).
761 * @param cls closure for 'main' 752 * @param task main function of the task
753 * @param task_cls closure of task
762 * @return unique task identifier for the job 754 * @return unique task identifier for the job
763 * only valid until "main" is started! 755 * only valid until "task" is started!
764 */ 756 */
765GNUNET_SCHEDULER_TaskIdentifier 757GNUNET_SCHEDULER_TaskIdentifier
766GNUNET_SCHEDULER_add_after (struct GNUNET_SCHEDULER_Handle *sched, 758GNUNET_SCHEDULER_add_after (struct GNUNET_SCHEDULER_Handle *sched,
767 int run_on_shutdown,
768 enum GNUNET_SCHEDULER_Priority prio,
769 GNUNET_SCHEDULER_TaskIdentifier prerequisite_task, 759 GNUNET_SCHEDULER_TaskIdentifier prerequisite_task,
770 GNUNET_SCHEDULER_Task main, void *cls) 760 GNUNET_SCHEDULER_Task task,
761 void *task_cls)
771{ 762{
772 return GNUNET_SCHEDULER_add_select (sched, run_on_shutdown, prio, 763 return GNUNET_SCHEDULER_add_select (sched,
764 GNUNET_SCHEDULER_PRIORITY_KEEP,
773 prerequisite_task, 765 prerequisite_task,
774 GNUNET_TIME_UNIT_ZERO, 766 GNUNET_TIME_UNIT_ZERO,
775 NULL, NULL, main, cls); 767 NULL, NULL, task, task_cls);
776} 768}
777 769
778 770
779/** 771/**
772 * Schedule a new task to be run with a specified priority.
773 *
774 * @param sched scheduler to use
775 * @param prio how important is the new task?
776 * @param task main function of the task
777 * @param task_cls closure of task
778 * @return unique task identifier for the job
779 * only valid until "task" is started!
780 */
781GNUNET_SCHEDULER_TaskIdentifier
782GNUNET_SCHEDULER_add_with_priority (struct GNUNET_SCHEDULER_Handle *sched,
783 enum GNUNET_SCHEDULER_Priority prio,
784 GNUNET_SCHEDULER_Task task,
785 void *task_cls)
786{
787 return GNUNET_SCHEDULER_add_select (sched,
788 prio,
789 GNUNET_SCHEDULER_NO_TASK,
790 GNUNET_TIME_UNIT_ZERO,
791 NULL, NULL, task, task_cls);
792}
793
794
795
796/**
780 * Schedule a new task to be run with a specified delay. The task 797 * Schedule a new task to be run with a specified delay. The task
781 * will be scheduled for execution once the delay has expired and the 798 * will be scheduled for execution once the delay has expired. It
782 * prerequisite task has completed. 799 * will be run with the priority of the calling task.
783 * 800 *
784 * @param sched scheduler to use 801 * @param sched scheduler to use
785 * @param run_on_shutdown run on shutdown? You can use this 802 * @param delay when should this operation time out? Use
786 * argument to run a function only during shutdown 803 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
787 * by setting delay to -1. Set this 804 * @param task main function of the task
788 * argument to GNUNET_NO to skip this task if 805 * @param task_cls closure of task
789 * the user requested process termination.
790 * @param prio how important is this task?
791 * @param prerequisite_task run this task after the task with the given
792 * task identifier completes (and any of our other
793 * conditions, such as delay, read or write-readyness
794 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
795 * on completion of other tasks.
796 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever"
797 * @param main main function of the task
798 * @param cls closure of task
799 * @return unique task identifier for the job 806 * @return unique task identifier for the job
800 * only valid until "main" is started! 807 * only valid until "task" is started!
801 */ 808 */
802GNUNET_SCHEDULER_TaskIdentifier 809GNUNET_SCHEDULER_TaskIdentifier
803GNUNET_SCHEDULER_add_delayed (struct GNUNET_SCHEDULER_Handle * sched, 810GNUNET_SCHEDULER_add_delayed (struct GNUNET_SCHEDULER_Handle *sched,
804 int run_on_shutdown,
805 enum GNUNET_SCHEDULER_Priority prio,
806 GNUNET_SCHEDULER_TaskIdentifier
807 prerequisite_task,
808 struct GNUNET_TIME_Relative delay, 811 struct GNUNET_TIME_Relative delay,
809 GNUNET_SCHEDULER_Task main, void *cls) 812 GNUNET_SCHEDULER_Task task,
813 void *task_cls)
810{ 814{
811 return GNUNET_SCHEDULER_add_select (sched, run_on_shutdown, prio, 815 return GNUNET_SCHEDULER_add_select (sched,
812 prerequisite_task, delay, 816 GNUNET_SCHEDULER_PRIORITY_KEEP,
813 NULL, NULL, main, cls); 817 GNUNET_SCHEDULER_NO_TASK, delay,
818 NULL, NULL, task, task_cls);
814} 819}
815 820
816 821
@@ -819,34 +824,24 @@ GNUNET_SCHEDULER_add_delayed (struct GNUNET_SCHEDULER_Handle * sched,
819 * specified file descriptor is ready for reading. The delay can be 824 * specified file descriptor is ready for reading. The delay can be
820 * used as a timeout on the socket being ready. The task will be 825 * used as a timeout on the socket being ready. The task will be
821 * scheduled for execution once either the delay has expired or the 826 * scheduled for execution once either the delay has expired or the
822 * socket operation is ready. 827 * socket operation is ready. It will be run with the priority of
828 * the calling task.
823 * 829 *
824 * @param sched scheduler to use 830 * @param sched scheduler to use
825 * @param run_on_shutdown run on shutdown? Set this 831 * @param delay when should this operation time out? Use
826 * argument to GNUNET_NO to skip this task if 832 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
827 * the user requested process termination.
828 * @param prio how important is this task?
829 * @param prerequisite_task run this task after the task with the given
830 * task identifier completes (and any of our other
831 * conditions, such as delay, read or write-readyness
832 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
833 * on completion of other tasks.
834 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever"
835 * @param rfd read file-descriptor 833 * @param rfd read file-descriptor
836 * @param main main function of the task 834 * @param task main function of the task
837 * @param cls closure of task 835 * @param task_cls closure of task
838 * @return unique task identifier for the job 836 * @return unique task identifier for the job
839 * only valid until "main" is started! 837 * only valid until "task" is started!
840 */ 838 */
841GNUNET_SCHEDULER_TaskIdentifier 839GNUNET_SCHEDULER_TaskIdentifier
842GNUNET_SCHEDULER_add_read_net (struct GNUNET_SCHEDULER_Handle * sched, 840GNUNET_SCHEDULER_add_read_net (struct GNUNET_SCHEDULER_Handle *sched,
843 int run_on_shutdown, 841 struct GNUNET_TIME_Relative delay,
844 enum GNUNET_SCHEDULER_Priority prio, 842 struct GNUNET_NETWORK_Handle *rfd,
845 GNUNET_SCHEDULER_TaskIdentifier 843 GNUNET_SCHEDULER_Task task,
846 prerequisite_task, 844 void *task_cls)
847 struct GNUNET_TIME_Relative delay,
848 struct GNUNET_NETWORK_Handle * rfd,
849 GNUNET_SCHEDULER_Task main, void *cls)
850{ 845{
851 struct GNUNET_NETWORK_FDSet *rs; 846 struct GNUNET_NETWORK_FDSet *rs;
852 GNUNET_SCHEDULER_TaskIdentifier ret; 847 GNUNET_SCHEDULER_TaskIdentifier ret;
@@ -854,9 +849,11 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_SCHEDULER_Handle * sched,
854 GNUNET_assert (rfd != NULL); 849 GNUNET_assert (rfd != NULL);
855 rs = GNUNET_NETWORK_fdset_create (); 850 rs = GNUNET_NETWORK_fdset_create ();
856 GNUNET_NETWORK_fdset_set (rs, rfd); 851 GNUNET_NETWORK_fdset_set (rs, rfd);
857 ret = GNUNET_SCHEDULER_add_select (sched, run_on_shutdown, prio, 852 ret = GNUNET_SCHEDULER_add_select (sched,
858 prerequisite_task, delay, 853 GNUNET_SCHEDULER_PRIORITY_KEEP,
859 rs, NULL, main, cls); 854 GNUNET_SCHEDULER_NO_TASK,
855 delay,
856 rs, NULL, task, task_cls);
860 GNUNET_NETWORK_fdset_destroy (rs); 857 GNUNET_NETWORK_fdset_destroy (rs);
861 return ret; 858 return ret;
862} 859}
@@ -867,34 +864,24 @@ GNUNET_SCHEDULER_add_read_net (struct GNUNET_SCHEDULER_Handle * sched,
867 * specified file descriptor is ready for writing. The delay can be 864 * specified file descriptor is ready for writing. The delay can be
868 * used as a timeout on the socket being ready. The task will be 865 * used as a timeout on the socket being ready. The task will be
869 * scheduled for execution once either the delay has expired or the 866 * scheduled for execution once either the delay has expired or the
870 * socket operation is ready. 867 * socket operation is ready. It will be run with the priority of
868 * the calling task.
871 * 869 *
872 * @param sched scheduler to use 870 * @param sched scheduler to use
873 * @param run_on_shutdown run on shutdown? Set this 871 * @param delay when should this operation time out? Use
874 * argument to GNUNET_NO to skip this task if 872 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
875 * the user requested process termination.
876 * @param prio how important is this task?
877 * @param prerequisite_task run this task after the task with the given
878 * task identifier completes (and any of our other
879 * conditions, such as delay, read or write-readyness
880 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
881 * on completion of other tasks.
882 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever"
883 * @param wfd write file-descriptor 873 * @param wfd write file-descriptor
884 * @param main main function of the task 874 * @param task main function of the task
885 * @param cls closure of task 875 * @param task_cls closure of task
886 * @return unique task identifier for the job 876 * @return unique task identifier for the job
887 * only valid until "main" is started! 877 * only valid until "task" is started!
888 */ 878 */
889GNUNET_SCHEDULER_TaskIdentifier 879GNUNET_SCHEDULER_TaskIdentifier
890GNUNET_SCHEDULER_add_write_net (struct GNUNET_SCHEDULER_Handle * sched, 880GNUNET_SCHEDULER_add_write_net (struct GNUNET_SCHEDULER_Handle *sched,
891 int run_on_shutdown, 881 struct GNUNET_TIME_Relative delay,
892 enum GNUNET_SCHEDULER_Priority prio, 882 struct GNUNET_NETWORK_Handle *wfd,
893 GNUNET_SCHEDULER_TaskIdentifier 883 GNUNET_SCHEDULER_Task task,
894 prerequisite_task, 884 void *task_cls)
895 struct GNUNET_TIME_Relative delay,
896 struct GNUNET_NETWORK_Handle * wfd,
897 GNUNET_SCHEDULER_Task main, void *cls)
898{ 885{
899 struct GNUNET_NETWORK_FDSet *ws; 886 struct GNUNET_NETWORK_FDSet *ws;
900 GNUNET_SCHEDULER_TaskIdentifier ret; 887 GNUNET_SCHEDULER_TaskIdentifier ret;
@@ -902,14 +889,95 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_SCHEDULER_Handle * sched,
902 GNUNET_assert (wfd != NULL); 889 GNUNET_assert (wfd != NULL);
903 ws = GNUNET_NETWORK_fdset_create (); 890 ws = GNUNET_NETWORK_fdset_create ();
904 GNUNET_NETWORK_fdset_set (ws, wfd); 891 GNUNET_NETWORK_fdset_set (ws, wfd);
905 ret = GNUNET_SCHEDULER_add_select (sched, run_on_shutdown, prio, 892 ret = GNUNET_SCHEDULER_add_select (sched,
906 prerequisite_task, delay, 893 GNUNET_SCHEDULER_PRIORITY_KEEP,
907 NULL, ws, main, cls); 894 GNUNET_SCHEDULER_NO_TASK, delay,
895 NULL, ws, task, task_cls);
896 GNUNET_NETWORK_fdset_destroy (ws);
897 return ret;
898}
899
900
901/**
902 * Schedule a new task to be run with a specified delay or when the
903 * specified file descriptor is ready for reading. The delay can be
904 * used as a timeout on the socket being ready. The task will be
905 * scheduled for execution once either the delay has expired or the
906 * socket operation is ready. It will be run with the priority of
907 * the calling task.
908 *
909 * @param sched scheduler to use
910 * @param delay when should this operation time out? Use
911 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
912 * @param rfd read file-descriptor
913 * @param task main function of the task
914 * @param task_cls closure of task
915 * @return unique task identifier for the job
916 * only valid until "task" is started!
917 */
918GNUNET_SCHEDULER_TaskIdentifier
919GNUNET_SCHEDULER_add_read_file (struct GNUNET_SCHEDULER_Handle *sched,
920 struct GNUNET_TIME_Relative delay,
921 const struct GNUNET_DISK_FileHandle *rfd,
922 GNUNET_SCHEDULER_Task task,
923 void *task_cls)
924{
925 struct GNUNET_NETWORK_FDSet *rs;
926 GNUNET_SCHEDULER_TaskIdentifier ret;
927
928 GNUNET_assert (rfd != NULL);
929 rs = GNUNET_NETWORK_fdset_create ();
930 GNUNET_NETWORK_fdset_handle_set (rs, rfd);
931 ret = GNUNET_SCHEDULER_add_select (sched,
932 GNUNET_SCHEDULER_PRIORITY_KEEP,
933 GNUNET_SCHEDULER_NO_TASK, delay,
934 rs, NULL, task, task_cls);
935 GNUNET_NETWORK_fdset_destroy (rs);
936 return ret;
937}
938
939
940/**
941 * Schedule a new task to be run with a specified delay or when the
942 * specified file descriptor is ready for writing. The delay can be
943 * used as a timeout on the socket being ready. The task will be
944 * scheduled for execution once either the delay has expired or the
945 * socket operation is ready. It will be run with the priority of
946 * the calling task.
947 *
948 * @param sched scheduler to use
949 * @param delay when should this operation time out? Use
950 * GNUNET_TIME_UNIT_FOREVER_REL for "on shutdown"
951 * @param wfd write file-descriptor
952 * @param task main function of the task
953 * @param task_cls closure of task
954 * @return unique task identifier for the job
955 * only valid until "task" is started!
956 */
957GNUNET_SCHEDULER_TaskIdentifier
958GNUNET_SCHEDULER_add_write_file (struct GNUNET_SCHEDULER_Handle *sched,
959 struct GNUNET_TIME_Relative delay,
960 const struct GNUNET_DISK_FileHandle *wfd,
961 GNUNET_SCHEDULER_Task task,
962 void *task_cls)
963{
964 struct GNUNET_NETWORK_FDSet *ws;
965 GNUNET_SCHEDULER_TaskIdentifier ret;
966
967 GNUNET_assert (wfd != NULL);
968 ws = GNUNET_NETWORK_fdset_create ();
969 GNUNET_NETWORK_fdset_handle_set (ws, wfd);
970 ret = GNUNET_SCHEDULER_add_select (sched,
971 GNUNET_SCHEDULER_PRIORITY_KEEP,
972 GNUNET_SCHEDULER_NO_TASK,
973 delay,
974 NULL, ws, task, task_cls);
908 GNUNET_NETWORK_fdset_destroy (ws); 975 GNUNET_NETWORK_fdset_destroy (ws);
909 return ret; 976 return ret;
910} 977}
911 978
912 979
980
913/** 981/**
914 * Schedule a new task to be run with a specified delay or when any of 982 * Schedule a new task to be run with a specified delay or when any of
915 * the specified file descriptor sets is ready. The delay can be used 983 * the specified file descriptor sets is ready. The delay can be used
@@ -928,160 +996,61 @@ GNUNET_SCHEDULER_add_write_net (struct GNUNET_SCHEDULER_Handle * sched,
928 * </code> 996 * </code>
929 * 997 *
930 * @param sched scheduler to use 998 * @param sched scheduler to use
931 * @param run_on_shutdown run on shutdown? Set this
932 * argument to GNUNET_NO to skip this task if
933 * the user requested process termination.
934 * @param prio how important is this task? 999 * @param prio how important is this task?
935 * @param prerequisite_task run this task after the task with the given 1000 * @param prerequisite_task run this task after the task with the given
936 * task identifier completes (and any of our other 1001 * task identifier completes (and any of our other
937 * conditions, such as delay, read or write-readyness 1002 * conditions, such as delay, read or write-readyness
938 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency 1003 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
939 * on completion of other tasks. 1004 * on completion of other tasks.
940 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever" 1005 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever",
1006 * which means that the task will only be run after we receive SIGTERM
941 * @param rs set of file descriptors we want to read (can be NULL) 1007 * @param rs set of file descriptors we want to read (can be NULL)
942 * @param ws set of file descriptors we want to write (can be NULL) 1008 * @param ws set of file descriptors we want to write (can be NULL)
943 * @param main main function of the task 1009 * @param task main function of the task
944 * @param cls closure of task 1010 * @param task_cls closure of task
945 * @return unique task identifier for the job 1011 * @return unique task identifier for the job
946 * only valid until "main" is started! 1012 * only valid until "task" is started!
947 */ 1013 */
948GNUNET_SCHEDULER_TaskIdentifier 1014GNUNET_SCHEDULER_TaskIdentifier
949GNUNET_SCHEDULER_add_select (struct GNUNET_SCHEDULER_Handle * sched, 1015GNUNET_SCHEDULER_add_select (struct GNUNET_SCHEDULER_Handle *sched,
950 int run_on_shutdown,
951 enum GNUNET_SCHEDULER_Priority prio, 1016 enum GNUNET_SCHEDULER_Priority prio,
952 GNUNET_SCHEDULER_TaskIdentifier 1017 GNUNET_SCHEDULER_TaskIdentifier
953 prerequisite_task, 1018 prerequisite_task,
954 struct GNUNET_TIME_Relative delay, 1019 struct GNUNET_TIME_Relative delay,
955 const struct GNUNET_NETWORK_FDSet * rs, 1020 const struct GNUNET_NETWORK_FDSet * rs,
956 const struct GNUNET_NETWORK_FDSet * ws, 1021 const struct GNUNET_NETWORK_FDSet * ws,
957 GNUNET_SCHEDULER_Task main, void *cls) 1022 GNUNET_SCHEDULER_Task task,
1023 void *task_cls)
958{ 1024{
959 struct Task *task; 1025 struct Task *t;
960 1026
961 task = GNUNET_malloc (sizeof (struct Task)); 1027 t = GNUNET_malloc (sizeof (struct Task));
962 task->callback = main; 1028 t->callback = task;
963 task->callback_cls = cls; 1029 t->callback_cls = task_cls;
964 if (rs != NULL) 1030 if (rs != NULL)
965 { 1031 {
966 task->read_set = GNUNET_NETWORK_fdset_create (); 1032 t->read_set = GNUNET_NETWORK_fdset_create ();
967 GNUNET_NETWORK_fdset_copy (task->read_set, rs); 1033 GNUNET_NETWORK_fdset_copy (t->read_set, rs);
968 } 1034 }
969 if (ws != NULL) 1035 if (ws != NULL)
970 { 1036 {
971 task->write_set = GNUNET_NETWORK_fdset_create (); 1037 t->write_set = GNUNET_NETWORK_fdset_create ();
972 GNUNET_NETWORK_fdset_copy (task->write_set, ws); 1038 GNUNET_NETWORK_fdset_copy (t->write_set, ws);
973 } 1039 }
974 task->id = ++sched->last_id; 1040 t->id = ++sched->last_id;
975 task->prereq_id = prerequisite_task; 1041 t->prereq_id = prerequisite_task;
976 task->timeout = GNUNET_TIME_relative_to_absolute (delay); 1042 t->timeout = GNUNET_TIME_relative_to_absolute (delay);
977 task->priority = 1043 t->priority =
978 check_priority ((prio == 1044 check_priority ((prio ==
979 GNUNET_SCHEDULER_PRIORITY_KEEP) ? sched->current_priority 1045 GNUNET_SCHEDULER_PRIORITY_KEEP) ? sched->current_priority
980 : prio); 1046 : prio);
981 task->run_on_shutdown = run_on_shutdown; 1047 t->next = sched->pending;
982 task->next = sched->pending; 1048 sched->pending = t;
983 sched->pending = task;
984#if DEBUG_TASKS 1049#if DEBUG_TASKS
985 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
986 "Adding task: %llu / %p\n", task->id, task->callback_cls); 1051 "Adding task: %llu / %p\n", t->id, t->callback_cls);
987#endif 1052#endif
988 return task->id; 1053 return t->id;
989} 1054}
990 1055
991/**
992 * Schedule a new task to be run with a specified delay or when the
993 * specified file descriptor is ready for reading. The delay can be
994 * used as a timeout on the socket being ready. The task will be
995 * scheduled for execution once either the delay has expired or the
996 * socket operation is ready.
997 *
998 * @param sched scheduler to use
999 * @param run_on_shutdown run on shutdown? Set this
1000 * argument to GNUNET_NO to skip this task if
1001 * the user requested process termination.
1002 * @param prio how important is this task?
1003 * @param prerequisite_task run this task after the task with the given
1004 * task identifier completes (and any of our other
1005 * conditions, such as delay, read or write-readyness
1006 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
1007 * on completion of other tasks.
1008 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever"
1009 * @param rfd read file-descriptor
1010 * @param main main function of the task
1011 * @param cls closure of task
1012 * @return unique task identifier for the job
1013 * only valid until "main" is started!
1014 */
1015GNUNET_SCHEDULER_TaskIdentifier
1016GNUNET_SCHEDULER_add_read_file (struct GNUNET_SCHEDULER_Handle * sched,
1017 int run_on_shutdown,
1018 enum GNUNET_SCHEDULER_Priority prio,
1019 GNUNET_SCHEDULER_TaskIdentifier
1020 prerequisite_task,
1021 struct GNUNET_TIME_Relative delay,
1022 const struct GNUNET_DISK_FileHandle * rfd,
1023 GNUNET_SCHEDULER_Task main, void *cls)
1024{
1025 struct GNUNET_NETWORK_FDSet *rs;
1026 GNUNET_SCHEDULER_TaskIdentifier ret;
1027
1028 GNUNET_assert (rfd != NULL);
1029 rs = GNUNET_NETWORK_fdset_create ();
1030 GNUNET_NETWORK_fdset_handle_set (rs, rfd);
1031 ret = GNUNET_SCHEDULER_add_select (sched, run_on_shutdown, prio,
1032 prerequisite_task, delay,
1033 rs, NULL, main, cls);
1034 GNUNET_NETWORK_fdset_destroy (rs);
1035 return ret;
1036}
1037
1038
1039/**
1040 * Schedule a new task to be run with a specified delay or when the
1041 * specified file descriptor is ready for writing. The delay can be
1042 * used as a timeout on the socket being ready. The task will be
1043 * scheduled for execution once either the delay has expired or the
1044 * socket operation is ready.
1045 *
1046 * @param sched scheduler to use
1047 * @param run_on_shutdown run on shutdown? Set this
1048 * argument to GNUNET_NO to skip this task if
1049 * the user requested process termination.
1050 * @param prio how important is this task?
1051 * @param prerequisite_task run this task after the task with the given
1052 * task identifier completes (and any of our other
1053 * conditions, such as delay, read or write-readyness
1054 * are satisfied). Use GNUNET_SCHEDULER_NO_TASK to not have any dependency
1055 * on completion of other tasks.
1056 * @param delay how long should we wait? Use GNUNET_TIME_UNIT_FOREVER_REL for "forever"
1057 * @param wfd write file-descriptor
1058 * @param main main function of the task
1059 * @param cls closure of task
1060 * @return unique task identifier for the job
1061 * only valid until "main" is started!
1062 */
1063GNUNET_SCHEDULER_TaskIdentifier
1064GNUNET_SCHEDULER_add_write_file (struct GNUNET_SCHEDULER_Handle * sched,
1065 int run_on_shutdown,
1066 enum GNUNET_SCHEDULER_Priority prio,
1067 GNUNET_SCHEDULER_TaskIdentifier
1068 prerequisite_task,
1069 struct GNUNET_TIME_Relative delay,
1070 const struct GNUNET_DISK_FileHandle * wfd,
1071 GNUNET_SCHEDULER_Task main, void *cls)
1072{
1073 struct GNUNET_NETWORK_FDSet *ws;
1074 GNUNET_SCHEDULER_TaskIdentifier ret;
1075
1076 GNUNET_assert (wfd != NULL);
1077 ws = GNUNET_NETWORK_fdset_create ();
1078 GNUNET_NETWORK_fdset_handle_set (ws, wfd);
1079 ret = GNUNET_SCHEDULER_add_select (sched, run_on_shutdown, prio,
1080 prerequisite_task, delay,
1081 NULL, ws, main, cls);
1082 GNUNET_NETWORK_fdset_destroy (ws);
1083 return ret;
1084}
1085
1086
1087/* end of scheduler.c */ 1056/* end of scheduler.c */