mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-18 21:29:18 +02:00
Issue #270 - Working through a solution
This commit is contained in:
parent
386e208eb8
commit
40c73203ce
3 changed files with 75 additions and 42 deletions
25
gc.c
25
gc.c
|
@ -2815,17 +2815,33 @@ void gc_mutator_thread_blocked(gc_thread_data * thd, object cont)
|
|||
|
||||
void Cyc_apply_from_buf(void *data, int argc, object prim, object * buf);
|
||||
|
||||
void gc_recopy_obj(object obj, gc_thread_data *thd)
|
||||
{
|
||||
// Temporarily change obj type so we can copy it
|
||||
object fwd = forward(obj);
|
||||
tag_type tag = type_of(fwd);
|
||||
type_of(obj) = tag;
|
||||
|
||||
fprintf(stderr, "\n!!! Recopying object %p with tag %d !!!\n\n", obj, tag);
|
||||
// Copy it again
|
||||
gc_copy_obj(fwd, obj, thd);
|
||||
// Restore forwarding pointer tag
|
||||
type_of(obj) = forward_tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called explicitly from a mutator thread to let the collector know
|
||||
* that it has finished blocking.
|
||||
* @param thd Mutator's thread data
|
||||
* @param result Data returned by the blocking function
|
||||
* @param maybe_copied An object used by the mutator while blocked that may
|
||||
* have been copied to the heap by the collector.
|
||||
*
|
||||
* In addition, if the collector cooperated on behalf of the mutator while
|
||||
* it was blocking, the mutator will move any remaining stack objects to
|
||||
* the heap and longjmp.
|
||||
*/
|
||||
void gc_mutator_thread_runnable(gc_thread_data * thd, object result)
|
||||
void gc_mutator_thread_runnable(gc_thread_data * thd, object result, object maybe_copied)
|
||||
{
|
||||
char stack_limit;
|
||||
// Transition from blocked back to runnable using CAS.
|
||||
|
@ -2845,6 +2861,13 @@ void gc_mutator_thread_runnable(gc_thread_data * thd, object result)
|
|||
// Setup value to send to continuation
|
||||
thd->gc_args[0] = result;
|
||||
thd->gc_num_args = 1;
|
||||
// Check if obj was copied while we slept
|
||||
if (maybe_copied &&
|
||||
is_object_type(maybe_copied) &&
|
||||
gc_is_stack_obj(thd, maybe_copied) &&
|
||||
type_of(maybe_copied) == forward_tag) {
|
||||
gc_recopy_obj(maybe_copied, thd);
|
||||
}
|
||||
// Move any remaining stack objects (should only be the result?) to heap
|
||||
gc_minor(thd, &stack_limit, thd->stack_start, thd->gc_cont, thd->gc_args,
|
||||
thd->gc_num_args);
|
||||
|
|
|
@ -398,11 +398,20 @@ void gc_post_handshake(gc_status_type s);
|
|||
void gc_wait_handshake();
|
||||
void gc_start_collector();
|
||||
void gc_mutator_thread_blocked(gc_thread_data * thd, object cont);
|
||||
void gc_mutator_thread_runnable(gc_thread_data * thd, object result);
|
||||
void gc_mutator_thread_runnable(gc_thread_data * thd, object result, object maybe_copied);
|
||||
#define set_thread_blocked(d, c) \
|
||||
gc_mutator_thread_blocked(((gc_thread_data *)d), (c))
|
||||
/**
|
||||
* @brief Return from a blocked thread
|
||||
*/
|
||||
#define return_thread_runnable(d, r) \
|
||||
gc_mutator_thread_runnable(((gc_thread_data *)d), (r))
|
||||
gc_mutator_thread_runnable(((gc_thread_data *)d), (r), NULL)
|
||||
/**
|
||||
* @brief Return from a blocked thread with an object that may have been copied.
|
||||
* If the object was copied we need to check and may need to copy it again.
|
||||
*/
|
||||
#define return_thread_runnable_with_obj(d, r, maybe_copied) \
|
||||
gc_mutator_thread_runnable(((gc_thread_data *)d), (r), maybe_copied)
|
||||
/*
|
||||
//#define do_with_blocked_thread(data, cont, result, body) \
|
||||
// set_thread_blocked((data), (cont)); \
|
||||
|
@ -952,6 +961,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
gc_header_type hdr;
|
||||
tag_type tag;
|
||||
void *unused; // Protect against forwarding pointer, ideally would not be needed.
|
||||
FILE *fp;
|
||||
int mode;
|
||||
unsigned char flags;
|
||||
|
|
78
runtime.c
78
runtime.c
|
@ -6233,7 +6233,7 @@ void _read_error(void *data, port_type *p, const char *msg)
|
|||
vec.num_elements = 1;
|
||||
vec.elements = (object *) alloca(sizeof(object) * vec.num_elements);
|
||||
vec.elements[0] = &str;
|
||||
return_thread_runnable(data, &vec);
|
||||
return_thread_runnable_with_obj(data, &vec, p);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6464,7 +6464,7 @@ void _read_string(void *data, object cont, port_type *p)
|
|||
p->tok_end = 0; // Reset for next atom
|
||||
{
|
||||
make_utf8_string(data, str, p->tok_buf);
|
||||
return_thread_runnable(data, &str);
|
||||
return_thread_runnable_with_obj(data, &str, p);
|
||||
}
|
||||
} else if (c == '\\') {
|
||||
escaped = 1;
|
||||
|
@ -6569,7 +6569,7 @@ void _read_literal_identifier(void *data, port_type *p)
|
|||
p->tok_end = 0; // Reset for next atom
|
||||
{
|
||||
object sym = find_or_add_symbol(p->tok_buf);
|
||||
return_thread_runnable(data, sym);
|
||||
return_thread_runnable_with_obj(data, sym, p);
|
||||
}
|
||||
} else if (c == '\\') {
|
||||
escaped = 1;
|
||||
|
@ -6594,29 +6594,29 @@ void _read_return_character(void *data, port_type *p)
|
|||
p->tok_end = 0; // Reset for next atom
|
||||
if (strlen(p->tok_buf) == 1) {
|
||||
// ASCII char, consider merging with below?
|
||||
return_thread_runnable(data, obj_char2obj(p->tok_buf[0]));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj(p->tok_buf[0]), p);
|
||||
} else if(strncmp(p->tok_buf, "alarm", 5) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj('\a'));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj('\a'), p);
|
||||
} else if(strncmp(p->tok_buf, "backspace", 9) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj('\b'));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj('\b'), p);
|
||||
} else if(strncmp(p->tok_buf, "delete", 6) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj(127));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj(127), p);
|
||||
} else if(strncmp(p->tok_buf, "escape", 6) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj(27));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj(27), p);
|
||||
} else if(strncmp(p->tok_buf, "newline", 7) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj('\n'));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj('\n'), p);
|
||||
} else if(strncmp(p->tok_buf, "null", 4) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj('\0'));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj('\0'), p);
|
||||
} else if(strncmp(p->tok_buf, "return", 6) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj('\r'));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj('\r'), p);
|
||||
} else if(strncmp(p->tok_buf, "space", 5) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj(' '));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj(' '), p);
|
||||
} else if(strncmp(p->tok_buf, "tab", 3) == 0) {
|
||||
return_thread_runnable(data, obj_char2obj('\t'));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj('\t'), p);
|
||||
} else if(strlen(p->tok_buf) > 1 && p->tok_buf[0] == 'x') {
|
||||
const char *buf = p->tok_buf + 1;
|
||||
char_type result = strtol(buf, NULL, 16);
|
||||
return_thread_runnable(data, obj_char2obj(result));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj(result), p);
|
||||
} else {
|
||||
// Try to read a UTF-8 char and if so return it, otherwise throw an error
|
||||
uint32_t state = CYC_UTF8_ACCEPT;
|
||||
|
@ -6630,7 +6630,7 @@ void _read_return_character(void *data, port_type *p)
|
|||
s++;
|
||||
}
|
||||
if (state == CYC_UTF8_ACCEPT && *s == '\0') {
|
||||
return_thread_runnable(data, obj_char2obj(codepoint));
|
||||
return_thread_runnable_with_obj(data, obj_char2obj(codepoint), p);
|
||||
} else {
|
||||
char buf[31];
|
||||
snprintf(buf, 30, "Unable to parse character %s", p->tok_buf);
|
||||
|
@ -6686,7 +6686,7 @@ void _read_return_number(void *data, port_type *p, int base, int exact)
|
|||
vec.elements[0] = &str;
|
||||
vec.elements[1] = obj_int2obj(base);
|
||||
vec.elements[2] = exact ? boolean_t : boolean_f;
|
||||
return_thread_runnable(data, &vec);
|
||||
return_thread_runnable_with_obj(data, &vec, p);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6717,7 +6717,7 @@ void _read_return_complex_number(void *data, port_type *p, int len)
|
|||
}
|
||||
}
|
||||
vec.elements[1] = obj_int2obj(i);
|
||||
return_thread_runnable(data, &vec);
|
||||
return_thread_runnable_with_obj(data, &vec, p);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6783,19 +6783,19 @@ void _read_return_atom(void *data, object cont, port_type *p)
|
|||
if (_read_is_complex_number(p->tok_buf, len)) {
|
||||
_read_return_complex_number(data, p, len);
|
||||
} else {
|
||||
return_thread_runnable(data, &opq);
|
||||
return_thread_runnable_with_obj(data, &opq, p);
|
||||
}
|
||||
} else if (strncmp("+inf.0", p->tok_buf, 6) == 0 ||
|
||||
strncmp("-inf.0", p->tok_buf, 6) == 0) {
|
||||
make_double(d, pow(2.0, 1000000));
|
||||
return_thread_runnable(data, &d);
|
||||
return_thread_runnable_with_obj(data, &d, p);
|
||||
} else if (strncmp("+nan.0", p->tok_buf, 6) == 0 ||
|
||||
strncmp("-nan.0", p->tok_buf, 6) == 0) {
|
||||
make_double(d, 0.0 / 0.0);
|
||||
return_thread_runnable(data, &d);
|
||||
return_thread_runnable_with_obj(data, &d, p);
|
||||
} else {
|
||||
sym = find_or_add_symbol(p->tok_buf);
|
||||
return_thread_runnable(data, sym);
|
||||
return_thread_runnable_with_obj(data, sym, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6807,7 +6807,7 @@ void _read_return_atom(void *data, object cont, port_type *p)
|
|||
int rv = read_from_port(p); \
|
||||
if (!rv) { \
|
||||
if (p->tok_end) _read_return_atom(data, cont, p); \
|
||||
return_thread_runnable(data, Cyc_EOF); \
|
||||
return_thread_runnable_with_obj(data, Cyc_EOF, p); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -6861,7 +6861,7 @@ object Cyc_io_peek_char(void *data, object cont, object port)
|
|||
memmove(p->mem_buf, buf, i);
|
||||
}
|
||||
|
||||
return_thread_runnable(data, (c != EOF) ? obj_char2obj(codepoint) : Cyc_EOF);
|
||||
return_thread_runnable_with_obj(data, (c != EOF) ? obj_char2obj(codepoint) : Cyc_EOF, p);
|
||||
}
|
||||
return Cyc_EOF;
|
||||
}
|
||||
|
@ -6884,7 +6884,7 @@ object Cyc_io_peek_u8(void *data, object cont, object port)
|
|||
_read_next_char(data, cont, p);
|
||||
}
|
||||
c = p->mem_buf[p->buf_idx];
|
||||
return_thread_runnable(data, (c != EOF) ? obj_char2obj(c) : Cyc_EOF);
|
||||
return_thread_runnable_with_obj(data, (c != EOF) ? obj_char2obj(c) : Cyc_EOF, p);
|
||||
}
|
||||
return Cyc_EOF;
|
||||
}
|
||||
|
@ -6925,7 +6925,7 @@ object Cyc_io_read_char(void *data, object cont, object port)
|
|||
} while(Cyc_utf8_decode(&state, &codepoint, (uint8_t)c));
|
||||
// TODO: limit above to 4 chars and then thrown an error?
|
||||
p->col_num++;
|
||||
return_thread_runnable(data, (c != EOF) ? obj_char2obj(codepoint) : Cyc_EOF);
|
||||
return_thread_runnable_with_obj(data, (c != EOF) ? obj_char2obj(codepoint) : Cyc_EOF, p);
|
||||
}
|
||||
return Cyc_EOF;
|
||||
}
|
||||
|
@ -6945,7 +6945,7 @@ object Cyc_io_read_u8(void *data, object cont, object port)
|
|||
c = p->mem_buf[p->buf_idx++];
|
||||
codepoint = (char_type) c;
|
||||
p->col_num++;
|
||||
return_thread_runnable(data, (c != EOF) ? obj_char2obj(codepoint) : Cyc_EOF);
|
||||
return_thread_runnable_with_obj(data, (c != EOF) ? obj_char2obj(codepoint) : Cyc_EOF, p);
|
||||
}
|
||||
return Cyc_EOF;
|
||||
}
|
||||
|
@ -6991,15 +6991,15 @@ object Cyc_io_read_line(void *data, object cont, object port)
|
|||
buf[len] = '\0';
|
||||
make_string_noalloc(s, buf, len);
|
||||
s.num_cp = num_cp;
|
||||
return_thread_runnable(data, &s);
|
||||
return_thread_runnable_with_obj(data, &s, port);
|
||||
}
|
||||
} else {
|
||||
if (feof(stream)) {
|
||||
return_thread_runnable(data, Cyc_EOF);
|
||||
return_thread_runnable_with_obj(data, Cyc_EOF, port);
|
||||
} else {
|
||||
// TODO: can't do this because we said thread could be blocked
|
||||
//Cyc_rt_raise2(data, "Error reading from file: ", obj_int2obj(errno));
|
||||
return_thread_runnable(data, Cyc_EOF);
|
||||
return_thread_runnable_with_obj(data, Cyc_EOF, port);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -7042,7 +7042,7 @@ void Cyc_io_read_token(void *data, object cont, object port)
|
|||
if (p->tok_end) _read_return_atom(data, cont, p);
|
||||
// Special encoding so we can distinguish from chars such as #\(
|
||||
make_c_opaque(opq, obj_char2obj(c));
|
||||
return_thread_runnable(data, &opq);
|
||||
return_thread_runnable_with_obj(data, &opq, p);
|
||||
} else if (c == ',') {
|
||||
if (p->tok_end) _read_return_atom(data, cont, p);
|
||||
|
||||
|
@ -7056,11 +7056,11 @@ void Cyc_io_read_token(void *data, object cont, object port)
|
|||
vec.elements[1] = boolean_f;
|
||||
p->buf_idx++;
|
||||
p->col_num++;
|
||||
return_thread_runnable(data, &vec);
|
||||
return_thread_runnable_with_obj(data, &vec, p);
|
||||
} else {
|
||||
// Again, special encoding for syntax
|
||||
make_c_opaque(opq, obj_char2obj(c));
|
||||
return_thread_runnable(data, &opq);
|
||||
return_thread_runnable_with_obj(data, &opq, p);
|
||||
}
|
||||
} else if (c == '"') {
|
||||
if (p->tok_end) _read_return_atom(data, cont, p);
|
||||
|
@ -7077,7 +7077,7 @@ void Cyc_io_read_token(void *data, object cont, object port)
|
|||
p->buf_idx += 3;
|
||||
p->col_num += 3;
|
||||
}
|
||||
return_thread_runnable(data, boolean_t);
|
||||
return_thread_runnable_with_obj(data, boolean_t, p);
|
||||
} else if (c == 'f') {
|
||||
if ((p->mem_buf_len - p->buf_idx) >= 4 &&
|
||||
p->mem_buf[p->buf_idx + 0] == 'a' &&
|
||||
|
@ -7087,7 +7087,7 @@ void Cyc_io_read_token(void *data, object cont, object port)
|
|||
p->buf_idx += 4;
|
||||
p->col_num += 4;
|
||||
}
|
||||
return_thread_runnable(data, boolean_f);
|
||||
return_thread_runnable_with_obj(data, boolean_f, p);
|
||||
} else if (c == '\\') {
|
||||
_read_character(data, p);
|
||||
} else if (c == 'e') {
|
||||
|
@ -7102,7 +7102,7 @@ void Cyc_io_read_token(void *data, object cont, object port)
|
|||
_read_number(data, p, 16, 1);
|
||||
} else if (c == '(') { // Vector
|
||||
make_empty_vector(vec);
|
||||
return_thread_runnable(data, &vec);
|
||||
return_thread_runnable_with_obj(data, &vec, p);
|
||||
} else if (c == 'u') { // Bytevector
|
||||
_read_next_char(data, cont, p); // Fill buffer
|
||||
c = p->mem_buf[p->buf_idx++];
|
||||
|
@ -7113,7 +7113,7 @@ void Cyc_io_read_token(void *data, object cont, object port)
|
|||
p->col_num++;
|
||||
if (c == '(') {
|
||||
make_empty_bytevector(vec);
|
||||
return_thread_runnable(data, &vec);
|
||||
return_thread_runnable_with_obj(data, &vec, p);
|
||||
} else {
|
||||
_read_error(data, p, "Unhandled input sequence");
|
||||
}
|
||||
|
@ -7130,7 +7130,7 @@ void Cyc_io_read_token(void *data, object cont, object port)
|
|||
vec.elements = (object *) alloca(sizeof(object) * vec.num_elements);
|
||||
vec.elements[0] = sym;
|
||||
vec.elements[1] = boolean_f;
|
||||
return_thread_runnable(data, &vec);
|
||||
return_thread_runnable_with_obj(data, &vec, p);
|
||||
} else {
|
||||
char buf[31];
|
||||
snprintf(buf, 30, "Unhandled input sequence %c", c);
|
||||
|
@ -7142,12 +7142,12 @@ void Cyc_io_read_token(void *data, object cont, object port)
|
|||
if (p->tok_end) _read_return_atom(data, cont, p);
|
||||
// Special encoding so we can distinguish from chars such as #\(
|
||||
make_c_opaque(opq, obj_char2obj('(')); // Cheap support for brackets
|
||||
return_thread_runnable(data, &opq);
|
||||
return_thread_runnable_with_obj(data, &opq, p);
|
||||
} else if (c == ']' || c == '}') {
|
||||
if (p->tok_end) _read_return_atom(data, cont, p);
|
||||
// Special encoding so we can distinguish from chars such as #\(
|
||||
make_c_opaque(opq, obj_char2obj(')')); // Cheap support for brackets
|
||||
return_thread_runnable(data, &opq);
|
||||
return_thread_runnable_with_obj(data, &opq, p);
|
||||
} else {
|
||||
// No special meaning, add char to current token (an atom)
|
||||
_read_add_to_tok_buf(p, c);
|
||||
|
|
Loading…
Add table
Reference in a new issue