Support fswait in tty

This commit is contained in:
Kevin Lange 2017-01-06 19:01:22 +09:00
parent 665343e636
commit 7d47cab8ab
10 changed files with 193 additions and 156 deletions

View File

@ -5,6 +5,7 @@
*/
#include <system.h>
#include <ringbuffer.h>
#include <process.h>
size_t ring_buffer_unread(ring_buffer_t * ring_buffer) {
if (ring_buffer->read_ptr == ring_buffer->write_ptr) {
@ -48,6 +49,26 @@ static inline void ring_buffer_increment_write(ring_buffer_t * ring_buffer) {
}
}
static void ring_buffer_alert_waiters(ring_buffer_t * ring_buffer) {
if (ring_buffer->alert_waiters) {
while (ring_buffer->alert_waiters->head) {
node_t * node = list_dequeue(ring_buffer->alert_waiters);
process_t * p = node->value;
process_alert_node(p, ring_buffer);
free(node);
}
}
}
void ring_buffer_select_wait(ring_buffer_t * ring_buffer, void * process) {
if (!ring_buffer->alert_waiters) {
ring_buffer->alert_waiters = list_create();
}
list_insert(ring_buffer->alert_waiters, process);
list_insert(((process_t *)process)->node_waits, ring_buffer);
}
size_t ring_buffer_read(ring_buffer_t * ring_buffer, size_t size, uint8_t * buffer) {
size_t collected = 0;
while (collected == 0) {
@ -83,6 +104,7 @@ size_t ring_buffer_write(ring_buffer_t * ring_buffer, size_t size, uint8_t * buf
spin_unlock(ring_buffer->lock);
wakeup_queue(ring_buffer->wait_queue_readers);
ring_buffer_alert_waiters(ring_buffer);
if (written < size) {
if (sleep_on(ring_buffer->wait_queue_writers) && ring_buffer->internal_stop) {
ring_buffer->internal_stop = 0;
@ -92,6 +114,7 @@ size_t ring_buffer_write(ring_buffer_t * ring_buffer, size_t size, uint8_t * buf
}
wakeup_queue(ring_buffer->wait_queue_readers);
ring_buffer_alert_waiters(ring_buffer);
return written;
}
@ -102,6 +125,7 @@ ring_buffer_t * ring_buffer_create(size_t size) {
out->write_ptr = 0;
out->read_ptr = 0;
out->size = size;
out->alert_waiters = NULL;
spin_init(out->lock);
@ -118,6 +142,7 @@ void ring_buffer_destroy(ring_buffer_t * ring_buffer) {
wakeup_queue(ring_buffer->wait_queue_writers);
wakeup_queue(ring_buffer->wait_queue_readers);
ring_buffer_alert_waiters(ring_buffer);
list_free(ring_buffer->wait_queue_writers);
list_free(ring_buffer->wait_queue_readers);

View File

@ -71,17 +71,14 @@ static inline void pipe_increment_write_by(pipe_device_t * pipe, size_t amount)
pipe->write_ptr = (pipe->write_ptr + amount) % pipe->size;
}
static void pipe_alert_waiters(fs_node_t * fs_node) {
pipe_device_t * pipe = (pipe_device_t *)fs_node->device;
static void pipe_alert_waiters(pipe_device_t * pipe) {
if (pipe->alert_waiters) {
while (pipe->alert_waiters->head) {
node_t * node = list_dequeue(pipe->alert_waiters);
process_t * p = node->value;
process_alert_node(p, fs_node);
process_alert_node(p, pipe);
free(node);
}
}
}
@ -180,7 +177,7 @@ uint32_t write_pipe(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *bu
spin_unlock(pipe->lock_write);
wakeup_queue(pipe->wait_queue_readers);
pipe_alert_waiters(node);
pipe_alert_waiters(pipe);
if (written < size) {
sleep_on(pipe->wait_queue_writers);
}
@ -249,11 +246,6 @@ static int pipe_wait(fs_node_t * node, void * process) {
return 0;
}
static int pipe_match(fs_node_t * node, void * value) {
pipe_device_t * pipe = (pipe_device_t *)node->device;
return pipe == value;
}
fs_node_t * make_pipe(size_t size) {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
pipe_device_t * pipe = malloc(sizeof(pipe_device_t));
@ -278,7 +270,6 @@ fs_node_t * make_pipe(size_t size) {
fnode->selectcheck = pipe_check;
fnode->selectwait = pipe_wait;
fnode->match = pipe_match;
fnode->atime = now();
fnode->mtime = fnode->atime;

View File

@ -280,6 +280,34 @@ int pty_available_output(fs_node_t * node) {
return ring_buffer_unread(pty->out);
}
static int check_pty_master(fs_node_t * node) {
pty_t * pty = (pty_t *)node->device;
if (ring_buffer_unread(pty->out) > 0) {
return 0;
}
return 1;
}
static int check_pty_slave(fs_node_t * node) {
pty_t * pty = (pty_t *)node->device;
if (ring_buffer_unread(pty->in) > 0) {
return 0;
}
return 1;
}
static int wait_pty_master(fs_node_t * node, void * process) {
pty_t * pty = (pty_t *)node->device;
ring_buffer_select_wait(pty->out, process);
return 0;
}
static int wait_pty_slave(fs_node_t * node, void * process) {
pty_t * pty = (pty_t *)node->device;
ring_buffer_select_wait(pty->in, process);
return 0;
}
fs_node_t * pty_master_create(pty_t * pty) {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
memset(fnode, 0x00, sizeof(fs_node_t));
@ -294,6 +322,8 @@ fs_node_t * pty_master_create(pty_t * pty) {
fnode->write = write_pty_master;
fnode->open = open_pty_master;
fnode->close = close_pty_master;
fnode->selectcheck = check_pty_master;
fnode->selectwait = wait_pty_master;
fnode->readdir = NULL;
fnode->finddir = NULL;
fnode->ioctl = ioctl_pty_master;
@ -318,6 +348,8 @@ fs_node_t * pty_slave_create(pty_t * pty) {
fnode->write = write_pty_slave;
fnode->open = open_pty_slave;
fnode->close = close_pty_slave;
fnode->selectcheck = check_pty_slave;
fnode->selectwait = wait_pty_slave;
fnode->readdir = NULL;
fnode->finddir = NULL;
fnode->ioctl = ioctl_pty_slave;

View File

@ -115,16 +115,6 @@ int selectwait_fs(fs_node_t * node, void * process) {
return -1;
}
/**
* fsnode_matches: Compare a node internally against a magic value to determine if the value belongs to that node.
*/
int fsnode_matches(fs_node_t * node, void * value) {
if (!node) return 0;
if (!node->match) return 0;
return node->match(node, value);
}
/**
* read_fs: Read a file system node based on its underlying type.
*

View File

@ -53,7 +53,6 @@ typedef void (*symlink_type_t) (struct fs_node *, char * name, char * value);
typedef int (*readlink_type_t) (struct fs_node *, char * buf, size_t size);
typedef int (*selectcheck_type_t) (struct fs_node *);
typedef int (*selectwait_type_t) (struct fs_node *, void * process);
typedef int (*match_type_t) (struct fs_node *, void * value);
typedef struct fs_node {
char name[256]; /* The filename. */
@ -95,7 +94,6 @@ typedef struct fs_node {
selectcheck_type_t selectcheck;
selectwait_type_t selectwait;
match_type_t match;
} fs_node_t;
struct dirent {
@ -149,7 +147,6 @@ int symlink_fs(char * value, char * name);
int readlink_fs(fs_node_t * node, char * buf, size_t size);
int selectcheck_fs(fs_node_t * node);
int selectwait_fs(fs_node_t * node, void * process);
int fsnode_matches(fs_node_t * node, void * value);
void vfs_install(void);
void * vfs_mount(char * path, fs_node_t * local_root);

View File

@ -137,7 +137,7 @@ extern process_t * kernel_idle_task;
extern list_t * process_list;
extern int process_wait_nodes(process_t * process,fs_node_t * nodes[]);
extern int process_alert_node(process_t * process, fs_node_t * fs_node);
extern int process_alert_node(process_t * process, void * value);
typedef void (*tasklet_t) (void *, char *);
extern int create_kernel_tasklet(tasklet_t tasklet, char * name, void * argp);

View File

@ -10,6 +10,7 @@ typedef struct {
list_t * wait_queue_readers;
list_t * wait_queue_writers;
int internal_stop;
list_t * alert_waiters;
} ring_buffer_t;
size_t ring_buffer_unread(ring_buffer_t * ring_buffer);
@ -21,5 +22,6 @@ size_t ring_buffer_write(ring_buffer_t * ring_buffer, size_t size, uint8_t * buf
ring_buffer_t * ring_buffer_create(size_t size);
void ring_buffer_destroy(ring_buffer_t * ring_buffer);
void ring_buffer_interrupt(ring_buffer_t * ring_buffer);
void ring_buffer_select_wait(ring_buffer_t * ring_buffer, void * process);
#endif

View File

@ -849,14 +849,14 @@ int process_wait_nodes(process_t * process,fs_node_t * nodes[]) {
return process->awoken_index;
}
int process_alert_node(process_t * process, fs_node_t * fs_node) {
int process_alert_node(process_t * process, void * value) {
if (!process->node_waits) {
return 0; /* Possibly already returned. Wait for another call. */
}
int index = 0;
foreach(node, process->node_waits) {
if (fsnode_matches(fs_node, node->value)) {
if (value == node->value) {
process->awoken_index = index;
list_free(process->node_waits);
free(process->node_waits);

View File

@ -238,10 +238,6 @@ static void close_client(fs_node_t * node) {
free(c);
}
static int match_server(fs_node_t * node, void * value) {
pex_ex_t * p = (pex_ex_t *)node->device;
return fsnode_matches(p->server_pipe,value);
}
static int wait_server(fs_node_t * node, void * process) {
pex_ex_t * p = (pex_ex_t *)node->device;
return selectwait_fs(p->server_pipe, process);
@ -251,10 +247,6 @@ static int check_server(fs_node_t * node) {
return selectcheck_fs(p->server_pipe);
}
static int match_client(fs_node_t * node, void * value) {
pex_client_t * c = (pex_client_t *)node->inode;
return fsnode_matches(c->pipe, value);
}
static int wait_client(fs_node_t * node, void * process) {
pex_client_t * c = (pex_client_t *)node->inode;
return selectwait_fs(c->pipe, process);
@ -278,7 +270,6 @@ static void open_pex(fs_node_t * node, unsigned int flags) {
node->ioctl = ioctl_server;
node->selectcheck = check_server;
node->selectwait = wait_server;
node->match = match_server;
debug_print(INFO, "[pex] Server launched: %s", t->name);
debug_print(INFO, "fs_node = 0x%x", node);
} else if (!(flags & O_CREAT)) {
@ -292,7 +283,6 @@ static void open_pex(fs_node_t * node, unsigned int flags) {
node->selectcheck = check_client;
node->selectwait = wait_client;
node->match = match_client;
list_insert(t->clients, client);

View File

@ -1074,11 +1074,13 @@ void key_event(int ret, key_event_t * event) {
}
}
void * wait_for_exit(void * garbage) {
int pid;
do {
pid = waitpid(-1, NULL, 0);
} while (pid == -1 && errno == EINTR);
void check_for_exit(void) {
if (exit_application) return;
int pid = waitpid(-1, NULL, WNOHANG);
if (pid != child_pid) return;
/* Clean up */
exit_application = 1;
/* Exit */
@ -1251,122 +1253,123 @@ void mouse_event(int button, int x, int y) {
handle_input_s(buf);
}
void * handle_incoming(void * garbage) {
void * handle_incoming(void) {
yutani_timer_request(yctx, 0, 0);
while (!exit_application) {
yutani_msg_t * m = yutani_poll(yctx);
if (m) {
switch (m->type) {
case YUTANI_MSG_KEY_EVENT:
{
struct yutani_msg_key_event * ke = (void*)m->data;
int ret = (ke->event.action == KEY_ACTION_DOWN) && (ke->event.key);
key_event(ret, &ke->event);
yutani_msg_t * m = yutani_poll(yctx);
if (m) {
switch (m->type) {
case YUTANI_MSG_KEY_EVENT:
{
struct yutani_msg_key_event * ke = (void*)m->data;
int ret = (ke->event.action == KEY_ACTION_DOWN) && (ke->event.key);
key_event(ret, &ke->event);
}
break;
case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
{
struct yutani_msg_window_focus_change * wf = (void*)m->data;
yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
if (win) {
win->focused = wf->focused;
render_decors();
}
break;
case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
{
struct yutani_msg_window_focus_change * wf = (void*)m->data;
yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
if (win) {
win->focused = wf->focused;
render_decors();
}
}
break;
case YUTANI_MSG_SESSION_END:
{
kill(child_pid, SIGKILL);
exit_application = 1;
}
break;
case YUTANI_MSG_RESIZE_OFFER:
{
struct yutani_msg_window_resize * wr = (void*)m->data;
resize_finish(wr->width, wr->height);
}
break;
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
{
struct yutani_msg_window_mouse_event * me = (void*)m->data;
if (!_no_frame) {
if (decor_handle_event(yctx, m) == DECOR_CLOSE) {
kill(child_pid, SIGKILL);
exit_application = 1;
break;
}
}
if (me->new_x < 0 || me->new_x >= window_width || me->new_y < 0 || me->new_y >= window_height) {
}
break;
case YUTANI_MSG_SESSION_END:
{
kill(child_pid, SIGKILL);
exit_application = 1;
}
break;
case YUTANI_MSG_RESIZE_OFFER:
{
struct yutani_msg_window_resize * wr = (void*)m->data;
resize_finish(wr->width, wr->height);
}
break;
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
{
struct yutani_msg_window_mouse_event * me = (void*)m->data;
if (!_no_frame) {
if (decor_handle_event(yctx, m) == DECOR_CLOSE) {
kill(child_pid, SIGKILL);
exit_application = 1;
break;
}
/* Map Cursor Action */
if (ansi_state->mouse_on) {
int new_x = me->new_x;
int new_y = me->new_y;
if (!_no_frame) {
new_x -= decor_left_width;
new_y -= decor_top_height;
}
/* Convert from coordinate to cell positon */
new_x /= char_width;
new_y /= char_height;
}
if (me->new_x < 0 || me->new_x >= window_width || me->new_y < 0 || me->new_y >= window_height) {
break;
}
/* Map Cursor Action */
if (ansi_state->mouse_on) {
int new_x = me->new_x;
int new_y = me->new_y;
if (!_no_frame) {
new_x -= decor_left_width;
new_y -= decor_top_height;
}
/* Convert from coordinate to cell positon */
new_x /= char_width;
new_y /= char_height;
if (me->buttons & YUTANI_MOUSE_SCROLL_UP) {
mouse_event(32+32, new_x, new_y);
} else if (me->buttons & YUTANI_MOUSE_SCROLL_DOWN) {
mouse_event(32+32+1, new_x, new_y);
}
if (me->buttons & YUTANI_MOUSE_SCROLL_UP) {
mouse_event(32+32, new_x, new_y);
} else if (me->buttons & YUTANI_MOUSE_SCROLL_DOWN) {
mouse_event(32+32+1, new_x, new_y);
}
if (me->buttons != button_state) {
/* Figure out what changed */
if (me->buttons & YUTANI_MOUSE_BUTTON_LEFT && !(button_state & YUTANI_MOUSE_BUTTON_LEFT)) mouse_event(0, new_x, new_y);
if (me->buttons & YUTANI_MOUSE_BUTTON_MIDDLE && !(button_state & YUTANI_MOUSE_BUTTON_MIDDLE)) mouse_event(1, new_x, new_y);
if (me->buttons & YUTANI_MOUSE_BUTTON_RIGHT && !(button_state & YUTANI_MOUSE_BUTTON_RIGHT)) mouse_event(2, new_x, new_y);
if (!(me->buttons & YUTANI_MOUSE_BUTTON_LEFT) && button_state & YUTANI_MOUSE_BUTTON_LEFT) mouse_event(3, new_x, new_y);
if (!(me->buttons & YUTANI_MOUSE_BUTTON_MIDDLE) && button_state & YUTANI_MOUSE_BUTTON_MIDDLE) mouse_event(3, new_x, new_y);
if (!(me->buttons & YUTANI_MOUSE_BUTTON_RIGHT) && button_state & YUTANI_MOUSE_BUTTON_RIGHT) mouse_event(3, new_x, new_y);
last_mouse_x = new_x;
last_mouse_y = new_y;
button_state = me->buttons;
} else if (ansi_state->mouse_on == 2) {
/* Report motion for pressed buttons */
if (last_mouse_x == new_x && last_mouse_y == new_y) break;
if (button_state & YUTANI_MOUSE_BUTTON_LEFT) mouse_event(32, new_x, new_y);
if (button_state & YUTANI_MOUSE_BUTTON_MIDDLE) mouse_event(33, new_x, new_y);
if (button_state & YUTANI_MOUSE_BUTTON_RIGHT) mouse_event(34, new_x, new_y);
last_mouse_x = new_x;
last_mouse_y = new_y;
}
} else {
if (me->buttons & YUTANI_MOUSE_SCROLL_UP) {
scroll_up(5);
} else if (me->buttons & YUTANI_MOUSE_SCROLL_DOWN) {
scroll_down(5);
}
if (me->buttons != button_state) {
/* Figure out what changed */
if (me->buttons & YUTANI_MOUSE_BUTTON_LEFT && !(button_state & YUTANI_MOUSE_BUTTON_LEFT)) mouse_event(0, new_x, new_y);
if (me->buttons & YUTANI_MOUSE_BUTTON_MIDDLE && !(button_state & YUTANI_MOUSE_BUTTON_MIDDLE)) mouse_event(1, new_x, new_y);
if (me->buttons & YUTANI_MOUSE_BUTTON_RIGHT && !(button_state & YUTANI_MOUSE_BUTTON_RIGHT)) mouse_event(2, new_x, new_y);
if (!(me->buttons & YUTANI_MOUSE_BUTTON_LEFT) && button_state & YUTANI_MOUSE_BUTTON_LEFT) mouse_event(3, new_x, new_y);
if (!(me->buttons & YUTANI_MOUSE_BUTTON_MIDDLE) && button_state & YUTANI_MOUSE_BUTTON_MIDDLE) mouse_event(3, new_x, new_y);
if (!(me->buttons & YUTANI_MOUSE_BUTTON_RIGHT) && button_state & YUTANI_MOUSE_BUTTON_RIGHT) mouse_event(3, new_x, new_y);
last_mouse_x = new_x;
last_mouse_y = new_y;
button_state = me->buttons;
} else if (ansi_state->mouse_on == 2) {
/* Report motion for pressed buttons */
if (last_mouse_x == new_x && last_mouse_y == new_y) break;
if (button_state & YUTANI_MOUSE_BUTTON_LEFT) mouse_event(32, new_x, new_y);
if (button_state & YUTANI_MOUSE_BUTTON_MIDDLE) mouse_event(33, new_x, new_y);
if (button_state & YUTANI_MOUSE_BUTTON_RIGHT) mouse_event(34, new_x, new_y);
last_mouse_x = new_x;
last_mouse_y = new_y;
}
} else {
if (me->buttons & YUTANI_MOUSE_SCROLL_UP) {
scroll_up(5);
} else if (me->buttons & YUTANI_MOUSE_SCROLL_DOWN) {
scroll_down(5);
}
}
break;
case YUTANI_MSG_TIMER_TICK:
{
uint64_t ticks = get_ticks();
if (ticks > mouse_ticks + 600000LL) {
mouse_ticks = ticks;
spin_lock(&display_lock);
flip_cursor();
spin_unlock(&display_lock);
}
}
break;
case YUTANI_MSG_TIMER_TICK:
{
uint64_t ticks = get_ticks();
if (ticks > mouse_ticks + 600000LL) {
mouse_ticks = ticks;
spin_lock(&display_lock);
flip_cursor();
spin_unlock(&display_lock);
}
default:
break;
}
free(m);
}
default:
break;
}
free(m);
}
pthread_exit(0);
}
#ifndef syscall_fswait
/* TODO: This isn't in our newlib syscall bindings yet. */
DEFN_SYSCALL2(fswait,59,int,int*);
#endif
int main(int argc, char ** argv) {
_use_freetype = 1;
@ -1546,21 +1549,28 @@ int main(int argc, char ** argv) {
child_pid = f;
pthread_t wait_for_exit_thread;
pthread_create(&wait_for_exit_thread, NULL, wait_for_exit, NULL);
yutani_timer_request(yctx, 0, 0);
pthread_t handle_incoming_thread;
pthread_create(&handle_incoming_thread, NULL, handle_incoming, NULL);
int fds[2] = {fd_master, fileno(yctx->sock)};
unsigned char buf[1024];
while (!exit_application) {
int r = read(fd_master, buf, 1024);
spin_lock(&display_lock);
for (uint32_t i = 0; i < r; ++i) {
ansi_put(ansi_state, buf[i]);
int index = syscall_fswait(2,fds);
check_for_exit();
if (index == 0) {
int r = read(fd_master, buf, 1024);
spin_lock(&display_lock);
for (uint32_t i = 0; i < r; ++i) {
ansi_put(ansi_state, buf[i]);
}
display_flip();
spin_unlock(&display_lock);
} else {
handle_incoming();
}
display_flip();
spin_unlock(&display_lock);
}
}