Skip to content

Commit

Permalink
Issue #270 - Working through a solution
Browse files Browse the repository at this point in the history
  • Loading branch information
justinethier committed Aug 7, 2018
1 parent 386e208 commit 40c7320
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 42 deletions.
25 changes: 24 additions & 1 deletion gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
Expand Down
14 changes: 12 additions & 2 deletions include/cyclone/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)); \
Expand Down Expand Up @@ -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;
Expand Down
78 changes: 39 additions & 39 deletions runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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);
}
}

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

Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand All @@ -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' &&
Expand All @@ -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') {
Expand All @@ -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++];
Expand All @@ -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");
}
Expand All @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 40c7320

Please sign in to comment.