more I/O work
parent
8321eadefe
commit
b9ad4405b4
|
@ -14,6 +14,7 @@ int main(int argc, char** argv)
|
||||||
load_image(argv[1]);
|
load_image(argv[1]);
|
||||||
init_stacks();
|
init_stacks();
|
||||||
init_io();
|
init_io();
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <poll.h>
|
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
63
native/fd.c
63
native/fd.c
|
@ -3,15 +3,40 @@
|
||||||
void init_io(void)
|
void init_io(void)
|
||||||
{
|
{
|
||||||
env.user[STDIN_ENV] = port(0);
|
env.user[STDIN_ENV] = port(0);
|
||||||
|
set_nonblocking(0);
|
||||||
env.user[STDOUT_ENV] = port(1);
|
env.user[STDOUT_ENV] = port(1);
|
||||||
|
set_nonblocking(1);
|
||||||
env.user[STDERR_ENV] = port(2);
|
env.user[STDERR_ENV] = port(2);
|
||||||
|
set_nonblocking(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_step(PORT* port)
|
int read_step(PORT* port)
|
||||||
{
|
{
|
||||||
int amount = read(port->fd,
|
FIXNUM amount = -1;
|
||||||
port->buffer + 1,
|
|
||||||
port->buffer->capacity * 2);
|
add_read_io_task(port,F);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
amount = read(port->fd,
|
||||||
|
port->buffer + 1,
|
||||||
|
port->buffer->capacity * 2);
|
||||||
|
|
||||||
|
if(amount == -1)
|
||||||
|
{
|
||||||
|
if(errno != EAGAIN)
|
||||||
|
{
|
||||||
|
remove_read_io_task(port);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
iomux();
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_read_io_task(port);
|
||||||
|
|
||||||
port->buf_fill = (amount < 0 ? 0 : amount);
|
port->buf_fill = (amount < 0 ? 0 : amount);
|
||||||
port->buf_pos = 0;
|
port->buf_pos = 0;
|
||||||
|
@ -90,8 +115,30 @@ void write_step(PORT* port)
|
||||||
{
|
{
|
||||||
char* chars = (char*)port->buffer + sizeof(STRING);
|
char* chars = (char*)port->buffer + sizeof(STRING);
|
||||||
|
|
||||||
FIXNUM amount = write(port->fd,chars + port->buf_pos,
|
FIXNUM amount;
|
||||||
port->buf_fill - port->buf_pos);
|
|
||||||
|
add_write_io_task(port,F);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
amount = write(port->fd,chars + port->buf_pos,
|
||||||
|
port->buf_fill - port->buf_pos);
|
||||||
|
|
||||||
|
if(amount == -1)
|
||||||
|
{
|
||||||
|
if(errno != EAGAIN)
|
||||||
|
{
|
||||||
|
remove_write_io_task(port);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
iomux();
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_write_io_task(port);
|
||||||
|
|
||||||
if(amount < 0)
|
if(amount < 0)
|
||||||
io_error(__FUNCTION__);
|
io_error(__FUNCTION__);
|
||||||
|
@ -193,3 +240,9 @@ void primitive_close_fd(void)
|
||||||
flush_buffer(port);
|
flush_buffer(port);
|
||||||
close(port->fd);
|
close(port->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_nonblocking(int fd)
|
||||||
|
{
|
||||||
|
if(fcntl(fd,F_SETFL,O_NONBLOCK,1) == -1)
|
||||||
|
io_error(__FUNCTION__);
|
||||||
|
}
|
||||||
|
|
|
@ -15,3 +15,4 @@ void write_fd_string_8(PORT* port, STRING* str);
|
||||||
void primitive_write_fd_8(void);
|
void primitive_write_fd_8(void);
|
||||||
void primitive_flush_fd(void);
|
void primitive_flush_fd(void);
|
||||||
void primitive_close_fd(void);
|
void primitive_close_fd(void);
|
||||||
|
void set_nonblocking(int fd);
|
||||||
|
|
|
@ -9,13 +9,13 @@ void primitive_open_file(void)
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if(read && write)
|
if(read && write)
|
||||||
mode = O_RDWR | O_CREAT;
|
mode = O_RDWR | O_CREAT | O_NONBLOCK;
|
||||||
else if(read)
|
else if(read)
|
||||||
mode = O_RDONLY;
|
mode = O_RDONLY | O_NONBLOCK;
|
||||||
else if(write)
|
else if(write)
|
||||||
mode = O_WRONLY | O_CREAT | O_TRUNC;
|
mode = O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK;
|
||||||
else
|
else
|
||||||
mode = 0;
|
mode = O_NONBLOCK;
|
||||||
|
|
||||||
fd = open(path,mode);
|
fd = open(path,mode);
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
|
|
108
native/iomux.c
108
native/iomux.c
|
@ -1,31 +1,111 @@
|
||||||
#include "factor.h"
|
#include "factor.h"
|
||||||
|
|
||||||
|
void init_io_tasks(fd_set* fdset, IO_TASK* io_tasks)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
FD_ZERO(fdset);
|
||||||
|
for(i = 0; i < FD_SETSIZE; i++)
|
||||||
|
{
|
||||||
|
read_io_tasks[i].port = NULL;
|
||||||
|
read_io_tasks[i].callback = F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init_iomux(void)
|
void init_iomux(void)
|
||||||
{
|
{
|
||||||
io_task_count = 0;
|
read_fd_count = 0;
|
||||||
|
init_io_tasks(&read_fd_set,read_io_tasks);
|
||||||
|
|
||||||
|
write_fd_count = 0;
|
||||||
|
init_io_tasks(&write_fd_set,write_io_tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_io_task(int fd, int events, CELL callback)
|
void add_io_task(
|
||||||
|
PORT* port,
|
||||||
|
CELL callback,
|
||||||
|
fd_set* fdset,
|
||||||
|
IO_TASK* io_tasks,
|
||||||
|
int* fd_count)
|
||||||
{
|
{
|
||||||
|
int fds = *fd_count;
|
||||||
|
|
||||||
/* Look for an empty slot first */
|
/* Look for an empty slot first */
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < io_task_count; i++)
|
for(i = 0; i < fds; i++)
|
||||||
{
|
{
|
||||||
if(io_tasks[i].fd == -1)
|
if(io_tasks[i].port == NULL)
|
||||||
{
|
{
|
||||||
io_tasks[i].fd = fd;
|
FD_SET(port->fd,fdset);
|
||||||
io_tasks[i].events = events;
|
io_tasks[i].port = port;
|
||||||
io_callbacks[i] = callback;
|
io_tasks[i].callback = callback;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add to the end */
|
/* add at end */
|
||||||
if(io_task_count == MAX_IO_TASKS)
|
if(fds == FD_SETSIZE)
|
||||||
critical_error("Too many I/O tasks",io_task_count);
|
critical_error("Too many I/O tasks",*fd_count);
|
||||||
|
|
||||||
io_tasks[io_task_count].fd = fd;
|
FD_SET(port->fd,fdset);
|
||||||
io_tasks[io_task_count].events = events;
|
io_tasks[fds].port = port;
|
||||||
io_callbacks[io_task_count] = callback;
|
io_tasks[fds].callback = callback;
|
||||||
io_task_count++;
|
*fd_count = fds + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_read_io_task(PORT* port, CELL callback)
|
||||||
|
{
|
||||||
|
add_io_task(port,callback,
|
||||||
|
&read_fd_set,read_io_tasks,
|
||||||
|
&read_fd_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_write_io_task(PORT* port, CELL callback)
|
||||||
|
{
|
||||||
|
add_io_task(port,callback,
|
||||||
|
&write_fd_set,write_io_tasks,
|
||||||
|
&write_fd_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_io_task(
|
||||||
|
PORT* port,
|
||||||
|
fd_set* fdset,
|
||||||
|
IO_TASK* io_tasks,
|
||||||
|
int* fd_count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int fds = *fd_count;
|
||||||
|
|
||||||
|
for(i = 0; i < fds; i++)
|
||||||
|
{
|
||||||
|
if(io_tasks[i].port == port)
|
||||||
|
{
|
||||||
|
FD_CLR(port->fd,fdset);
|
||||||
|
io_tasks[i].port = NULL;
|
||||||
|
io_tasks[i].callback = F;
|
||||||
|
if(i == fds - 1)
|
||||||
|
*fd_count = fds - 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_read_io_task(PORT* port)
|
||||||
|
{
|
||||||
|
remove_io_task(port,&read_fd_set,read_io_tasks,&read_fd_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_write_io_task(PORT* port)
|
||||||
|
{
|
||||||
|
remove_io_task(port,&write_fd_set,write_io_tasks,&write_fd_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for I/O and return a callback. */
|
||||||
|
CELL iomux(void)
|
||||||
|
{
|
||||||
|
int nfds = select(read_fd_count > write_fd_count
|
||||||
|
? read_fd_count : write_fd_count,
|
||||||
|
&read_fd_set,&write_fd_set,NULL,NULL);
|
||||||
|
|
||||||
|
return F;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,31 @@
|
||||||
#define MAX_IO_TASKS 256
|
typedef struct {
|
||||||
struct pollfd io_tasks[MAX_IO_TASKS];
|
PORT* port;
|
||||||
CELL io_callbacks[MAX_IO_TASKS];
|
CELL callback;
|
||||||
unsigned int io_task_count;
|
} IO_TASK;
|
||||||
|
|
||||||
|
fd_set read_fd_set;
|
||||||
|
IO_TASK read_io_tasks[FD_SETSIZE];
|
||||||
|
int read_fd_count;
|
||||||
|
|
||||||
|
fd_set write_fd_set;
|
||||||
|
IO_TASK write_io_tasks[FD_SETSIZE];
|
||||||
|
int write_fd_count;
|
||||||
|
|
||||||
|
void init_io_tasks(fd_set* fd_set, IO_TASK* io_tasks);
|
||||||
void init_iomux(void);
|
void init_iomux(void);
|
||||||
void add_io_task(int fd, int events, CELL callback);
|
void add_io_task(
|
||||||
|
PORT* port,
|
||||||
|
CELL callback,
|
||||||
|
fd_set* fd_set,
|
||||||
|
IO_TASK* io_tasks,
|
||||||
|
int* fd_count);
|
||||||
|
void add_read_io_task(PORT* port, CELL callback);
|
||||||
|
void add_write_io_task(PORT* port, CELL callback);
|
||||||
|
void remove_io_task(
|
||||||
|
PORT* port,
|
||||||
|
fd_set* fdset,
|
||||||
|
IO_TASK* io_tasks,
|
||||||
|
int* fd_count);
|
||||||
|
void remove_read_io_task(PORT* port);
|
||||||
|
void remove_write_io_task(PORT* port);
|
||||||
|
CELL iomux(void);
|
||||||
|
|
|
@ -52,6 +52,8 @@ int accept_connection(int sock)
|
||||||
if(new < 0)
|
if(new < 0)
|
||||||
io_error(__FUNCTION__);
|
io_error(__FUNCTION__);
|
||||||
|
|
||||||
|
set_nonblocking(new);
|
||||||
|
|
||||||
printf("Connection from host %s, port %hd.\n",
|
printf("Connection from host %s, port %hd.\n",
|
||||||
inet_ntoa(clientname.sin_addr),
|
inet_ntoa(clientname.sin_addr),
|
||||||
ntohs(clientname.sin_port));
|
ntohs(clientname.sin_port));
|
||||||
|
|
Loading…
Reference in New Issue