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

View File

@ -127,7 +127,6 @@ CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_PROGNAME="init"
CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_TELNETD=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TESTING_GETPRIME=y
CONFIG_TLS_TASK_NELEM=4
CONFIG_UART1_SERIAL_CONSOLE=y

View File

@ -128,7 +128,6 @@ CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_PROGNAME="init"
CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_TELNETD=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TESTING_GETPRIME=y
CONFIG_TESTING_SMP=y
CONFIG_TLS_TASK_NELEM=4

View File

@ -90,7 +90,6 @@ CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TLS_TASK_NELEM=4
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_WIRELESS=y

View File

@ -127,7 +127,6 @@ CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TLS_TASK_NELEM=4
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_WIRELESS=y

View File

@ -97,7 +97,6 @@ CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_STACKMONITOR=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TLS_TASK_NELEM=4
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_WIRELESS=y

View File

@ -85,7 +85,6 @@ CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_STACKMONITOR=y
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=2048
CONFIG_TELNET_CHARACTER_MODE=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=2048
CONFIG_TLS_TASK_NELEM=4
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_WIRELESS=y

View File

@ -106,7 +106,6 @@ CONFIG_SYSTEM_NTPC=y
CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_SYSTEM=y
CONFIG_SYSTEM_TASKSET=y
CONFIG_TELNET_IOTHREAD_STACKSIZE=1280
CONFIG_TESTING_GETPRIME=y
CONFIG_TESTING_OSTEST=y
CONFIG_TESTING_SMP=y

View File

@ -82,14 +82,6 @@ config TELNET_CHARACTER_MODE
will echo a character which telnet client sent. By default, it works
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
bool "Support NAWS (Negotiate About Window Size)"
default n

View File

@ -59,14 +59,6 @@
# define CONFIG_TELNET_MAXLCLIENTS 8
#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
#if defined(CONFIG_TTY_SIGINT) || defined(CONFIG_TTY_SIGTSTP)
# define HAVE_SIGNALS
@ -120,8 +112,6 @@ enum telnet_state_e
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_crefs; /* The number of open references to the session */
uint8_t td_minor; /* Minor device number */
@ -135,7 +125,6 @@ struct telnet_dev_s
#ifdef HAVE_SIGNALS
pid_t td_pid;
#endif
struct pollfd td_fds;
FAR struct socket td_psock; /* A clone of the internal socket structure */
char td_rxbuffer[CONFIG_TELNET_RXBUFFER_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);
static void telnet_sendopt(FAR struct telnet_dev_s *priv, uint8_t option,
uint8_t value);
static int telnet_io_main(int argc, FAR char** argv);
/* 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).
*/
static pid_t g_telnet_io_kthread = INVALID_PROCESS_ID;
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);
/****************************************************************************
@ -644,7 +630,7 @@ static int telnet_open(FAR struct file *filep)
/* Get exclusive access to the device structures */
ret = nxsem_wait(&priv->td_exclsem);
ret = nxsem_wait(&g_clients_sem);
if (ret < 0)
{
nerr("ERROR: nxsem_wait failed: %d\n", ret);
@ -671,7 +657,7 @@ static int telnet_open(FAR struct file *filep)
ret = OK;
errout_with_sem:
nxsem_post(&priv->td_exclsem);
nxsem_post(&g_clients_sem);
errout:
return ret;
@ -693,11 +679,11 @@ static int telnet_close(FAR struct file *filep)
/* Get exclusive access to the device structures */
ret = nxsem_wait(&priv->td_exclsem);
ret = nxsem_wait(&g_clients_sem);
if (ret < 0)
{
nerr("ERROR: nxsem_wait failed: %d\n", ret);
goto errout;
return ret;
}
/* 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 */
priv->td_crefs--;
nxsem_post(&priv->td_exclsem);
}
else
{
@ -748,9 +733,6 @@ static int telnet_close(FAR struct file *filep)
kmm_free(devpath);
}
/* Remove ourself from the clients list */
nxsem_wait(&g_clients_sem);
for (i = 0; i < CONFIG_TELNET_MAXLCLIENTS; i++)
{
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 */
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);
}
errout:
nxsem_post(&g_clients_sem);
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 telnet_dev_s *priv = inode->i_private;
ssize_t nread = 0;
int ret;
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)
{
/* poll fds.revents contains last poll status in case of error */
if ((priv->td_fds.revents & (POLLHUP | POLLERR)) != 0)
nread = psock_recv(&priv->td_psock,
priv->td_rxbuffer,
CONFIG_TELNET_RXBUFFER_SIZE,
0);
if (nread <= 0)
{
return -EPIPE;
return nread;
}
if (filep->f_oflags & O_NONBLOCK)
{
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;
priv->td_pending = nread;
}
/* Process the buffered telnet data */
src = &priv->td_rxbuffer[priv->td_offset];
nread = telnet_receive(priv, src, priv->td_pending, buffer, len);
nxsem_post(&priv->td_exclsem);
}
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)
{
nxsem_post(&g_iosem);
}
telnet_check_ctrlchar(priv, buffer, nread);
#endif
/* 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 telnet_dev_s *priv = inode->i_private;
FAR const char *src = buffer;
ssize_t ret = 0;
ssize_t nsent;
ssize_t ret;
int ncopied;
char ch;
bool eol;
@ -990,17 +922,6 @@ static int telnet_session(FAR struct telnet_session_s *session)
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_crefs = 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);
#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 */
g_telnet_clients[priv->td_minor] = priv;
nxsem_post(&g_clients_sem);
nxsem_post(&g_iosem);
return OK;
@ -1197,11 +1096,10 @@ static int telnet_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
#endif
default:
ret = -ENOTTY;
ret = psock_ioctl(&priv->td_psock, cmd, arg);
break;
}
UNUSED(priv); /* Avoid warning if not used */
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);
}
/****************************************************************************
* 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
****************************************************************************/