refactoring native i/o code
parent
00dc2c9464
commit
8321eadefe
|
@ -48,7 +48,7 @@ USE: namespaces
|
||||||
|
|
||||||
( -- str )
|
( -- str )
|
||||||
[
|
[
|
||||||
"in" get read-line-fd-8 dup [ sbuf>str ] when
|
"in" get read-line-fd-8
|
||||||
] "freadln" set
|
] "freadln" set
|
||||||
|
|
||||||
( -- )
|
( -- )
|
||||||
|
|
|
@ -33,8 +33,7 @@ typedef unsigned short CHAR;
|
||||||
/* Memory heap size */
|
/* Memory heap size */
|
||||||
#define DEFAULT_ARENA (32 * 1024 * 1024)
|
#define DEFAULT_ARENA (32 * 1024 * 1024)
|
||||||
|
|
||||||
/* #define PAGE_SIZE 4096 */
|
#define STACK_SIZE 16384
|
||||||
#define STACK_SIZE 8192
|
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
@ -50,7 +49,9 @@ typedef unsigned short CHAR;
|
||||||
#include "complex.h"
|
#include "complex.h"
|
||||||
#include "arithmetic.h"
|
#include "arithmetic.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "relocate.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "sbuf.h"
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
#include "fd.h"
|
#include "fd.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
@ -61,7 +62,5 @@ typedef unsigned short CHAR;
|
||||||
#include "primitives.h"
|
#include "primitives.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
#include "sbuf.h"
|
|
||||||
#include "relocate.h"
|
|
||||||
|
|
||||||
#endif /* __FACTOR_H__ */
|
#endif /* __FACTOR_H__ */
|
||||||
|
|
160
native/fd.c
160
native/fd.c
|
@ -7,9 +7,11 @@ void init_io(void)
|
||||||
env.user[STDERR_ENV] = port(2);
|
env.user[STDERR_ENV] = port(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_step(PORT* port, STRING* buf)
|
int read_step(PORT* port)
|
||||||
{
|
{
|
||||||
int amount = read(port->fd,buf + 1,buf->capacity * 2);
|
int amount = read(port->fd,
|
||||||
|
port->buffer + 1,
|
||||||
|
port->buffer->capacity * 2);
|
||||||
|
|
||||||
port->buf_fill = (amount < 0 ? 0 : amount);
|
port->buf_fill = (amount < 0 ? 0 : amount);
|
||||||
port->buf_pos = 0;
|
port->buf_pos = 0;
|
||||||
|
@ -17,85 +19,101 @@ int read_step(PORT* port, STRING* buf)
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void primitive_read_line_fd_8(void)
|
READLINE_STAT read_line_step(PORT* port)
|
||||||
{
|
{
|
||||||
PORT* port = untag_port(dpeek());
|
|
||||||
|
|
||||||
int amount;
|
int amount;
|
||||||
int i;
|
int i;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
/* finished line, unicode */
|
SBUF* line = port->line;
|
||||||
SBUF* line = sbuf(LINE_SIZE);
|
|
||||||
|
if(port->buf_pos >= port->buf_fill)
|
||||||
|
{
|
||||||
|
amount = read_step(port);
|
||||||
|
|
||||||
|
if(amount < 0)
|
||||||
|
io_error(__FUNCTION__);
|
||||||
|
else if(amount == 0)
|
||||||
|
return READLINE_EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = port->buf_pos; i < port->buf_fill; i++)
|
||||||
|
{
|
||||||
|
ch = bget((CELL)port->buffer + sizeof(STRING) + i);
|
||||||
|
if(ch == '\n')
|
||||||
|
{
|
||||||
|
port->buf_pos = i + 1;
|
||||||
|
return READLINE_EOL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
set_sbuf_nth(line,line->top,ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
port->buf_pos = port->buf_fill;
|
||||||
|
|
||||||
|
/* We've reached the end of the above loop, without seeing a newline
|
||||||
|
or EOF, so read again */
|
||||||
|
return READLINE_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void primitive_read_line_fd_8(void)
|
||||||
|
{
|
||||||
|
PORT* port = untag_port(dpeek());
|
||||||
|
SBUF* line;
|
||||||
|
READLINE_STAT state;
|
||||||
|
|
||||||
init_buffer(port,B_READ);
|
init_buffer(port,B_READ);
|
||||||
|
if(port->line == NULL)
|
||||||
|
port->line = sbuf(LINE_SIZE);
|
||||||
|
else
|
||||||
|
port->line->top = 0;
|
||||||
|
line = port->line;
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if(port->buf_pos >= port->buf_fill)
|
state = read_line_step(port);
|
||||||
|
if(state != READLINE_AGAIN)
|
||||||
{
|
{
|
||||||
amount = read_step(port,port->buffer);
|
if(state == READLINE_EOF && line->top == 0)
|
||||||
|
|
||||||
if(amount < 0)
|
|
||||||
io_error(__FUNCTION__);
|
|
||||||
|
|
||||||
if(amount == 0)
|
|
||||||
{
|
{
|
||||||
if(line->top == 0)
|
/* didn't read anything before EOF */
|
||||||
{
|
drepl(F);
|
||||||
/* didn't read anything before EOF */
|
|
||||||
drepl(F);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
drepl(tag_object(line));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i = port->buf_pos; i < port->buf_fill; i++)
|
|
||||||
{
|
|
||||||
ch = bget((CELL)port->buffer + sizeof(STRING) + i);
|
|
||||||
if(ch == '\n')
|
|
||||||
{
|
|
||||||
port->buf_pos = i + 1;
|
|
||||||
drepl(tag_object(line));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
set_sbuf_nth(line,line->top,ch);
|
drepl(tag_object(sbuf_to_string(line)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We've reached the end of the above loop */
|
|
||||||
port->buf_pos = port->buf_fill;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_step(PORT* port)
|
||||||
|
{
|
||||||
|
char* chars = (char*)port->buffer + sizeof(STRING);
|
||||||
|
|
||||||
|
FIXNUM amount = write(port->fd,chars + port->buf_pos,
|
||||||
|
port->buf_fill - port->buf_pos);
|
||||||
|
|
||||||
|
if(amount < 0)
|
||||||
|
io_error(__FUNCTION__);
|
||||||
|
|
||||||
|
port->buf_pos += amount;
|
||||||
|
}
|
||||||
|
|
||||||
/* keep writing to the stream until everything is written */
|
/* keep writing to the stream until everything is written */
|
||||||
void write_fully(PORT* port, char* str, CELL len)
|
|
||||||
{
|
|
||||||
FIXNUM amount, written = 0, remains;
|
|
||||||
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
remains = len - written;
|
|
||||||
|
|
||||||
if(remains == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
amount = write(port->fd,str + written,remains);
|
|
||||||
if(amount < 0)
|
|
||||||
io_error(__FUNCTION__);
|
|
||||||
|
|
||||||
written += amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush_buffer(PORT* port)
|
void flush_buffer(PORT* port)
|
||||||
{
|
{
|
||||||
if(port->buf_mode != B_WRITE || port->buf_fill == 0)
|
if(port->buf_mode != B_WRITE || port->buf_fill == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
write_fully(port,(char*)port->buffer + sizeof(STRING),port->buf_fill);
|
for(;;)
|
||||||
|
{
|
||||||
|
if(port->buf_fill == port->buf_pos)
|
||||||
|
break;
|
||||||
|
|
||||||
|
write_step(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
port->buf_pos = 0;
|
||||||
port->buf_fill = 0;
|
port->buf_fill = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,25 +140,23 @@ void write_fd_string_8(PORT* port, STRING* str)
|
||||||
/* Is the string longer than the buffer? */
|
/* Is the string longer than the buffer? */
|
||||||
if(str->capacity > port->buffer->capacity * CHARS)
|
if(str->capacity > port->buffer->capacity * CHARS)
|
||||||
{
|
{
|
||||||
/* Just write it immediately */
|
|
||||||
flush_buffer(port);
|
flush_buffer(port);
|
||||||
write_fully(port,c_str,str->capacity);
|
|
||||||
|
/* Increase the buffer to fit the string */
|
||||||
|
port->buffer = allot_string(str->capacity / CHARS + 1);
|
||||||
}
|
}
|
||||||
else
|
/* Is there enough room in the buffer? If not, flush */
|
||||||
|
if(port->buf_fill + str->capacity
|
||||||
|
> port->buffer->capacity * CHARS)
|
||||||
{
|
{
|
||||||
/* Is there enough room in the buffer? If not, flush */
|
flush_buffer(port);
|
||||||
if(port->buf_fill + str->capacity
|
|
||||||
> port->buffer->capacity * CHARS)
|
|
||||||
{
|
|
||||||
flush_buffer(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append string to buffer */
|
|
||||||
memcpy((void*)((CELL)port->buffer + sizeof(STRING)
|
|
||||||
+ port->buf_fill),c_str,str->capacity);
|
|
||||||
|
|
||||||
port->buf_fill += str->capacity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Append string to buffer */
|
||||||
|
memcpy((void*)((CELL)port->buffer + sizeof(STRING)
|
||||||
|
+ port->buf_fill),c_str,str->capacity);
|
||||||
|
|
||||||
|
port->buf_fill += str->capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
void primitive_write_fd_8(void)
|
void primitive_write_fd_8(void)
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
#define LINE_SIZE 80
|
#define LINE_SIZE 80
|
||||||
#define BUF_SIZE (32 * 1024)
|
#define BUF_SIZE (32 * 1024)
|
||||||
|
|
||||||
int read_step(PORT* port, STRING* buf);
|
int read_step(PORT* port);
|
||||||
|
|
||||||
|
/* read_line_step() return values */
|
||||||
|
typedef enum { READLINE_AGAIN, READLINE_EOL, READLINE_EOF } READLINE_STAT;
|
||||||
|
|
||||||
|
READLINE_STAT read_line_step(PORT* port);
|
||||||
void flush_buffer(PORT* port);
|
void flush_buffer(PORT* port);
|
||||||
void write_fully(PORT* port, char* str, CELL len);
|
|
||||||
void init_io(void);
|
void init_io(void);
|
||||||
void primitive_read_line_fd_8(void);
|
void primitive_read_line_fd_8(void);
|
||||||
void write_fd_char_8(PORT* port, FIXNUM ch);
|
void write_fd_char_8(PORT* port, FIXNUM ch);
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
#include "factor.h"
|
#include "factor.h"
|
||||||
|
|
||||||
/* Stacks are malloc()'ed, then we set up guard pages to check for
|
/* set up guard pages to check for under/overflow.
|
||||||
under/overflow. size must be a multiple of the page size */
|
size must be a multiple of the page size */
|
||||||
void* alloc_guarded(CELL size)
|
void* alloc_guarded(CELL size)
|
||||||
{
|
{
|
||||||
char* array = mmap((void*)0,PAGE_SIZE + size + PAGE_SIZE,
|
int pagesize = getpagesize();
|
||||||
PROT_READ | PROT_WRITE,MAP_ANON,-1,0);
|
|
||||||
|
|
||||||
if(mprotect(array,PAGE_SIZE,PROT_NONE) == -1)
|
char* array = mmap((void*)0,pagesize + size + pagesize,
|
||||||
|
PROT_READ | PROT_WRITE,MAP_ANON | MAP_PRIVATE,-1,0);
|
||||||
|
|
||||||
|
if(mprotect(array,pagesize,PROT_NONE) == -1)
|
||||||
fatal_error("Cannot allocate low guard page",(CELL)array);
|
fatal_error("Cannot allocate low guard page",(CELL)array);
|
||||||
|
|
||||||
if(mprotect(array + PAGE_SIZE + size,PAGE_SIZE,PROT_NONE) == -1)
|
if(mprotect(array + pagesize + size,pagesize,PROT_NONE) == -1)
|
||||||
fatal_error("Cannot allocate high guard page",(CELL)array);
|
fatal_error("Cannot allocate high guard page",(CELL)array);
|
||||||
|
|
||||||
/* return bottom of actual array */
|
/* return bottom of actual array */
|
||||||
return array + PAGE_SIZE;
|
return array + pagesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZONE* zalloc(CELL size)
|
ZONE* zalloc(CELL size)
|
||||||
|
|
|
@ -15,7 +15,8 @@ CELL port(CELL fd)
|
||||||
{
|
{
|
||||||
PORT* port = allot_object(PORT_TYPE,sizeof(PORT));
|
PORT* port = allot_object(PORT_TYPE,sizeof(PORT));
|
||||||
port->fd = fd;
|
port->fd = fd;
|
||||||
port->buffer = (STRING*)0;
|
port->buffer = NULL;
|
||||||
|
port->line = NULL;
|
||||||
port->buf_mode = B_NONE;
|
port->buf_mode = B_NONE;
|
||||||
port->buf_fill = 0;
|
port->buf_fill = 0;
|
||||||
port->buf_pos = 0;
|
port->buf_pos = 0;
|
||||||
|
@ -43,8 +44,10 @@ void fixup_port(PORT* port)
|
||||||
{
|
{
|
||||||
port->fd = -1;
|
port->fd = -1;
|
||||||
if(port->buffer != 0)
|
if(port->buffer != 0)
|
||||||
|
port->buffer = fixup_untagged_string(port->buffer);
|
||||||
|
if(port->line != 0)
|
||||||
{
|
{
|
||||||
port->buffer = (STRING*)((CELL)port->buffer
|
port->line = (SBUF*)((CELL)port->line
|
||||||
+ (active->base - relocation_base));
|
+ (active->base - relocation_base));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,8 +55,10 @@ void fixup_port(PORT* port)
|
||||||
void collect_port(PORT* port)
|
void collect_port(PORT* port)
|
||||||
{
|
{
|
||||||
if(port->buffer != 0)
|
if(port->buffer != 0)
|
||||||
|
port->buffer = copy_untagged_string(port->buffer);
|
||||||
|
if(port->line != 0)
|
||||||
{
|
{
|
||||||
port->buffer = copy_untagged_object(
|
port->line = (SBUF*)copy_untagged_object(
|
||||||
port->buffer,SSIZE(port->buffer));
|
port->line,sizeof(SBUF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
|
/* Buffer mode */
|
||||||
|
typedef enum { B_READ, B_WRITE, B_NONE } B_MODE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CELL header;
|
CELL header;
|
||||||
FIXNUM fd;
|
FIXNUM fd;
|
||||||
STRING* buffer;
|
STRING* buffer;
|
||||||
CELL buf_mode;
|
/* partial line used by read_line_fd */
|
||||||
|
SBUF* line;
|
||||||
|
/* one of B_READ, B_WRITE or B_NONE */
|
||||||
|
B_MODE buf_mode;
|
||||||
|
/* top of buffer */
|
||||||
CELL buf_fill;
|
CELL buf_fill;
|
||||||
|
/* current read/write position */
|
||||||
CELL buf_pos;
|
CELL buf_pos;
|
||||||
} PORT;
|
} PORT;
|
||||||
|
|
||||||
/* Buffer mode */
|
|
||||||
#define B_READ 0
|
|
||||||
#define B_WRITE 1
|
|
||||||
#define B_NONE 2
|
|
||||||
|
|
||||||
PORT* untag_port(CELL tagged);
|
PORT* untag_port(CELL tagged);
|
||||||
CELL port(CELL fd);
|
CELL port(CELL fd);
|
||||||
void init_buffer(PORT* port, int mode);
|
void init_buffer(PORT* port, int mode);
|
||||||
|
|
|
@ -134,11 +134,10 @@ void primitive_sbuf_eq(void)
|
||||||
|
|
||||||
void fixup_sbuf(SBUF* sbuf)
|
void fixup_sbuf(SBUF* sbuf)
|
||||||
{
|
{
|
||||||
sbuf->string = (STRING*)((CELL)sbuf->string
|
sbuf->string = fixup_untagged_string(sbuf->string);
|
||||||
+ (active->base - relocation_base));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_sbuf(SBUF* sbuf)
|
void collect_sbuf(SBUF* sbuf)
|
||||||
{
|
{
|
||||||
sbuf->string = copy_untagged_object(sbuf->string,SSIZE(sbuf->string));
|
sbuf->string = copy_untagged_string(sbuf->string);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,3 +46,13 @@ void primitive_string_eq(void);
|
||||||
void primitive_string_hashcode(void);
|
void primitive_string_hashcode(void);
|
||||||
void primitive_index_of(void);
|
void primitive_index_of(void);
|
||||||
void primitive_substring(void);
|
void primitive_substring(void);
|
||||||
|
|
||||||
|
INLINE STRING* fixup_untagged_string(STRING* str)
|
||||||
|
{
|
||||||
|
return (STRING*)((CELL)str + (active->base - relocation_base));
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE STRING* copy_untagged_string(STRING* str)
|
||||||
|
{
|
||||||
|
return copy_untagged_object(str,SSIZE(str));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue