mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-27 07:58:07 -04:00
terminal: use async_write() when writing to ptmx
This commit is contained in:
parent
9ae5c311d1
commit
3081898caf
1 changed files with 20 additions and 50 deletions
70
terminal.c
70
terminal.c
|
|
@ -17,6 +17,8 @@
|
||||||
#define LOG_MODULE "terminal"
|
#define LOG_MODULE "terminal"
|
||||||
#define LOG_ENABLE_DBG 0
|
#define LOG_ENABLE_DBG 0
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "async.h"
|
||||||
#include "grid.h"
|
#include "grid.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "vt.h"
|
#include "vt.h"
|
||||||
|
|
@ -27,48 +29,6 @@
|
||||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
|
||||||
enum ptmx_write_status {PTMX_WRITE_DONE, PTMX_WRITE_REMAIN, PTMX_WRITE_ERR};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Primitive that writes data to the slave/client
|
|
||||||
*
|
|
||||||
* _data: points to the beginning of the buffer
|
|
||||||
* len: total size of the data buffer
|
|
||||||
* idx: pointer to byte offset into data buffer - writing starts here.
|
|
||||||
*
|
|
||||||
* Thus, the total amount of data to write is (len - *idx). *idx is
|
|
||||||
* updated such that it points to the next unwritten byte in the data
|
|
||||||
* buffer.
|
|
||||||
*
|
|
||||||
* I.e. if the return value is:
|
|
||||||
* - PTMX_WRITE_DONE, then the *idx == len.
|
|
||||||
* - PTMX_WRITE_REMAIN, then *idx < len
|
|
||||||
* - PTMX_WRITE_ERR, there was an error, and no data was written
|
|
||||||
*/
|
|
||||||
static enum ptmx_write_status
|
|
||||||
to_slave(struct terminal *term, const void *_data, size_t len, size_t *idx)
|
|
||||||
{
|
|
||||||
const uint8_t *const data = _data;
|
|
||||||
size_t left = len - *idx;
|
|
||||||
|
|
||||||
while (left > 0) {
|
|
||||||
ssize_t ret = write(term->ptmx, &data[*idx], left);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
|
||||||
return PTMX_WRITE_REMAIN;
|
|
||||||
|
|
||||||
LOG_ERRNO("failed to write to client");
|
|
||||||
return PTMX_WRITE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*idx += ret;
|
|
||||||
left -= left;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PTMX_WRITE_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
term_to_slave(struct terminal *term, const void *_data, size_t len)
|
term_to_slave(struct terminal *term, const void *_data, size_t len)
|
||||||
{
|
{
|
||||||
|
|
@ -82,15 +42,19 @@ term_to_slave(struct terminal *term, const void *_data, size_t len)
|
||||||
* switch to asynchronous.
|
* switch to asynchronous.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
switch (to_slave(term, _data, len, &(size_t){0})) {
|
switch (async_write(term->ptmx, _data, len, &(size_t){0})) {
|
||||||
case PTMX_WRITE_REMAIN:
|
case ASYNC_WRITE_REMAIN:
|
||||||
/* Switch to asynchronous mode; let FDM write the remaining data */
|
/* Switch to asynchronous mode; let FDM write the remaining data */
|
||||||
if (!fdm_event_add(term->fdm, term->ptmx, EPOLLOUT))
|
if (!fdm_event_add(term->fdm, term->ptmx, EPOLLOUT))
|
||||||
return false;
|
return false;
|
||||||
goto enqueue_data;
|
goto enqueue_data;
|
||||||
|
|
||||||
case PTMX_WRITE_DONE: return true;
|
case ASYNC_WRITE_DONE:
|
||||||
case PTMX_WRITE_ERR: return false;
|
return true;
|
||||||
|
|
||||||
|
case ASYNC_WRITE_ERR:
|
||||||
|
LOG_ERRNO("failed to synchronously write %zu bytes to slave", len);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shouldn't get here */
|
/* Shouldn't get here */
|
||||||
|
|
@ -126,14 +90,20 @@ fdm_ptmx_out(struct fdm *fdm, int fd, int events, void *data)
|
||||||
|
|
||||||
/* Don't use pop() since we may not be able to write the entire buffer */
|
/* Don't use pop() since we may not be able to write the entire buffer */
|
||||||
tll_foreach(term->ptmx_buffer, it) {
|
tll_foreach(term->ptmx_buffer, it) {
|
||||||
switch (to_slave(term, it->item.data, it->item.len, &it->item.idx)) {
|
switch (async_write(term->ptmx, it->item.data, it->item.len, &it->item.idx)) {
|
||||||
case PTMX_WRITE_DONE:
|
case ASYNC_WRITE_DONE:
|
||||||
free(it->item.data);
|
free(it->item.data);
|
||||||
tll_remove(term->ptmx_buffer, it);
|
tll_remove(term->ptmx_buffer, it);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PTMX_WRITE_REMAIN: return true; /* to_slave() updated it->item.idx */
|
case ASYNC_WRITE_REMAIN:
|
||||||
case PTMX_WRITE_ERR: return false;
|
/* to_slave() updated it->item.idx */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ASYNC_WRITE_ERR:
|
||||||
|
LOG_ERRNO("failed to asynchronously write %zu bytes to slave",
|
||||||
|
it->item.len - it->item.idx);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue