refactoring native i/o code

cvs
Slava Pestov 2004-08-13 03:40:28 +00:00
parent 00dc2c9464
commit 8321eadefe
9 changed files with 137 additions and 99 deletions

View File

@ -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
( -- ) ( -- )

View File

@ -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__ */

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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));
} }
} }

View File

@ -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);

View File

@ -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);
} }

View File

@ -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));
}