From 8dbb8a0ad386fd890f688109c44df0429c2af597 Mon Sep 17 00:00:00 2001 From: Steven Barth Date: Sun, 8 Feb 2009 20:57:36 +0000 Subject: Use poll() instead of select() Reintroduce nanosleep() --- libs/nixio/Makefile | 2 +- libs/nixio/src/nixio.c | 5 +- libs/nixio/src/nixio.h | 2 +- libs/nixio/src/poll.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++ libs/nixio/src/select.c | 110 ----------------------------- 5 files changed, 184 insertions(+), 116 deletions(-) create mode 100644 libs/nixio/src/poll.c delete mode 100644 libs/nixio/src/select.c diff --git a/libs/nixio/Makefile b/libs/nixio/Makefile index a2ce5dae6..b6d9485e4 100644 --- a/libs/nixio/Makefile +++ b/libs/nixio/Makefile @@ -5,7 +5,7 @@ include ../../build/gccconfig.mk %.o: %.c $(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $< -compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/select.o +compile: src/nixio.o src/socket.o src/sockopt.o src/bind.o src/address.o src/poll.o $(LINK) $(SHLIB_FLAGS) -o src/nixio.so src/*.o mkdir -p dist$(LUA_LIBRARYDIR) cp src/nixio.so dist$(LUA_LIBRARYDIR)/nixio.so diff --git a/libs/nixio/src/nixio.c b/libs/nixio/src/nixio.c index 1152f2cc8..6f3e0793f 100644 --- a/libs/nixio/src/nixio.c +++ b/libs/nixio/src/nixio.c @@ -19,11 +19,8 @@ #include #include #include -#include -#include #include #include -#include #include #include "nixio.h" @@ -109,7 +106,7 @@ LUALIB_API int luaopen_nixio(lua_State *L) { nixio_open_sockopt(L); nixio_open_bind(L); nixio_open_address(L); - nixio_open_select(L); + nixio_open_poll(L); /* module version */ lua_pushnumber(L, VERSION); diff --git a/libs/nixio/src/nixio.h b/libs/nixio/src/nixio.h index ce79c9aa6..d39c31b6d 100644 --- a/libs/nixio/src/nixio.h +++ b/libs/nixio/src/nixio.h @@ -24,7 +24,7 @@ void nixio_open_socket(lua_State *L); void nixio_open_sockopt(lua_State *L); void nixio_open_bind(lua_State *L); void nixio_open_address(lua_State *L); -void nixio_open_select(lua_State *L); +void nixio_open_poll(lua_State *L); /* Method functions */ diff --git a/libs/nixio/src/poll.c b/libs/nixio/src/poll.c new file mode 100644 index 000000000..7a397b96e --- /dev/null +++ b/libs/nixio/src/poll.c @@ -0,0 +1,181 @@ +/* + * nixio - Linux I/O library for lua + * + * Copyright (C) 2009 Steven Barth + * + * 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 +#include "nixio.h" + + +/** + * nanosleep() + */ +static int nixio_nanosleep(lua_State *L) { + struct timespec req, rem; + req.tv_sec = luaL_optint(L, 1, 0); + req.tv_nsec = luaL_optint(L, 2, 0); + + int status = nanosleep(&req, &rem); + if (!status) { + lua_pushboolean(L, 1); + return 1; + } else { + if (errno == EINTR) { + lua_pushboolean(L, 0); + lua_pushinteger(L, rem.tv_sec); + lua_pushinteger(L, rem.tv_nsec); + return 3; + } else { + return nixio__perror(L); + } + } +} + +/** + * Checks whether a flag is set in the table and translates it into a bitmap + */ +static void nixio_poll_flags__w(lua_State *L, int *map, int f, const char *t) { + lua_pushstring(L, t); + lua_rawget(L, -2); + if (lua_toboolean(L, -1)) { + *map |= f; + } + lua_pop(L, 1); +} + +/** + * Checks whether a flag is set in the bitmap and sets the matching table value + */ +static void nixio_poll_flags__r(lua_State *L, int *map, int f, const char *t) { + lua_pushstring(L, t); + if (*map & f) { + lua_pushboolean(L, 1); + } else { + lua_pushnil(L); + } + lua_rawset(L, -3); +} + +/** + * Translate integer to poll flags and vice versa + */ +static int nixio_poll_flags(lua_State *L) { + int flags; + if (lua_istable(L, 1)) { + lua_settop(L, 1); + flags = 0; + nixio_poll_flags__w(L, &flags, POLLIN, "in"); + nixio_poll_flags__w(L, &flags, POLLPRI, "pri"); + nixio_poll_flags__w(L, &flags, POLLOUT, "out"); + nixio_poll_flags__w(L, &flags, POLLERR, "err"); + nixio_poll_flags__w(L, &flags, POLLHUP, "hup"); + nixio_poll_flags__w(L, &flags, POLLNVAL, "nval"); + lua_pushinteger(L, flags); + } else { + flags = luaL_checkinteger(L, 1); + lua_newtable(L); + nixio_poll_flags__r(L, &flags, POLLIN, "in"); + nixio_poll_flags__r(L, &flags, POLLPRI, "pri"); + nixio_poll_flags__r(L, &flags, POLLOUT, "out"); + nixio_poll_flags__r(L, &flags, POLLERR, "err"); + nixio_poll_flags__r(L, &flags, POLLHUP, "hup"); + nixio_poll_flags__r(L, &flags, POLLNVAL, "nval"); + } + return 1; +} + +/** + * poll({{fd = socket, events = FLAGS}, ...}, timeout) + */ +static int nixio_poll(lua_State *L) { + int len = lua_objlen(L, 1); + int i, fd; + int timeout = luaL_optint(L, 2, 0); + int status = -1; + + /* we are being abused as sleep() replacement... */ + if (lua_isnoneornil(L, 1) || len < 1) { + return nixio__pstatus(L, !poll(NULL, 0, timeout)); + } + + luaL_checktype(L, 1, LUA_TTABLE); + struct pollfd *fds = calloc(len, sizeof(struct pollfd)); + + for (i = 0; i < len; i++) { + lua_rawgeti(L, 1, i+1); + if (!lua_istable(L, -1)) { + free(fds); + return luaL_argerror(L, 1, "invalid datastructure"); + } + + lua_pushliteral(L, "fd"); + lua_rawget(L, -2); + fd = nixio__tofd(L, -1); + if (fd == -1) { + free(fds); + return luaL_argerror(L, 1, "invalid fd in datastructure"); + } + fds[i].fd = fd; + + lua_pushliteral(L, "events"); + lua_rawget(L, -3); + fds[i].events = (short)lua_tointeger(L, -1); + + lua_pop(L, 3); + } + + status = poll(fds, (nfds_t)len, timeout); + + if (status < 1) { + free(fds); + return nixio__perror(L); + } + + for (i = 0; i < len; i++) { + lua_rawgeti(L, 1, i+1); + + lua_pushliteral(L, "revents"); + lua_pushinteger(L, fds[i].revents); + lua_rawset(L, -3); + + lua_pop(L, 1); + } + + free(fds); + + lua_pushinteger(L, status); + lua_pushvalue(L, 1); + + return 2; +} + +/* module table */ +static const luaL_reg R[] = { + {"nanosleep", nixio_nanosleep}, + {"poll", nixio_poll}, + {"poll_flags", nixio_poll_flags}, + {NULL, NULL} +}; + +void nixio_open_poll(lua_State *L) { + luaL_register(L, NULL, R); +} diff --git a/libs/nixio/src/select.c b/libs/nixio/src/select.c deleted file mode 100644 index e88075ce4..000000000 --- a/libs/nixio/src/select.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * nixio - Linux I/O library for lua - * - * Copyright (C) 2009 Steven Barth - * - * 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 "nixio.h" - -static int nixio_select(lua_State *L) { - int nfds = 0, tmpfd = -1, i = 0, j = 0, o = 0, k, tlen; - fd_set rfds, wfds, xfds; - fd_set *fdsets[3] = {&rfds, &wfds, &xfds}; - FD_ZERO(fdsets[0]); - FD_ZERO(fdsets[1]); - FD_ZERO(fdsets[2]); - - struct timeval timeout; - timeout.tv_sec = luaL_optinteger(L, 4, 0); - timeout.tv_usec = luaL_optinteger(L, 5, 0); - - /* create fdsets */ - for (i=0; i<3; i++) { - o = i + 1; - if (lua_isnoneornil(L, o)) { - fdsets[i] = NULL; - continue; - } - - luaL_checktype(L, o, LUA_TTABLE); - tlen = lua_objlen(L, o); - luaL_argcheck(L, tlen <= FD_SETSIZE, o, "too many fds"); - - for (j=1; j<=tlen; j++) { - lua_rawgeti(L, o, j); - tmpfd = nixio__checkfd(L, -1); - FD_SET(tmpfd, fdsets[i]); - if (tmpfd >= nfds) { - nfds = tmpfd + 1; - } - lua_pop(L, 1); - } - } - - int stat = select(nfds, fdsets[0], fdsets[1], fdsets[2], &timeout); - - if (stat < 0) { - return nixio__perror(L); - } else if (stat == 0) { - lua_pushinteger(L, stat); - for (i=1; i<=3; i++) { - if (lua_isnoneornil(L, i)) { - lua_pushnil(L); - } else { - lua_newtable(L); - } - } - } else { - lua_pushinteger(L, stat); - - /* create return tables */ - for (i=0; i<3; i++) { - o = i + 1; - if (lua_isnoneornil(L, o)) { - lua_pushnil(L); - continue; - } - - lua_newtable(L); - tlen = lua_objlen(L, o); - k = 1; - - for (j=1; j<=tlen; j++) { - lua_rawgeti(L, o, j); - tmpfd = nixio__tofd(L, -1); - if (FD_ISSET(tmpfd, fdsets[i])) { - lua_rawseti(L, -2, k++); - } else { - lua_pop(L, 1); - } - } - } - } - return 4; -} - -/* module table */ -static const luaL_reg R[] = { - {"select", nixio_select}, - {NULL, NULL} -}; - -void nixio_open_select(lua_State *L) { - luaL_register(L, NULL, R); -} -- cgit v1.2.3