diff options
Diffstat (limited to 'stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c')
-rw-r--r-- | stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c new file mode 100644 index 0000000..0223ac9 --- /dev/null +++ b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c @@ -0,0 +1,150 @@ +/* +* +* 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 "stackx_epoll_api.h" +#include "stackx_spl_share.h" +#include "common_pal_bitwide_adjust.h" +#include "nstack_dmm_adpt.h" +#include "nstack_dmm_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif /* _cplusplus */ + +void +epoll_triggle_event_from_api (sbr_socket_t * sock, int op) +{ + struct spl_netconn *conn = sbr_get_conn (sock); + void *epInfo = ADDR_SHTOL (conn->epInfo); + //NSPOL_LOGDBG(SOCKETS_DEBUG, "enter]fd=%d,op=%d", sock, op); + switch (op) + { + case EPOLL_API_OP_RECV: + break; + case EPOLL_API_OP_SEND: + if (conn->epoll_flag && epInfo) + { + nstack_event_callback (epInfo, EPOLLOUT); + } + break; + case EPOLL_API_OP_STACK_RECV: + if (conn->epoll_flag && epInfo) + { + nstack_event_callback (epInfo, EPOLLIN); + } + break; + default: + break; + } + return; +} + +/* + * This function will be registed to application + * The context will be in the application + */ +unsigned int +stackx_eventpoll_triggle (sbr_socket_t * sock, int triggle_ops, + struct epoll_event *pevent, void *pdata) +{ + struct spl_netconn *conn = sbr_get_conn (sock); + unsigned int events = 0; + if (!conn) + { + NSPOL_LOGINF (SOCKETS_DEBUG, "get socket failed]fd=%d", sock->fd); + return -1; + } + + NSPOL_LOGINF (SOCKETS_DEBUG, + "]fd=%d,triggle_ops=%d conn=%p event:%d pdata=%p", sock->fd, + triggle_ops, conn, pevent->events, pdata); + /* + * sock->epoll_flag must be set before sock->rcvevent check. + * Consider this Scenario : 1) network stack has got one packet, but event_callback not called yet + * 2) Do epoll ctl add, then stackx triggle will check event, it will get 0 + * 3) network stack call event_callback , it will check epoll_flag + * So, if epoll_flag not set before sock->rcvent check, neither of network stack and stackx triggle + * will add this event to epoll. because : for network stack, event_callback check epoll_flag fail + * for stackx triggle, event check fail. + */ + if (nstack_ep_triggle_add == triggle_ops) + { + /*log info */ + conn->epInfo = pdata; + __sync_fetch_and_add (&conn->epoll_flag, 1); + } + + if ((pevent->events & EPOLLIN) + && + (!((conn->rcvevent == 0) && (sbr_get_fd_share (sock)->lastdata == 0) + && (sbr_get_fd_share (sock)->lastoffset == 0)))) + events |= EPOLLIN; + if ((pevent->events & EPOLLOUT) && conn->sendevent) + events |= EPOLLOUT; + if (conn->errevent) + events |= pevent->events & (conn->errevent); + + switch (triggle_ops) + { + case nstack_ep_triggle_add: + break; + case nstack_ep_triggle_mod: + break; + case nstack_ep_triggle_del: + if (conn->epoll_flag > 0) + { + __sync_fetch_and_sub (&conn->epoll_flag, 1); + } + events = 0; + break; + default: + return -1; + } + return events; +} + +/* + * This function will be registed to application + * The context will be in the application + * RETURN VALUE : Event exists in current protocol + */ +unsigned int +stackx_eventpoll_getEvt (sbr_socket_t * sock, unsigned int events) +{ + struct spl_netconn *conn = sbr_get_conn (sock); + unsigned int tevent = 0; + if ((events & EPOLLIN) + && + (!((conn->rcvevent == 0) && (sbr_get_fd_share (sock)->lastdata == 0) + && (sbr_get_fd_share (sock)->lastoffset == 0)))) + { + tevent |= EPOLLIN; + } + + if ((events & EPOLLOUT) && conn->sendevent) + { + tevent |= EPOLLOUT; + } + return tevent; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* _cplusplus */ |