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 )
[
"in" get read-line-fd-8 dup [ sbuf>str ] when
"in" get read-line-fd-8
] "freadln" set
( -- )

View File

@ -33,8 +33,7 @@ typedef unsigned short CHAR;
/* Memory heap size */
#define DEFAULT_ARENA (32 * 1024 * 1024)
/* #define PAGE_SIZE 4096 */
#define STACK_SIZE 8192
#define STACK_SIZE 16384
#include "error.h"
#include "memory.h"
@ -50,7 +49,9 @@ typedef unsigned short CHAR;
#include "complex.h"
#include "arithmetic.h"
#include "misc.h"
#include "relocate.h"
#include "string.h"
#include "sbuf.h"
#include "port.h"
#include "fd.h"
#include "file.h"
@ -61,7 +62,5 @@ typedef unsigned short CHAR;
#include "primitives.h"
#include "vector.h"
#include "stack.h"
#include "sbuf.h"
#include "relocate.h"
#endif /* __FACTOR_H__ */

View File

@ -7,9 +7,11 @@ void init_io(void)
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_pos = 0;
@ -17,85 +19,101 @@ int read_step(PORT* port, STRING* buf)
return amount;
}
void primitive_read_line_fd_8(void)
READLINE_STAT read_line_step(PORT* port)
{
PORT* port = untag_port(dpeek());
int amount;
int i;
int ch;
/* finished line, unicode */
SBUF* line = sbuf(LINE_SIZE);
SBUF* line = port->line;
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);
if(port->line == NULL)
port->line = sbuf(LINE_SIZE);
else
port->line->top = 0;
line = port->line;
for(;;)
{
if(port->buf_pos >= port->buf_fill)
state = read_line_step(port);
if(state != READLINE_AGAIN)
{
amount = read_step(port,port->buffer);
if(amount < 0)
io_error(__FUNCTION__);
if(amount == 0)
if(state == READLINE_EOF && line->top == 0)
{
if(line->top == 0)
{
/* 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;
/* didn't read anything before EOF */
drepl(F);
}
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 */
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)
{
if(port->buf_mode != B_WRITE || port->buf_fill == 0)
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;
}
@ -122,25 +140,23 @@ void write_fd_string_8(PORT* port, STRING* str)
/* Is the string longer than the buffer? */
if(str->capacity > port->buffer->capacity * CHARS)
{
/* Just write it immediately */
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 */
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;
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;
}
void primitive_write_fd_8(void)

View File

@ -1,9 +1,13 @@
#define LINE_SIZE 80
#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 write_fully(PORT* port, char* str, CELL len);
void init_io(void);
void primitive_read_line_fd_8(void);
void write_fd_char_8(PORT* port, FIXNUM ch);

View File

@ -1,20 +1,22 @@
#include "factor.h"
/* Stacks are malloc()'ed, then we set up guard pages to check for
under/overflow. size must be a multiple of the page size */
/* set up guard pages to check for under/overflow.
size must be a multiple of the page size */
void* alloc_guarded(CELL size)
{
char* array = mmap((void*)0,PAGE_SIZE + size + PAGE_SIZE,
PROT_READ | PROT_WRITE,MAP_ANON,-1,0);
int pagesize = getpagesize();
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);
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);
/* return bottom of actual array */
return array + PAGE_SIZE;
return array + pagesize;
}
ZONE* zalloc(CELL size)

View File

@ -15,7 +15,8 @@ CELL port(CELL fd)
{
PORT* port = allot_object(PORT_TYPE,sizeof(PORT));
port->fd = fd;
port->buffer = (STRING*)0;
port->buffer = NULL;
port->line = NULL;
port->buf_mode = B_NONE;
port->buf_fill = 0;
port->buf_pos = 0;
@ -43,8 +44,10 @@ void fixup_port(PORT* port)
{
port->fd = -1;
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));
}
}
@ -52,8 +55,10 @@ void fixup_port(PORT* port)
void collect_port(PORT* port)
{
if(port->buffer != 0)
port->buffer = copy_untagged_string(port->buffer);
if(port->line != 0)
{
port->buffer = copy_untagged_object(
port->buffer,SSIZE(port->buffer));
port->line = (SBUF*)copy_untagged_object(
port->line,sizeof(SBUF));
}
}

View File

@ -1,17 +1,20 @@
/* Buffer mode */
typedef enum { B_READ, B_WRITE, B_NONE } B_MODE;
typedef struct {
CELL header;
FIXNUM fd;
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;
/* current read/write position */
CELL buf_pos;
} PORT;
/* Buffer mode */
#define B_READ 0
#define B_WRITE 1
#define B_NONE 2
PORT* untag_port(CELL tagged);
CELL port(CELL fd);
void init_buffer(PORT* port, int mode);

View File

@ -134,11 +134,10 @@ void primitive_sbuf_eq(void)
void fixup_sbuf(SBUF* sbuf)
{
sbuf->string = (STRING*)((CELL)sbuf->string
+ (active->base - relocation_base));
sbuf->string = fixup_untagged_string(sbuf->string);
}
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_index_of(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));
}