mirror of
https://github.com/tio/tio.git
synced 2026-05-01 14:57:59 +02:00
Add write_poll to improve tty_write and tty_sync
Implement blockable write with poll + nonblock write.
This commit is contained in:
parent
b5656112d7
commit
eab0f6245b
4 changed files with 62 additions and 10 deletions
34
src/misc.c
34
src/misc.c
|
|
@ -111,6 +111,40 @@ int read_poll(int fd, void *data, size_t len, int timeout)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t write_poll(int fd, void *data, size_t len, int timeout)
|
||||||
|
{
|
||||||
|
struct pollfd fds;
|
||||||
|
ssize_t ret = 0;
|
||||||
|
|
||||||
|
fds.events = POLLOUT;
|
||||||
|
fds.fd = fd;
|
||||||
|
|
||||||
|
/* Wait data available */
|
||||||
|
ret = poll(&fds, 1, timeout);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
tio_error_print("%s", strerror(errno));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else if (ret > 0)
|
||||||
|
{
|
||||||
|
if (fds.revents & POLLOUT)
|
||||||
|
{
|
||||||
|
// Ready to write
|
||||||
|
// return value should not be 0
|
||||||
|
return write(fd, data, len);
|
||||||
|
}
|
||||||
|
else /* if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) */
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Timeout */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function to calculate djb2 hash of string
|
// Function to calculate djb2 hash of string
|
||||||
unsigned long djb2_hash(const unsigned char *str)
|
unsigned long djb2_hash(const unsigned char *str)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define WRITE_POLL_FOREVER (-1)
|
||||||
#define UNUSED(expr) do { (void)(expr); } while (0)
|
#define UNUSED(expr) do { (void)(expr); } while (0)
|
||||||
|
|
||||||
void delay(long ms);
|
void delay(long ms);
|
||||||
|
|
@ -32,6 +33,7 @@ bool regex_match(const char *string, const char *pattern);
|
||||||
unsigned long djb2_hash(const unsigned char *str);
|
unsigned long djb2_hash(const unsigned char *str);
|
||||||
void *base62_encode(unsigned long num, char *output);
|
void *base62_encode(unsigned long num, char *output);
|
||||||
int read_poll(int fd, void *data, size_t len, int timeout);
|
int read_poll(int fd, void *data, size_t len, int timeout);
|
||||||
|
ssize_t write_poll(int fd, const void *data, size_t len, int timeout);
|
||||||
double get_current_time(void);
|
double get_current_time(void);
|
||||||
bool match_patterns(const char *string, const char *patterns);
|
bool match_patterns(const char *string, const char *patterns);
|
||||||
int execute_shell_command(int fd, const char *command);
|
int execute_shell_command(int fd, const char *command);
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,7 @@ static int api_write(lua_State *L)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ret = write(device_fd, string, len);
|
ret = write_poll(device_fd, string, len, WRITE_POLL_FOREVER);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return luaL_error(L, "%s", strerror(errno));
|
return luaL_error(L, "%s", strerror(errno));
|
||||||
|
|
||||||
|
|
|
||||||
34
src/tty.c
34
src/tty.c
|
|
@ -238,28 +238,43 @@ inline static unsigned char char_to_nibble(char c)
|
||||||
|
|
||||||
void tty_sync(int fd)
|
void tty_sync(int fd)
|
||||||
{
|
{
|
||||||
|
/* If output_delay is valid, tty_buffer should be already empty.
|
||||||
|
* So this function doesn't consider output_delay options. */
|
||||||
ssize_t count;
|
ssize_t count;
|
||||||
|
size_t remain = tty_buffer_count;
|
||||||
|
char *cp = tty_buffer;
|
||||||
|
|
||||||
while (tty_buffer_count > 0)
|
while (remain > 0)
|
||||||
{
|
{
|
||||||
count = write(fd, tty_buffer, tty_buffer_count);
|
count = write_poll(fd, cp, remain, WRITE_POLL_FOREVER);
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
{
|
{
|
||||||
// Error
|
// Error
|
||||||
tio_debug_printf("Write error while flushing tty buffer (%s)", strerror(errno));
|
tio_debug_printf("Write error while flushing tty buffer (%s)", strerror(errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tty_buffer_count -= count;
|
cp += count;
|
||||||
fsync(fd);
|
remain -= count;
|
||||||
tcdrain(fd);
|
|
||||||
|
/* Reduce the number of additional sends */
|
||||||
|
if (remain > 0)
|
||||||
|
{
|
||||||
|
int estimated_sendtime_us = (int)((int64_t)count * 10 * 1000 * 1000 / option.baudrate);
|
||||||
|
if (estimated_sendtime_us > 300 * 1000)
|
||||||
|
usleep(300 * 1000);
|
||||||
|
else
|
||||||
|
usleep(estimated_sendtime_us);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
fsync(fd);
|
||||||
|
tcdrain(fd);
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
tty_buffer_write_ptr = tty_buffer;
|
tty_buffer_write_ptr = tty_buffer;
|
||||||
tty_buffer_count = 0;
|
tty_buffer_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t tty_write(int fd, const void *buffer, size_t count)
|
ssize_t tty_write(int fd, void *buffer, size_t count)
|
||||||
{
|
{
|
||||||
ssize_t retval = 0, bytes_written = 0;
|
ssize_t retval = 0, bytes_written = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
@ -279,7 +294,7 @@ ssize_t tty_write(int fd, const void *buffer, size_t count)
|
||||||
// Write byte by byte with output delay
|
// Write byte by byte with output delay
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
retval = write(fd, &cbuf[i], 1);
|
retval = write_poll(fd, &cbuf[i], 1, WRITE_POLL_FOREVER);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
{
|
{
|
||||||
// Error
|
// Error
|
||||||
|
|
@ -2526,7 +2541,7 @@ void forward_to_tty(int fd, char output_char)
|
||||||
/* Map newline character */
|
/* Map newline character */
|
||||||
if ((output_char == '\n' || output_char == '\r') && (option.map_o_nl_crnl))
|
if ((output_char == '\n' || output_char == '\r') && (option.map_o_nl_crnl))
|
||||||
{
|
{
|
||||||
const char *crlf = "\r\n";
|
char crlf[] = "\r\n";
|
||||||
|
|
||||||
optional_local_echo(crlf[0]);
|
optional_local_echo(crlf[0]);
|
||||||
optional_local_echo(crlf[1]);
|
optional_local_echo(crlf[1]);
|
||||||
|
|
@ -2730,7 +2745,7 @@ int tty_connect(void)
|
||||||
else if (ret > 0)
|
else if (ret > 0)
|
||||||
{
|
{
|
||||||
// Forward to tty device
|
// Forward to tty device
|
||||||
ret = write(device_fd, &input_char, 1);
|
ret = write_poll(device_fd, &input_char, 1, WRITE_POLL_FOREVER);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
tio_error_printf("Could not write to serial device (%s)", strerror(errno));
|
tio_error_printf("Could not write to serial device (%s)", strerror(errno));
|
||||||
|
|
@ -2743,6 +2758,7 @@ int tty_connect(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tty_sync(device_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Manage script activation */
|
/* Manage script activation */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue