diff options
Diffstat (limited to 'stacks/rsocket/src/rsocket_adpt.c')
-rw-r--r-- | stacks/rsocket/src/rsocket_adpt.c | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/stacks/rsocket/src/rsocket_adpt.c b/stacks/rsocket/src/rsocket_adpt.c new file mode 100644 index 0000000..eda7fd7 --- /dev/null +++ b/stacks/rsocket/src/rsocket_adpt.c @@ -0,0 +1,218 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <dlfcn.h> + +#include "nstack_dmm_api.h" + +#include "rsocket_adpt.h" +#include "rdma/rsocket.h" + + +#define RR_EVFD(u64) ((int)((u64) >> 32)) +#define RR_RSFD(u64) ((int)((u64) & 0xFFFFFFFF)) +#define RR_DATA(evfd, rsfd) ((((uint64_t)(evfd)) << 32) | (uint64_t)(uint32_t)(rsfd)) + +#define RR_EV_NUM 64 + +rsocket_var_t g_rr_var = {0}; + +rr_sapi_t g_sapi = {0}; + +int g_rr_log_level = -1; + + +int rr_notify_event(void *pdata, int events) +{ + int ret; + + ret = g_rr_var.event_cb(pdata, events); + + RR_DBG("event_cb(%p, 0x%x)=%d,%d\n", pdata, events, ret, errno); + + return ret; +} + +int rr_epoll_ctl(int op, int evfd, uint32_t events, int rsfd) +{ + int ret; + struct epoll_event event; + event.events = events; + event.data.u64 = RR_DATA(evfd, rsfd); + ret = GSAPI(epoll_ctl)(g_rr_var.epfd, op, evfd, &event); + return ret; +} + +static void *rr_epoll_thread(void *arg) +{ + int i, ret, e; + struct epoll_event events[RR_EV_NUM]; + + while (1) { + ret = GSAPI(epoll_wait)(g_rr_var.epfd, events, RR_EV_NUM, 100); + e = errno; + + for (i = 0; i < ret; ++i) { + if (rr_rs_handle(RR_RSFD(events[i].data.u64), events[i].events)) { + (void)rr_ep_del(RR_EVFD(events[i].data.u64)); + } + } + + if (ret < 0) { + RR_STAT_INC(RR_STAT_EPW_ERR); + if (e == EINTR) { + RR_STAT_INC(RR_STAT_EPW_EINTR); + } else if ( e == ETIMEDOUT) { + RR_STAT_INC(RR_STAT_EPW_ETIMEOUT); + } else { + RR_ERR("epoll_wait()=%d:%d\n", ret, errno); + } + } + } + + return NULL; +} + + +static int rr_init_sapi() +{ + void *handle = dlopen("libc.so.6", RTLD_NOW | RTLD_GLOBAL); + if (!handle) { + RR_ERR("dlopen(libc.so.6):NULL\n"); + return -1; + } + +#define RR_SAPI(name) \ + GSAPI(name) = dlsym(handle, #name); \ + if (!GSAPI(name)) \ + RR_ERR("dlsym(" #name "):NULL\n"); +#include "rsocket_sapi.h" +#undef RR_SAPI + + return 0; +} + +static void rr_init_log() +{ + int level; + char *log; + + if (g_rr_log_level >= 0) + return; + + log = getenv("RSOCKET_LOG"); + if (!log || !log[0]) { + g_rr_log_level = RR_LOG_OFF; + return; + } + + level = atoi(log); + if (level < 0 || level > 99999) { + g_rr_log_level = RR_LOG_OFF; + return; + } + + g_rr_log_level = level; +} + +static int rsocket_init() +{ + int ret; + + rr_init_log(); + + if (rr_init_sapi()) { + return -1; + } + + g_rr_var.epfd = GSAPI(epoll_create)(1); + if (g_rr_var.epfd < 0) + return g_rr_var.epfd; + + ret = pthread_create(&g_rr_var.epoll_threadid, NULL, rr_epoll_thread, NULL); + if (ret) { + GSAPI(close)(g_rr_var.epfd); + g_rr_var.epfd = -1; + return ret; + } + (void)pthread_setname_np(g_rr_var.epoll_threadid, "rsocket_epoll"); + + return 0; +} + +int rsocket_exit() +{ + if (g_rr_var.epfd >= 0) { + (void)GSAPI(close)(g_rr_var.epfd); + g_rr_var.epfd = -1; + } + + return 0; +} + +unsigned int rsocket_ep_ctl(int epFD, int proFD, int ctl_ops, struct epoll_event * event, void *pdata) +{ + int ret; + struct eventpoll *ep; + unsigned int revents = 0; + + RR_DBG("(%d, %d, %d, 0x%x, %p)\n", epFD, proFD, ctl_ops, event->events, pdata); + + switch (ctl_ops) { + case nstack_ep_triggle_add: + ret = rr_rs_ep_add(proFD, pdata, &revents); + if (ret) + return -1; + return revents; + + case nstack_ep_triggle_mod: + ret = rr_rs_ep_mod(proFD, pdata, &revents); + if (ret) + return -1; + return revents; + case nstack_ep_triggle_del: + return rr_rs_ep_del(proFD); + } + + return _err(EPERM); +} + +int rsocket_stack_register(nstack_proc_cb *proc_fun, nstack_event_cb *event_ops) +{ + rr_init_log(); + +#define NSTACK_MK_DECL(ret, fn, args) \ + do { \ + proc_fun->socket_ops.pf##fn = dlsym(event_ops->handle, "r"#fn); \ + if (!proc_fun->socket_ops.pf##fn) \ + RR_LOG("socket API '" #fn "' not found\n"); \ + } while (0) +#include "declare_syscalls.h" +#undef NSTACK_MK_DECL + + proc_fun->extern_ops.module_init = rsocket_init; + proc_fun->extern_ops.ep_ctl = rsocket_ep_ctl; + proc_fun->extern_ops.ep_getevt = NULL; + + g_rr_var.type = event_ops->type; + g_rr_var.event_cb = event_ops->event_cb; + + return 0; +} + |