1 #include <lunaix/clock.h>
2 #include <lunaix/device.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/process.h>
6 #include <lunaix/sched.h>
7 #include <lunaix/spike.h>
8 #include <lunaix/syscall.h>
9 #include <lunaix/syscall_utils.h>
11 #define MAX_POLLER_COUNT 16
14 current_rmiopoll(int pld)
16 iopoll_remove(__current->pid, &__current->pollctx, pld);
19 static struct iopoller*
20 iopoll_getpoller(struct iopoll* ctx, int pld)
22 if (pld < 0 || pld >= MAX_POLLER_COUNT) {
26 return ctx->pollers[pld];
30 __do_poll(struct poll_info* pinfo, int pld)
32 struct iopoller* poller = iopoll_getpoller(&__current->pollctx, pld);
40 if ((dev = resolve_device(poller->file_ref->inode->data))) {
43 // TODO handle generic file
45 N.B. In Linux, polling on any of the non-device mapped file cause
46 immediate return of poller, in other words, the I/O signal on file is
47 always active. Which make it no use on monitoring any file
48 modifications. However, polling for such modifications
49 must go through inotify_* API. Which is not that elegant as it breaks
50 the nice consistency that *poll(2) should have. Let see want can we
56 poll_setrevt(pinfo, _POLLERR);
60 if ((evt = poll_checkevt(pinfo, evt))) {
61 poll_setrevt(pinfo, evt);
68 if ((pinfo->flags & _POLLEE_RM_ON_ERR)) {
69 current_rmiopoll(pld);
74 if (!(pinfo->flags & _POLLEE_ALWAYS)) {
75 current_rmiopoll(pld);
82 __do_poll_round(struct poll_info* pinfos, int ninfo)
87 for (int i = 0; i < ninfo; i++) {
88 struct poll_info* pinfo = &pinfos[i];
91 if (__do_poll(pinfo, pld)) {
100 __do_poll_all(struct poll_info* pinfo)
102 for (int i = 0; i < MAX_POLLER_COUNT; i++) {
103 if (!__do_poll(pinfo, i)) {
114 #define fd2dev(fd) resolve_device((fd)->file->inode->data)
119 for (size_t i = 0; i < MAX_POLLER_COUNT; i++) {
120 if (!__current->pollctx.pollers[i]) {
129 __append_pollers(int* ds, int npoller)
133 for (int i = 0; i < npoller; i++) {
135 if ((err = vfs_getfd(*fd, &fd_s))) {
141 int pld = iopoll_install(__current->pid, &__current->pollctx, fd_s);
160 iopoll_init(struct iopoll* ctx)
162 ctx->pollers = vzalloc(sizeof(ptr_t) * MAX_POLLER_COUNT);
167 iopoll_free(pid_t pid, struct iopoll* ctx)
169 for (int i = 0; i < MAX_POLLER_COUNT; i++) {
170 struct iopoller* poller = ctx->pollers[i];
172 vfs_pclose(poller->file_ref, pid);
173 llist_delete(&poller->evt_listener);
182 iopoll_wake_pollers(poll_evt_q* pollers_q)
184 struct iopoller *pos, *n;
185 llist_for_each(pos, n, pollers_q, evt_listener)
187 struct proc_info* proc = get_process(pos->pid);
188 if (proc_hanged(proc)) {
189 resume_process(proc);
192 assert(!proc_terminated(proc));
197 iopoll_remove(pid_t pid, struct iopoll* ctx, int pld)
199 struct iopoller* poller = ctx->pollers[pld];
204 vfs_pclose(poller->file_ref, pid);
206 ctx->pollers[pld] = NULL;
213 iopoll_install(pid_t pid, struct iopoll* pollctx, struct v_fd* fd)
215 int pld = __alloc_pld();
220 struct iopoller* iop = valloc(sizeof(struct iopoller));
221 *iop = (struct iopoller){
222 .file_ref = fd->file,
226 vfs_ref_file(fd->file);
227 __current->pollctx.pollers[pld] = iop;
228 __current->pollctx.n_poller++;
231 if ((dev = fd2dev(fd))) {
232 iopoll_listen_on(iop, &dev->pollers);
234 // TODO handle generic file
240 __DEFINE_LXSYSCALL2(int, pollctl, int, action, va_list, va)
245 int* ds = va_arg(va, int*);
246 int nds = va_arg(va, int);
247 retcode = __append_pollers(ds, nds);
250 int pld = va_arg(va, int);
251 retcode = iopoll_remove(__current->pid, &__current->pollctx, pld);
254 struct poll_info* pinfos = va_arg(va, struct poll_info*);
255 int npinfos = va_arg(va, int);
256 int timeout = va_arg(va, int);
258 time_t t1 = clock_systime() + timeout;
259 while (!(retcode == __do_poll_round(pinfos, npinfos))) {
260 if (timeout >= 0 && t1 < clock_systime()) {
263 __wait_until_event();
266 case _SPOLL_WAIT_ANY: {
267 struct poll_info* pinfo = va_arg(va, struct poll_info*);
268 int timeout = va_arg(va, int);
270 time_t t1 = clock_systime() + timeout;
271 while (!(retcode == __do_poll_all(pinfo))) {
272 if (timeout >= 0 && t1 < clock_systime()) {
275 __wait_until_event();
283 return DO_STATUS(retcode);