X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Ffdev-epoll.c;h=262ec84b61339990cc03bf08310c620af5b94952;hb=65353dce81a629e042800bb7b86fcd869a76727e;hp=80c037d089c62f41f63bb9becd7f5522e6fdddb7;hpb=ca820c65c2b03a24e8936218171c6c1d138fd1f7;p=src%2Fapp-framework-binder.git diff --git a/src/fdev-epoll.c b/src/fdev-epoll.c index 80c037d0..262ec84b 100644 --- a/src/fdev-epoll.c +++ b/src/fdev-epoll.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 "IoT.bzh" + * Copyright (C) 2015-2020 "IoT.bzh" * Author José Bollo * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,15 +23,30 @@ #include "fdev.h" #include "fdev-epoll.h" +/* + * For sake of simplicity there is no struct fdev_epoll. + * Instead, the file descriptor of the internal epoll is used + * and wrapped in a pseudo pointer to a pseudo struct. + */ #define epollfd(fdev_epoll) ((int)(intptr_t)fdev_epoll) +/* + * disable callback for fdev + * + * refs to fdev must not be counted here + */ static void disable(void *closure, const struct fdev *fdev) { struct fdev_epoll *fdev_epoll = closure; epoll_ctl(epollfd(fdev_epoll), EPOLL_CTL_DEL, fdev_fd(fdev), 0); } -static void enable(void *closure, const struct fdev *fdev) +/* + * enable callback for fdev + * + * refs to fdev must not be counted here + */ +static void enable_or_update(void *closure, const struct fdev *fdev, int op, int err) { struct fdev_epoll *fdev_epoll = closure; struct epoll_event event; @@ -40,18 +55,45 @@ static void enable(void *closure, const struct fdev *fdev) fd = fdev_fd(fdev); event.events = fdev_events(fdev); event.data.ptr = (void*)fdev; - rc = epoll_ctl(epollfd(fdev_epoll), EPOLL_CTL_MOD, fd, &event); - if (rc < 0 && errno == ENOENT) - epoll_ctl(epollfd(fdev_epoll), EPOLL_CTL_ADD, fd, &event); + rc = epoll_ctl(epollfd(fdev_epoll), op, fd, &event); + if (rc < 0 && errno == err) + epoll_ctl(epollfd(fdev_epoll), (EPOLL_CTL_MOD + EPOLL_CTL_ADD) - op, fd, &event); +} + +/* + * enable callback for fdev + * + * refs to fdev must not be counted here + */ +static void enable(void *closure, const struct fdev *fdev) +{ + enable_or_update(closure, fdev, EPOLL_CTL_ADD, EEXIST); +} + +/* + * update callback for fdev + * + * refs to fdev must not be counted here + */ +static void update(void *closure, const struct fdev *fdev) +{ + enable_or_update(closure, fdev, EPOLL_CTL_MOD, ENOENT); } +/* + * unref is not handled here + */ static struct fdev_itf itf = { .unref = 0, .disable = disable, - .enable = enable + .enable = enable, + .update = update }; +/* + * create an fdev_epoll + */ struct fdev_epoll *fdev_epoll_create() { int fd = epoll_create1(EPOLL_CLOEXEC); @@ -62,16 +104,25 @@ struct fdev_epoll *fdev_epoll_create() return fd < 0 ? 0 : (struct fdev_epoll*)(intptr_t)fd; } +/* + * destroy the fdev_epoll + */ void fdev_epoll_destroy(struct fdev_epoll *fdev_epoll) { close(epollfd(fdev_epoll)); } +/* + * get pollable fd for the fdev_epoll + */ int fdev_epoll_fd(struct fdev_epoll *fdev_epoll) { return epollfd(fdev_epoll); } +/* + * create an fdev linked to the 'fdev_epoll' for 'fd' + */ struct fdev *fdev_epoll_add(struct fdev_epoll *fdev_epoll, int fd) { struct fdev *fdev; @@ -82,16 +133,20 @@ struct fdev *fdev_epoll_add(struct fdev_epoll *fdev_epoll, int fd) return fdev; } -void fdev_epoll_wait_and_dispatch(struct fdev_epoll *fdev_epoll, int timeout_ms) +/* + * get pollable fd for the fdev_epoll + */ +int fdev_epoll_wait_and_dispatch(struct fdev_epoll *fdev_epoll, int timeout_ms) { struct fdev *fdev; - struct epoll_event events[8]; - int rc, i; + struct epoll_event events; + int rc; - rc = epoll_wait(epollfd(fdev_epoll), events, sizeof events / sizeof *events, timeout_ms < 0 ? -1 : timeout_ms); - for (i = 0 ; i < rc ; i++) { - fdev = events[i].data.ptr; - fdev_dispatch(fdev, events[i].events); + rc = epoll_wait(epollfd(fdev_epoll), &events, 1, timeout_ms < 0 ? -1 : timeout_ms); + if (rc == 1) { + fdev = events.data.ptr; + fdev_dispatch(fdev, events.events); } + return rc; }