From 677717c5c86f107b2d196d70796a9be7db3532df Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Bollo?= Date: Tue, 5 Apr 2016 13:14:58 +0200 Subject: [PATCH] start epoll integration by upoll MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: If137a21e6f411775446393525ad7512421d7780e Signed-off-by: José Bollo --- include/afb-plugin.h | 10 +--- include/afb-poll-itf.h | 29 ++++++++++ src/CMakeLists.txt | 4 +- src/afb-apis.c | 19 +++++++ src/main.c | 1 + src/utils-upoll.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++ src/utils-upoll.h | 29 ++++++++++ 7 files changed, 225 insertions(+), 9 deletions(-) create mode 100644 include/afb-poll-itf.h create mode 100644 src/utils-upoll.c create mode 100644 src/utils-upoll.h diff --git a/include/afb-plugin.h b/include/afb-plugin.h index 88938e3d..ba86e181 100644 --- a/include/afb-plugin.h +++ b/include/afb-plugin.h @@ -61,19 +61,13 @@ enum AFB_Mode { AFB_MODE_GLOBAL }; -/* -typedef enum AFB_pluginE AFB_pluginE; -typedef enum AFB_sessionE AFB_sessionE; -typedef void (*AFB_apiCB)(struct afb_req); -typedef void (*AFB_freeCtxCB)(void*); -typedef struct AFB_restapi AFB_restapi; -typedef struct AFB_plugin AFB_plugin; -*/ +struct afb_poll; struct AFB_interface { int verbosity; enum AFB_Mode mode; + struct afb_poll (*poll_open)(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure); }; extern const struct AFB_plugin *pluginRegister (const struct AFB_interface *interface); diff --git a/include/afb-poll-itf.h b/include/afb-poll-itf.h new file mode 100644 index 00000000..4ce1fa48 --- /dev/null +++ b/include/afb-poll-itf.h @@ -0,0 +1,29 @@ +/* + * Copyright 2016 IoT.bzh + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +struct afb_poll_itf +{ + int (*update)(void *data, uint32_t events); + void (*close)(void *data); +}; + +struct afb_poll +{ + const struct afb_poll_itf *itf; + void *data; +}; + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7e02578e..d8bddcf0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,7 +8,9 @@ ADD_LIBRARY(src OBJECT afb-hreq.c afb-websock.c websock.c - verbose.c) + verbose.c + utils-upoll.c +) INCLUDE_DIRECTORIES(${include_dirs}) diff --git a/src/afb-apis.c b/src/afb-apis.c index 7634dca1..8dfac519 100644 --- a/src/afb-apis.c +++ b/src/afb-apis.c @@ -41,9 +41,12 @@ #include "afb-plugin.h" #include "afb-req-itf.h" +#include "afb-poll-itf.h" + #include "session.h" #include "afb-apis.h" #include "verbose.h" +#include "utils-upoll.h" struct api_desc { struct AFB_plugin *plugin; /* descriptor */ @@ -59,6 +62,12 @@ static int apis_count = 0; static const char plugin_register_function[] = "pluginRegister"; +static const struct afb_poll_itf upoll_itf = { + .update = (void*)upoll_update, + .close = (void*)upoll_close +}; + + int afb_apis_count() { return apis_count; @@ -76,6 +85,15 @@ void afb_apis_free_context(int apiidx, void *context) free(context); } +static struct afb_poll itf_poll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure) +{ + struct afb_poll result; + result.data = upoll_open(fd, events, process, closure); + result.itf = result.data ? &upoll_itf : NULL; + return result; +} + + int afb_apis_add_plugin(const char *path) { struct api_desc *apis; @@ -117,6 +135,7 @@ int afb_apis_add_plugin(const char *path) } interface->verbosity = 0; interface->mode = AFB_MODE_LOCAL; + interface->poll_open = itf_poll_open; /* init the plugin */ plugin = pluginRegisterFct(interface); diff --git a/src/main.c b/src/main.c index 37183e72..15f84b18 100644 --- a/src/main.c +++ b/src/main.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "afb-plugin.h" diff --git a/src/utils-upoll.c b/src/utils-upoll.c new file mode 100644 index 00000000..af4a6161 --- /dev/null +++ b/src/utils-upoll.c @@ -0,0 +1,142 @@ +/* + * Copyright 2016 IoT.bzh + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "utils-upoll.h" + + +struct upoll +{ + int fd; + void (*process)(void *closure, int fd, uint32_t events); + void *closure; + struct upoll *next; +}; + +static int pollfd = 0; +static struct upoll *head = NULL; +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +int upoll_is_valid(struct upoll *upoll) +{ + struct upoll *it = head; + while (it != NULL) { + if (it == upoll) + return 1; + it = it->next; + } + return 0; +} + +struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure) +{ + struct epoll_event e; + struct upoll *result; + int rc; + + /* opens the epoll stream */ + if (pollfd == 0) { + pollfd = epoll_create1(EPOLL_CLOEXEC); + if (pollfd == 0) { + pollfd = dup(0); + close(0); + } + if (pollfd < 0) { + pollfd = 0; + return NULL; + } + } + + /* allocates */ + result = malloc(sizeof *result); + if (result == NULL) + return NULL; + + /* init */ + result->fd = fd; + result->process = process; + result->closure = closure; + pthread_mutex_lock(&mutex); + result->next = head; + head = result; + pthread_mutex_unlock(&mutex); + + /* records */ + e.events = events; + e.data.ptr = result; + rc = epoll_ctl(pollfd, EPOLL_CTL_ADD, fd, &e); + if (rc == 0) + return result; + + /* revert on error */ + rc = errno; + upoll_close(result); + errno = rc; + return NULL; +} + +int upoll_update(struct upoll *upoll, uint32_t events) +{ + struct epoll_event e; + + assert(pollfd != 0); + assert(upoll_is_valid(upoll)); + + e.events = events; + e.data.ptr = upoll; + return epoll_ctl(pollfd, EPOLL_CTL_MOD, upoll->fd, &e); +} + +void upoll_close(struct upoll *upoll) +{ + struct upoll **it; + + assert(pollfd != 0); + assert(upoll_is_valid(upoll)); + + epoll_ctl(pollfd, EPOLL_CTL_DEL, upoll->fd, NULL); + pthread_mutex_lock(&mutex); + it = &head; + while (*it != upoll) + it = &(*it)->next; + *it = upoll->next; + pthread_mutex_unlock(&mutex); + free(upoll); +} + +void upoll_wait(int timeout) +{ + int rc; + struct epoll_event e; + struct upoll *upoll; + + if (pollfd == 0) + return; + + rc = epoll_wait(pollfd, &e, 1, timeout); + if (rc == 1) { + upoll = e.data.ptr; + upoll->process(upoll->closure, upoll->fd, e.events); + } +} + diff --git a/src/utils-upoll.h b/src/utils-upoll.h new file mode 100644 index 00000000..24aaf41a --- /dev/null +++ b/src/utils-upoll.h @@ -0,0 +1,29 @@ +/* + * Copyright 2016 IoT.bzh + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +struct upoll; + +extern int upoll_is_valid(struct upoll *upoll); + +extern struct upoll *upoll_open(int fd, uint32_t events, void (*process)(void *closure, int fd, uint32_t events), void *closure); + +extern int upoll_update(struct upoll *upoll, uint32_t events); + +extern void upoll_close(struct upoll *upoll); + +extern void upoll_wait(int timeout); + -- 2.16.6