drivers/telnet: Remove io work thread

The thread isn't really needed but complicate the workflow

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao
2022-09-29 00:29:04 +08:00
committed by Masayuki Ishikawa
parent c3b6d35290
commit 0fa17f32f2
9 changed files with 20 additions and 248 deletions
@@ -127,7 +127,6 @@ CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_PROGNAME="init" CONFIG_SYSTEM_NSH_PROGNAME="init"
CONFIG_SYSTEM_PING=y CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_TELNETD=y CONFIG_SYSTEM_TELNETD=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TESTING_GETPRIME=y CONFIG_TESTING_GETPRIME=y
CONFIG_TLS_TASK_NELEM=4 CONFIG_TLS_TASK_NELEM=4
CONFIG_UART1_SERIAL_CONSOLE=y CONFIG_UART1_SERIAL_CONSOLE=y
@@ -128,7 +128,6 @@ CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_PROGNAME="init" CONFIG_SYSTEM_NSH_PROGNAME="init"
CONFIG_SYSTEM_PING=y CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_TELNETD=y CONFIG_SYSTEM_TELNETD=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TESTING_GETPRIME=y CONFIG_TESTING_GETPRIME=y
CONFIG_TESTING_SMP=y CONFIG_TESTING_SMP=y
CONFIG_TLS_TASK_NELEM=4 CONFIG_TLS_TASK_NELEM=4
@@ -90,7 +90,6 @@ CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y CONFIG_SYSTEM_PING=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048 CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TLS_TASK_NELEM=4 CONFIG_TLS_TASK_NELEM=4
CONFIG_UART0_SERIAL_CONSOLE=y CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_WIRELESS=y CONFIG_WIRELESS=y
@@ -127,7 +127,6 @@ CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y CONFIG_SYSTEM_PING=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048 CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TLS_TASK_NELEM=4 CONFIG_TLS_TASK_NELEM=4
CONFIG_UART0_SERIAL_CONSOLE=y CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_WIRELESS=y CONFIG_WIRELESS=y
@@ -97,7 +97,6 @@ CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_STACKMONITOR=y CONFIG_SYSTEM_STACKMONITOR=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048 CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TLS_TASK_NELEM=4 CONFIG_TLS_TASK_NELEM=4
CONFIG_UART0_SERIAL_CONSOLE=y CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_WIRELESS=y CONFIG_WIRELESS=y
@@ -85,7 +85,6 @@ CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_STACKMONITOR=y CONFIG_SYSTEM_STACKMONITOR=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048 CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TLS_TASK_NELEM=4 CONFIG_TLS_TASK_NELEM=4
CONFIG_UART0_SERIAL_CONSOLE=y CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_WIRELESS=y CONFIG_WIRELESS=y
@@ -106,7 +106,6 @@ CONFIG_SYSTEM_NTPC=y
CONFIG_SYSTEM_PING=y CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_SYSTEM=y CONFIG_SYSTEM_SYSTEM=y
CONFIG_SYSTEM_TASKSET=y CONFIG_SYSTEM_TASKSET=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=1280
CONFIG_TESTING_GETPRIME=y CONFIG_TESTING_GETPRIME=y
CONFIG_TESTING_OSTEST=y CONFIG_TESTING_OSTEST=y
CONFIG_TESTING_SMP=y CONFIG_TESTING_SMP=y
-8
View File
@@ -82,14 +82,6 @@ config TELNET_CHARACTER_MODE
will echo a character which telnet client sent. By default, it works will echo a character which telnet client sent. By default, it works
in line mode. in line mode.
config TELNET_IOTHREAD_PRIORITY
int "I/O thread priority"
default 100
config TELNET_IOTHREAD_STACKSIZE
int "I/O thread stack size"
default 1024
config TELNET_SUPPORT_NAWS config TELNET_SUPPORT_NAWS
bool "Support NAWS (Negotiate About Window Size)" bool "Support NAWS (Negotiate About Window Size)"
default n default n
+20 -233
View File
@@ -59,14 +59,6 @@
# define CONFIG_TELNET_MAXLCLIENTS 8 # define CONFIG_TELNET_MAXLCLIENTS 8
#endif #endif
#ifndef CONFIG_TELNET_IOTHREAD_PRIORITY
# define CONFIG_TELNET_IOTHREAD_PRIORITY 100
#endif
#ifndef CONFIG_TELNET_IOTHREAD_STACKSIZE
# define CONFIG_TELNET_IOTHREAD_STACKSIZE 1024
#endif
#undef HAVE_SIGNALS #undef HAVE_SIGNALS
#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP) #if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)
# define HAVE_SIGNALS # define HAVE_SIGNALS
@@ -120,8 +112,6 @@ enum telnet_state_e
struct telnet_dev_s struct telnet_dev_s
{ {
sem_t td_exclsem; /* Enforces mutually exclusive access */
sem_t td_iosem; /* I/O thread will notify that data is available */
uint8_t td_state; /* (See telnet_state_e) */ uint8_t td_state; /* (See telnet_state_e) */
uint8_t td_crefs; /* The number of open references to the session */ uint8_t td_crefs; /* The number of open references to the session */
uint8_t td_minor; /* Minor device number */ uint8_t td_minor; /* Minor device number */
@@ -135,7 +125,6 @@ struct telnet_dev_s
#ifdef HAVE_SIGNALS #ifdef HAVE_SIGNALS
pid_t td_pid; pid_t td_pid;
#endif #endif
struct pollfd td_fds;
FAR struct socket td_psock; /* A clone of the internal socket structure */ FAR struct socket td_psock; /* A clone of the internal socket structure */
char td_rxbuffer[CONFIG_TELNET_RXBUFFER_SIZE]; char td_rxbuffer[CONFIG_TELNET_RXBUFFER_SIZE];
char td_txbuffer[CONFIG_TELNET_TXBUFFER_SIZE]; char td_txbuffer[CONFIG_TELNET_TXBUFFER_SIZE];
@@ -162,7 +151,6 @@ static bool telnet_putchar(FAR struct telnet_dev_s *priv, uint8_t ch,
int *nwritten); int *nwritten);
static void telnet_sendopt(FAR struct telnet_dev_s *priv, uint8_t option, static void telnet_sendopt(FAR struct telnet_dev_s *priv, uint8_t option,
uint8_t value); uint8_t value);
static int telnet_io_main(int argc, FAR char** argv);
/* Telnet character driver methods */ /* Telnet character driver methods */
@@ -227,9 +215,7 @@ static const struct file_operations g_factory_fops =
* characters received via Telenet (via Ctrl-C SIGINT, in particular). * characters received via Telenet (via Ctrl-C SIGINT, in particular).
*/ */
static pid_t g_telnet_io_kthread = INVALID_PROCESS_ID;
static struct telnet_dev_s *g_telnet_clients[CONFIG_TELNET_MAXLCLIENTS]; static struct telnet_dev_s *g_telnet_clients[CONFIG_TELNET_MAXLCLIENTS];
static sem_t g_iosem = SEM_INITIALIZER(0);
static sem_t g_clients_sem = SEM_INITIALIZER(1); static sem_t g_clients_sem = SEM_INITIALIZER(1);
/**************************************************************************** /****************************************************************************
@@ -644,7 +630,7 @@ static int telnet_open(FAR struct file *filep)
/* Get exclusive access to the device structures */ /* Get exclusive access to the device structures */
ret = nxsem_wait(&priv->td_exclsem); ret = nxsem_wait(&g_clients_sem);
if (ret < 0) if (ret < 0)
{ {
nerr("ERROR: nxsem_wait failed: %d\n", ret); nerr("ERROR: nxsem_wait failed: %d\n", ret);
@@ -671,7 +657,7 @@ static int telnet_open(FAR struct file *filep)
ret = OK; ret = OK;
errout_with_sem: errout_with_sem:
nxsem_post(&priv->td_exclsem); nxsem_post(&g_clients_sem);
errout: errout:
return ret; return ret;
@@ -693,11 +679,11 @@ static int telnet_close(FAR struct file *filep)
/* Get exclusive access to the device structures */ /* Get exclusive access to the device structures */
ret = nxsem_wait(&priv->td_exclsem); ret = nxsem_wait(&g_clients_sem);
if (ret < 0) if (ret < 0)
{ {
nerr("ERROR: nxsem_wait failed: %d\n", ret); nerr("ERROR: nxsem_wait failed: %d\n", ret);
goto errout; return ret;
} }
/* Decrement the references to the driver. If the reference count will /* Decrement the references to the driver. If the reference count will
@@ -709,7 +695,6 @@ static int telnet_close(FAR struct file *filep)
/* Just decrement the reference count and release the semaphore */ /* Just decrement the reference count and release the semaphore */
priv->td_crefs--; priv->td_crefs--;
nxsem_post(&priv->td_exclsem);
} }
else else
{ {
@@ -748,9 +733,6 @@ static int telnet_close(FAR struct file *filep)
kmm_free(devpath); kmm_free(devpath);
} }
/* Remove ourself from the clients list */
nxsem_wait(&g_clients_sem);
for (i = 0; i < CONFIG_TELNET_MAXLCLIENTS; i++) for (i = 0; i < CONFIG_TELNET_MAXLCLIENTS; i++)
{ {
if (g_telnet_clients[i] == priv) if (g_telnet_clients[i] == priv)
@@ -760,40 +742,13 @@ static int telnet_close(FAR struct file *filep)
} }
} }
/* If the socket is still polling */
if (priv->td_fds.events)
{
/* Tear down the poll */
psock_poll(&priv->td_psock, &priv->td_fds, FALSE);
priv->td_fds.events = 0;
}
nxsem_post(&g_clients_sem);
/* Notify the I/O thread that a client was removed */
nxsem_post(&g_iosem);
/* Close the socket */ /* Close the socket */
psock_close(&priv->td_psock); psock_close(&priv->td_psock);
/* Release the driver memory. What if there are threads waiting on
* td_exclsem? They will never be awakened! How could this happen?
* crefs == 1 so there are no other open references to the driver.
* But this could have if someone were trying to re-open the driver
* after every other thread has closed it. That really should not
* happen in the intended usage model.
*/
DEBUGASSERT(priv->td_exclsem.semcount == 0);
nxsem_destroy(&priv->td_exclsem);
kmm_free(priv); kmm_free(priv);
} }
errout: nxsem_post(&g_clients_sem);
return ret; return ret;
} }
@@ -807,7 +762,6 @@ static ssize_t telnet_read(FAR struct file *filep, FAR char *buffer,
FAR struct inode *inode = filep->f_inode; FAR struct inode *inode = filep->f_inode;
FAR struct telnet_dev_s *priv = inode->i_private; FAR struct telnet_dev_s *priv = inode->i_private;
ssize_t nread = 0; ssize_t nread = 0;
int ret;
ninfo("len: %zd\n", len); ninfo("len: %zd\n", len);
@@ -824,54 +778,32 @@ static ssize_t telnet_read(FAR struct file *filep, FAR char *buffer,
if (priv->td_pending == 0) if (priv->td_pending == 0)
{ {
/* poll fds.revents contains last poll status in case of error */ nread = psock_recv(&priv->td_psock,
priv->td_rxbuffer,
if ((priv->td_fds.revents & (POLLHUP | POLLERR)) != 0) CONFIG_TELNET_RXBUFFER_SIZE,
0);
if (nread <= 0)
{ {
return -EPIPE; return nread;
} }
if (filep->f_oflags & O_NONBLOCK) priv->td_pending = nread;
{
return -EAGAIN;
}
/* Wait for new data, interrupt, or thread cancellation */
ret = nxsem_wait(&priv->td_iosem);
if (ret < 0)
{
nerr("ERROR: nxsem_wait failed: %d\n", ret);
return (ssize_t)ret;
}
continue;
}
/* Take exclusive access to data buffer */
ret = nxsem_wait(&priv->td_exclsem);
if (ret < 0)
{
nerr("ERROR: nxsem_wait failed: %d\n", ret);
return (ssize_t)ret;
} }
/* Process the buffered telnet data */ /* Process the buffered telnet data */
src = &priv->td_rxbuffer[priv->td_offset]; src = &priv->td_rxbuffer[priv->td_offset];
nread = telnet_receive(priv, src, priv->td_pending, buffer, len); nread = telnet_receive(priv, src, priv->td_pending, buffer, len);
nxsem_post(&priv->td_exclsem);
} }
while (nread == 0); while (nread == 0);
/* Notify the I/O thread the rxbuffer is available */ #ifdef HAVE_SIGNALS
/* Check if any of the received characters is a
* control that should generate a signal.
*/
if (nread > 0) telnet_check_ctrlchar(priv, buffer, nread);
{ #endif
nxsem_post(&g_iosem);
}
/* Returned Value: /* Returned Value:
* *
@@ -893,8 +825,8 @@ static ssize_t telnet_write(FAR struct file *filep, FAR const char *buffer,
FAR struct inode *inode = filep->f_inode; FAR struct inode *inode = filep->f_inode;
FAR struct telnet_dev_s *priv = inode->i_private; FAR struct telnet_dev_s *priv = inode->i_private;
FAR const char *src = buffer; FAR const char *src = buffer;
ssize_t ret = 0;
ssize_t nsent; ssize_t nsent;
ssize_t ret;
int ncopied; int ncopied;
char ch; char ch;
bool eol; bool eol;
@@ -990,17 +922,6 @@ static int telnet_session(FAR struct telnet_session_s *session)
return -ENOMEM; return -ENOMEM;
} }
/* Initialize the allocated driver instance */
nxsem_init(&priv->td_exclsem, 0, 1);
nxsem_init(&priv->td_iosem, 0, 0);
/* td_iosem is used for signaling and, hence, must not participate in
* priority inheritance.
*/
nxsem_set_protocol(&priv->td_iosem, SEM_PRIO_NONE);
priv->td_state = STATE_NORMAL; priv->td_state = STATE_NORMAL;
priv->td_crefs = 0; priv->td_crefs = 0;
priv->td_minor = 0; priv->td_minor = 0;
@@ -1091,32 +1012,10 @@ static int telnet_session(FAR struct telnet_session_s *session)
telnet_sendopt(priv, TELNET_WILL, TELNET_ECHO); telnet_sendopt(priv, TELNET_WILL, TELNET_ECHO);
#endif #endif
/* Has the I/O thread been started? */
if (g_telnet_io_kthread == INVALID_PROCESS_ID)
{
/* g_iosem is used for signaling and, hence, must not participate in
* priority inheritance.
*/
nxsem_set_protocol(&g_iosem, SEM_PRIO_NONE);
/* Start the I/O thread */
ret = kthread_create("telnet_io", CONFIG_TELNET_IOTHREAD_PRIORITY,
CONFIG_TELNET_IOTHREAD_STACKSIZE, telnet_io_main,
NULL);
if (ret > 0)
{
g_telnet_io_kthread = ret;
}
}
/* Save ourself in the list of Telnet client threads */ /* Save ourself in the list of Telnet client threads */
g_telnet_clients[priv->td_minor] = priv; g_telnet_clients[priv->td_minor] = priv;
nxsem_post(&g_clients_sem); nxsem_post(&g_clients_sem);
nxsem_post(&g_iosem);
return OK; return OK;
@@ -1197,11 +1096,10 @@ static int telnet_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
#endif #endif
default: default:
ret = -ENOTTY; ret = psock_ioctl(&priv->td_psock, cmd, arg);
break; break;
} }
UNUSED(priv); /* Avoid warning if not used */
return ret; return ret;
} }
@@ -1245,117 +1143,6 @@ static int telnet_poll(FAR struct file *filep, FAR struct pollfd *fds,
return psock_poll(&priv->td_psock, fds, setup); return psock_poll(&priv->td_psock, fds, setup);
} }
/****************************************************************************
* Name: telnet_io_main
****************************************************************************/
static int telnet_io_main(int argc, FAR char** argv)
{
FAR struct telnet_dev_s *priv;
FAR char *buffer;
int i;
int ret;
while (1)
{
nxsem_reset(&g_iosem, 0);
/* Poll each client in the g_telnet_clients[] array. */
nxsem_wait(&g_clients_sem);
for (i = 0; i < CONFIG_TELNET_MAXLCLIENTS; i++)
{
priv = g_telnet_clients[i];
if (priv != NULL &&
!(priv->td_fds.revents & (POLLHUP | POLLERR)) &&
(CONFIG_TELNET_RXBUFFER_SIZE -
priv->td_pending - priv->td_offset) > 0)
{
priv->td_fds.sem = &g_iosem;
priv->td_fds.events = POLLIN | POLLHUP | POLLERR;
priv->td_fds.revents = 0;
psock_poll(&priv->td_psock, &priv->td_fds, TRUE);
}
}
nxsem_post(&g_clients_sem);
/* Wait for any Telnet connect/disconnect events
* to include/remove client sockets from polling
*/
nxsem_wait(&g_iosem);
/* Revisit each client in the g_telnet_clients[] array */
nxsem_wait(&g_clients_sem);
for (i = 0; i < CONFIG_TELNET_MAXLCLIENTS; i++)
{
priv = g_telnet_clients[i];
/* If poll was setup previously (events != 0) */
if (priv != NULL && priv->td_fds.events)
{
/* Check for a pending poll() */
if (priv->td_fds.revents & POLLIN)
{
if (priv->td_pending < CONFIG_TELNET_RXBUFFER_SIZE)
{
/* Take exclusive access to data buffer */
nxsem_wait(&priv->td_exclsem);
buffer = priv->td_rxbuffer + priv->td_pending +
priv->td_offset;
ret = psock_recv(&priv->td_psock, buffer,
CONFIG_TELNET_RXBUFFER_SIZE -
priv->td_pending - priv->td_offset,
0);
priv->td_pending += ret;
nxsem_post(&priv->td_exclsem);
/* Notify the client thread that data is available */
nxsem_post(&priv->td_iosem);
#ifdef HAVE_SIGNALS
/* Check if any of the received characters is a
* control that should generate a signal.
*/
telnet_check_ctrlchar(priv, buffer, ret);
#endif
}
}
/* Tear it down */
psock_poll(&priv->td_psock, &priv->td_fds, FALSE);
priv->td_fds.events = 0;
/* POLLHUP (or POLLERR) indicates that this session has
* terminated.
*/
if (priv->td_fds.revents & (POLLHUP | POLLERR))
{
/* notify the client thread */
nxsem_post(&priv->td_iosem);
}
}
}
nxsem_post(&g_clients_sem);
}
return 0;
}
/**************************************************************************** /****************************************************************************
* Name: factory_ioctl * Name: factory_ioctl
****************************************************************************/ ****************************************************************************/