1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
/* SPDX-License-Identifier: GPL-2.0 */
/** \file sched.h The paraslash scheduler
*
* Most paraslash executables employ the scheduler to perform non-blocking I/O
* to more than one file descriptor without threading.
*
* The scheduler maintains a list of task structures where each list element
* represents a task that has been registered to the scheduler by calling \ref
* task_register(). At each iteration of main loop, the scheduler first calls
* the \ref task_info::pre_monitor() method of each registered task to set
* up two file descriptor sets and to compute the timeout for the subsequent
* call to poll(2). The \ref task_info::post_monitor() method of each task is
* called after poll(2) returns. These methods perform read/write operations
* if the poll(2) call indicated that their file descriptors are ready for I/O.
*
* Inter-task communication is possible through a notification API also
* described here.
*
* The functions declared here are implemented in \ref sched.c.
*/
struct sched;
/**
* Information that must be supplied by callers of \ref task_register().
*
* The structure may be safely discarded after the task has been registered.
*/
struct task_info {
/** Used for log messages and by \ref get_task_list(). */
const char *name;
/**
* Configure watch fds and impose an upper bound on the I/O timeout.
*
* If this is not NULL, the function is called at each iteration of the
* scheduler's main loop. Its purpose is to tell the scheduler that
* certain file descriptors should be monitored for readiness for I/O.
* The function may also lower the scheduler's timeout value (but shall
* never increase it) to impose an upper bound on the waiting time in
* case no file descriptors happen to be ready.
*
* \sa \ref time.c.
*/
void (*pre_monitor)(struct sched *s, void *context);
/**
* Perform I/O on file descriptors which are ready for I/O.
*
* This mandatory hook is called after the system call which monitors
* file descriptors returns. The function should perform non-blocking
* I/O on those file descriptors which are reported as being ready.
*
* If this function returns a negative value, the scheduler unregisters
* the task.
*/
int (*post_monitor)(struct sched *s, void *context);
/**
* This pointer is saved when the task is registered. It is passed to
* ->pre_monitor() and ->post_monitor(). Usually this is a pointer to the
* struct owned by the caller which contains the task pointer.
*/
void *context;
};
/**
* This is set by the scheduler at the beginning of its main loop. It may be
* used (read-only) from everywhere. As none of the functions called by the
* scheduler are allowed to block, this value should be accurate enough so that
* there is no need to call clock_gettime() directly.
*/
extern const struct timeval *now;
struct sched *sched_new(int (*poll_function)(struct pollfd *, nfds_t, int));
struct task *task_register(struct task_info *info, struct sched *s);
int schedule(struct sched *s);
void sched_shutdown(struct sched *s);
char *get_task_list(struct sched *s);
void task_notify(struct task *t, int err);
void task_notify_all(struct sched *s, int err);
int task_get_notification(const struct task *t);
int task_status(const struct task *t);
int task_reap(struct task **tptr);
void sched_min_delay(struct sched *s);
void sched_request_timeout(struct timeval *to, struct sched *s);
void sched_request_timeout_ms(long unsigned ms, struct sched *s);
int sched_request_barrier(struct timeval *barrier, struct sched *s);
int sched_request_barrier_or_min_delay(struct timeval *barrier, struct sched *s);
void sched_monitor_readfd(int fd, struct sched *s);
void sched_monitor_writefd(int fd, struct sched *s);
bool sched_read_ok(int fd, const struct sched *s);
bool sched_write_ok(int fd, const struct sched *s);
|