aboutsummaryrefslogtreecommitdiffstats
path: root/src/nSocket/nstack/event/select/nstack_select.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nSocket/nstack/event/select/nstack_select.c')
-rw-r--r--src/nSocket/nstack/event/select/nstack_select.c756
1 files changed, 756 insertions, 0 deletions
diff --git a/src/nSocket/nstack/event/select/nstack_select.c b/src/nSocket/nstack/event/select/nstack_select.c
new file mode 100644
index 0000000..bb43dbe
--- /dev/null
+++ b/src/nSocket/nstack/event/select/nstack_select.c
@@ -0,0 +1,756 @@
+/*
+*
+* 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 header files *
+ *----------------------------------------------*/
+#include "nstack_select.h"
+#include "nstack_log.h"
+#include "nsfw_base_linux_api.h"
+
+/*==============================================*
+ * constants or macros define *
+ *----------------------------------------------*/
+#ifdef NSTACK_SELECT_MODULE
+
+/*==============================================*
+ * project-wide global variables *
+ *----------------------------------------------*/
+extern void *nstack_select_thread (void *arg);
+/*************select module***************************/
+struct select_module_info g_select_module = {
+ .inited = FALSE,
+};
+
+/*==============================================*
+ * routines' or functions' implementations *
+ *----------------------------------------------*/
+/*****************************************************************************
+* Prototype : get_select_module
+* Description : get_select_module
+* Input : void
+* Output : None
+* Return Value : struct select_module_info *
+* Calls :
+* Called By :
+*****************************************************************************/
+struct select_module_info *
+get_select_module (void)
+{
+ return &g_select_module;
+}
+
+/*split comm seclet entry to child mod select*/
+/*****************************************************************************
+* Prototype : select_cb_split_by_mod
+* Description : select_cb_split_by_module
+* Input : i32 nfds
+* fd_set *readfd
+* fd_set *writefd
+* fd_set *exceptfd
+* struct select_entry *entry
+* Output : None
+* Return Value : i32
+* Calls :
+* Called By :
+*****************************************************************************/
+i32
+select_cb_split_by_mod (i32 nfds,
+ fd_set * readfd,
+ fd_set * writefd,
+ fd_set * exceptfd, struct select_entry * entry)
+{
+ i32 inx;
+ i32 i;
+ i32 fd;
+
+ for (i = 0; i < nfds; i++)
+ {
+
+ /*not bound to any stack */
+ for (inx = 0; inx < get_mode_num (); inx++)
+ {
+ if (!((readfd && FD_ISSET (i, readfd)) ||
+ (writefd && FD_ISSET (i, writefd)) ||
+ (exceptfd && FD_ISSET (i, exceptfd))))
+ {
+ continue;
+ }
+ fd = select_get_modfd (i, inx);
+
+ /*not create by nstack */
+ if ((fd < 0) || (select_get_modindex (i) < 0))
+ {
+
+ if (inx != get_mode_linux_index ())
+ {
+ continue;
+ }
+ fd = i;
+ nssct_create (fd, fd, inx);
+ }
+ else
+ {
+ if (select_get_modindex (i) != inx)
+ continue;
+ }
+ NSSOC_LOGDBG ("fd is valiable i= %d fd = %d index = %d\n", i, fd,
+ inx);
+ if ((readfd) && (FD_ISSET (i, readfd)))
+ {
+ NSTACK_FD_SET (fd, &(entry->cb[inx].nstack_readset));
+ if (entry->cb[inx].count <= fd)
+ entry->cb[inx].count = fd + 1;
+ }
+
+ if ((writefd) && (FD_ISSET (i, writefd)))
+ {
+ NSTACK_FD_SET (fd, &(entry->cb[inx].nstack_writeset));
+ if (entry->cb[inx].count <= fd)
+ entry->cb[inx].count = fd + 1;
+ }
+
+ if ((exceptfd) && (FD_ISSET (i, exceptfd)))
+ {
+ NSTACK_FD_SET (fd, &(entry->cb[inx].nstack_exceptset));
+ if (entry->cb[inx].count <= fd)
+ entry->cb[inx].count = fd + 1;
+ }
+ }
+ }
+
+ for (inx = 0; inx < get_mode_num (); inx++)
+ {
+ if (entry->cb[inx].count > 0)
+ {
+ entry->info.set_num++;
+ entry->info.index = inx;
+ }
+ }
+ return TRUE;
+}
+
+/*****************************************************************************
+* Prototype : select_add_cb
+* Description : add cb to gloab list
+* Input : struct select_entry *entry
+* Output : None
+* Return Value : i32
+* Calls :
+* Called By :
+*****************************************************************************/
+i32
+select_add_cb (struct select_entry * entry)
+{
+
+ if ((!entry))
+ {
+
+ return FALSE;
+ }
+ select_spin_lock (&g_select_module.lock);
+
+ if (!g_select_module.entry_head)
+ {
+ g_select_module.entry_head = entry;
+ g_select_module.entry_tail = entry;
+ entry->next = NULL;
+ entry->prev = NULL;
+ }
+ else
+ {
+ g_select_module.entry_tail->next = entry;
+ entry->prev = g_select_module.entry_tail;
+ g_select_module.entry_tail = entry;
+ entry->next = NULL;
+ }
+
+ select_spin_unlock (&g_select_module.lock);
+ select_sem_post (&g_select_module.sem);
+ return TRUE;
+}
+
+/*****************************************************************************
+* Prototype : select_rm_cb
+* Description : rm the cb from gloab list
+* Input : struct select_entry *entry
+* Output : None
+* Return Value : i32
+* Calls :
+* Called By :
+*****************************************************************************/
+i32
+select_rm_cb (struct select_entry * entry)
+{
+
+ if (!entry)
+ {
+
+ return FALSE;
+ }
+
+ select_spin_lock (&g_select_module.lock);
+
+ if (g_select_module.entry_head == entry)
+ {
+ g_select_module.entry_head = entry->next;
+
+ }
+ else if (entry->prev)
+ {
+ entry->prev->next = entry->next;
+ }
+
+ if (g_select_module.entry_tail == entry)
+ {
+ g_select_module.entry_tail = entry->prev;
+ }
+ else if (entry->next)
+ {
+ entry->next->prev = entry->prev;
+ }
+
+ entry->next = NULL;
+ entry->prev = NULL;
+
+ select_spin_unlock (&g_select_module.lock);
+ return TRUE;
+}
+
+/*get fd set from entrys*/
+/*****************************************************************************
+* Prototype : select_thread_get_fdset
+* Description : get module listening fd form gloab list
+* Input : nstack_fd_set *readfd
+* nstack_fd_set *writefd
+* nstack_fd_set *exceptfd
+* struct select_module_info *module
+* i32 inx
+* Output : None
+* Return Value : i32
+* Calls :
+* Called By :
+*****************************************************************************/
+i32
+select_thread_get_fdset (nstack_fd_set * readfd,
+ nstack_fd_set * writefd,
+ nstack_fd_set * exceptfd,
+ struct select_module_info * module, i32 inx)
+{
+
+ struct select_entry *tmp;
+ i32 nfds = 0;
+ int retVal;
+
+ if (!module)
+ {
+ return FALSE;
+ }
+
+ retVal = NSTACK_FD_ZERO (readfd);
+ retVal |= NSTACK_FD_ZERO (writefd);
+ retVal |= NSTACK_FD_ZERO (exceptfd);
+ if (EOK != retVal)
+ {
+ NSSOC_LOGERR ("NSTACK_FD_ZERO MEMSET_S failed]ret=%d", retVal);
+ return FALSE;
+ }
+
+ select_spin_lock (&module->lock);
+ for (tmp = module->entry_head; NULL != tmp; tmp = tmp->next)
+ {
+ if (tmp->cb[inx].count <= 0)
+ {
+ continue;
+ }
+
+ NSTACK_FD_OR (readfd, &tmp->cb[inx].nstack_readset);
+ NSTACK_FD_OR (writefd, &tmp->cb[inx].nstack_writeset);
+ NSTACK_FD_OR (exceptfd, &tmp->cb[inx].nstack_exceptset);
+ if (nfds < tmp->cb[inx].count)
+ {
+ nfds = tmp->cb[inx].count;
+ }
+ }
+ select_spin_unlock (&module->lock);
+
+ return nfds;
+}
+
+/*****************************************************************************
+* Prototype : select_thread_set_fdset
+* Description : set ready event to gloab list
+* Input : i32 nfds
+* nstack_fd_set *readfd
+* nstack_fd_set *writefd
+* nstack_fd_set *exceptfd
+* struct select_module_info *module
+* i32 inx
+* i32 err
+* Output : None
+* Return Value : i32
+* Calls :
+* Called By :
+*****************************************************************************/
+i32
+select_thread_set_fdset (i32 nfds,
+ nstack_fd_set * readfd,
+ nstack_fd_set * writefd,
+ nstack_fd_set * exceptfd,
+ struct select_module_info * module, i32 inx, i32 err)
+{
+
+ struct select_entry *tmp;
+
+ if (!module)
+ {
+ return FALSE;
+ }
+
+ select_spin_lock (&module->lock);
+ for (tmp = module->entry_head; NULL != tmp; tmp = tmp->next)
+ {
+ if (tmp->cb[inx].count <= 0)
+ {
+ continue;
+ }
+
+ if (nfds < 0)
+ {
+ tmp->ready.readyset = nfds;
+ tmp->ready.select_errno = err;
+ continue;
+ }
+ NSSOC_LOGDBG ("readyset=%d,index=%d", tmp->ready.readyset, inx);
+ entry_module_fdset (tmp, nfds, readfd, writefd, exceptfd, inx);
+ }
+ select_spin_unlock (&module->lock);
+ return TRUE;
+
+}
+
+/*****************************************************************************
+* Prototype : select_event_post
+* Description : when event ready post sem to awaik nstack_select
+* Input : struct select_module_info *module
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*****************************************************************************/
+void
+select_event_post (struct select_module_info *module)
+{
+ struct select_entry *tmp;
+ int inx;
+ select_spin_lock (&module->lock);
+ for (tmp = module->entry_head; NULL != tmp; tmp = tmp->next)
+ {
+
+ if ((tmp->ready.readyset != 0))
+ {
+ for (inx = 0; inx < get_mode_num (); inx++)
+ {
+ tmp->cb[inx].count = 0;
+ }
+ NSSOC_LOGDBG ("readyset=%d", tmp->ready.readyset);
+ select_sem_post (&tmp->sem);
+ }
+ }
+ select_spin_unlock (&module->lock);
+}
+
+/*set select_event function*/
+/*****************************************************************************
+* Prototype : select_module_init
+* Description : init select module
+* Input : None
+* Output : None
+* Return Value : i32
+* Calls :
+* Called By :
+*****************************************************************************/
+i32
+select_module_init ()
+{
+ i32 i;
+ pthread_t select_thread_id;
+ i32 retval;
+
+ if (fdmapping_init () < 0)
+ {
+ goto ERR_RET;
+ }
+
+ g_select_module.default_mod = get_mode_linux_index ();
+ g_select_module.default_fun = nsfw_base_select;
+
+ /*regist select fun */
+ for (i = 0; i < get_mode_num (); i++)
+ {
+ g_select_module.get_select_fun_nonblock[i] =
+ nstack_module_ops (i)->pfselect;
+ }
+
+ select_sem_init (&g_select_module.sem, 0, 0);
+ select_spin_lock_init (&g_select_module.lock);
+
+ if (pthread_create (&select_thread_id, NULL, nstack_select_thread, NULL))
+ {
+
+ goto ERR_RET;
+ }
+
+ retval = pthread_setname_np (select_thread_id, "nstack_select");
+ if (retval)
+ {
+ /*set thread name failed */
+ }
+
+ g_select_module.inited = TRUE;
+ g_select_module.entry_head = g_select_module.entry_tail = NULL;
+ return TRUE;
+
+ERR_RET:
+
+ return FALSE;
+}
+
+/*****************************************************************************
+* Prototype : entry_module_fdset
+* Description : set event
+* Input : struct select_entry *entry
+* i32 fd_size
+* nstack_fd_set *readfd
+* nstack_fd_set *writefd
+* nstack_fd_set *exceptfd
+* i32 inx
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*****************************************************************************/
+void
+entry_module_fdset (struct select_entry *entry,
+ i32 fd_size,
+ nstack_fd_set * readfd,
+ nstack_fd_set * writefd,
+ nstack_fd_set * exceptfd, i32 inx)
+{
+ i32 i;
+ i32 fd;
+
+ for (i = 0; i < fd_size; i++)
+ {
+ fd = select_get_commfd (i, inx);
+ if (fd < 0)
+ {
+ continue;
+ }
+ if (NSTACK_FD_ISSET (i, readfd)
+ && NSTACK_FD_ISSET (i, &entry->cb[inx].nstack_readset))
+ {
+ FD_SET (fd, &entry->ready.readset);
+ entry->ready.readyset++;
+ NSSOC_LOGDBG ("readyset is %d", entry->ready.readyset);
+ }
+
+ if (NSTACK_FD_ISSET (i, writefd)
+ && NSTACK_FD_ISSET (i, &entry->cb[inx].nstack_writeset))
+ {
+ FD_SET (fd, &entry->ready.writeset);
+ entry->ready.readyset++;
+ NSSOC_LOGDBG ("writeset is %d", entry->ready.readyset);
+ }
+
+ if (NSTACK_FD_ISSET (i, exceptfd)
+ && NSTACK_FD_ISSET (i, &entry->cb[inx].nstack_exceptset))
+ {
+ FD_SET (fd, &entry->ready.exceptset);
+ entry->ready.readyset++;
+ NSSOC_LOGDBG ("exceptset is %d", entry->ready.readyset);
+ }
+ }
+
+}
+
+/*****************************************************************************
+* Prototype : select_scan
+* Description : scan all modules to check event ready or not
+* Input : struct select_entry *entry
+* Output : None
+* Return Value : i32
+* Calls :
+* Called By :
+*****************************************************************************/
+i32
+select_scan (struct select_entry *entry)
+{
+ i32 inx;
+ i32 fd_size;
+ i32 ready;
+ nstack_fd_set *readfd;
+ nstack_fd_set *writefd;
+ nstack_fd_set *exceptfd;
+ struct timeval timeout;
+
+ readfd = malloc (sizeof (nstack_fd_set));
+ writefd = malloc (sizeof (nstack_fd_set));
+ exceptfd = malloc (sizeof (nstack_fd_set));
+ if ((!readfd) || (!writefd) || (!exceptfd))
+ {
+ NSPOL_LOGERR ("malloc nstack_fd_set fail");
+ FREE_FD_SET (readfd, writefd, exceptfd);
+ return -1;
+ }
+ for (inx = 0; inx < get_mode_num (); inx++)
+ {
+
+ *readfd = entry->cb[inx].nstack_readset;
+ *writefd = entry->cb[inx].nstack_writeset;
+ *exceptfd = entry->cb[inx].nstack_exceptset;
+ fd_size = entry->cb[inx].count;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ if ((g_select_module.get_select_fun_nonblock[inx]) && (fd_size > 0))
+ {
+ ready =
+ g_select_module.get_select_fun_nonblock[inx] (fd_size,
+ (fd_set *) readfd,
+ (fd_set *) writefd,
+ (fd_set *) exceptfd,
+ &timeout);
+ }
+ else
+ {
+ continue;
+ }
+
+ if (ready > 0)
+ {
+ entry_module_fdset (entry, fd_size, readfd, writefd, exceptfd, inx);
+ }
+ else if (ready < 0)
+ {
+ entry->ready.readyset = ready;
+ entry->ready.select_errno = errno;
+ NSSOC_LOGERR ("select failed index = %d", inx);
+ FREE_FD_SET (readfd, writefd, exceptfd);
+ return FALSE;
+ }
+
+ }
+ FREE_FD_SET (readfd, writefd, exceptfd);
+ return TRUE;
+}
+
+/*****************************************************************************
+* Prototype : lint_lock
+* Description : avoid lint error
+* Input : None
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline void
+lint_lock ()
+{
+ return;
+}
+
+/*****************************************************************************
+* Prototype : lint_unlock
+* Description : avoid lint error
+* Input : None
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline void
+lint_unlock ()
+{
+ return;
+}
+
+/*****************************************************************************
+* Prototype : nstack_select_thread
+* Description : if gloab list not null scaning all modules ,need to think
+ about block mod
+* Input : void *arg
+* Output : None
+* Return Value : void *
+* Calls :
+* Called By :
+*****************************************************************************/
+void *
+nstack_select_thread (void *arg)
+{
+
+#define SELECT_SLEEP_TIME 800 //us
+
+ i32 inx;
+ nstack_fd_set *readfd;
+ nstack_fd_set *writefd;
+ nstack_fd_set *exceptfd;
+ i32 fd_size;
+ i32 ready;
+ i32 sleep_time = SELECT_SLEEP_TIME;
+ struct timeval timeout;
+
+ lint_lock ();
+
+ readfd = malloc (sizeof (nstack_fd_set));
+ writefd = malloc (sizeof (nstack_fd_set));
+ exceptfd = malloc (sizeof (nstack_fd_set));
+ if ((!readfd) || (!writefd) || (!exceptfd))
+ {
+ NSPOL_LOGERR ("malloc nstack_fd_set fail");
+ FREE_FD_SET (readfd, writefd, exceptfd);
+ lint_unlock ();
+ return NULL;
+ }
+
+ /*used nonblock need add block mod later */
+
+ for (;;)
+ {
+ /*wait app calling select no cong cpu */
+ if (!g_select_module.entry_head)
+ {
+ select_sem_wait (&g_select_module.sem);
+ }
+
+ for (inx = 0; inx < get_mode_num (); inx++)
+ {
+
+ fd_size =
+ select_thread_get_fdset (readfd, writefd, exceptfd,
+ &g_select_module, inx);
+ if (fd_size <= 0)
+ {
+ continue;
+ }
+
+ if (g_select_module.get_select_fun_nonblock[inx])
+ {
+ ready =
+ g_select_module.get_select_fun_nonblock[inx] (fd_size,
+ (fd_set *)
+ readfd,
+ (fd_set *)
+ writefd,
+ (fd_set *)
+ exceptfd,
+ &timeout);
+ }
+ else
+ {
+ continue;
+ }
+
+ if (ready > 0)
+ {
+ select_thread_set_fdset (fd_size, readfd, writefd, exceptfd,
+ &g_select_module, inx, 0);
+ }
+ else if (ready < 0)
+ {
+ select_thread_set_fdset (ready, readfd, writefd, exceptfd,
+ &g_select_module, inx, errno);
+ NSSOC_LOGERR ("module[%d] select failed] ret = %d errno = %d",
+ inx, ready, errno);
+ lint_unlock ();
+ break;
+ }
+
+ }
+ select_event_post (&g_select_module);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = sleep_time;
+ lint_unlock ();
+ /*use linux select for timer */
+ nsfw_base_select (1, NULL, NULL, NULL, &timeout);
+ }
+}
+
+/*****************************************************************************
+* Prototype : nssct_create
+* Description : create a select record for eveny fd
+* Input : i32 cfd
+* i32 mfd
+* i32 inx
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*****************************************************************************/
+void
+nssct_create (i32 cfd, i32 mfd, i32 inx)
+{
+ if (g_select_module.inited != TRUE)
+ {
+ return;
+ }
+ select_set_modfd (cfd, inx, mfd);
+ select_set_commfd (mfd, inx, cfd);
+}
+
+/*****************************************************************************
+* Prototype : nssct_close
+* Description : rm the record
+* Input : i32 cfd
+* i32 inx
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*****************************************************************************/
+void
+nssct_close (i32 cfd, i32 inx)
+{
+ if (g_select_module.inited != TRUE)
+ {
+ return;
+ }
+ i32 mfd = select_get_modfd (cfd, inx);
+ select_set_modfd (cfd, inx, -1);
+ select_set_commfd (mfd, inx, -1);
+ select_set_index (cfd, -1);
+}
+
+/*****************************************************************************
+* Prototype : nssct_set_index
+* Description : set select fd index
+* Input : i32 fd
+* i32 inx
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*****************************************************************************/
+void
+nssct_set_index (i32 fd, i32 inx)
+{
+ if (g_select_module.inited != TRUE)
+ {
+ return;
+ }
+ select_set_index (fd, inx);
+}
+
+#endif /* NSTACK_SELECT_MODULE */