diff options
Diffstat (limited to 'libguile/whippet/src/serial-tracer.h')
-rw-r--r-- | libguile/whippet/src/serial-tracer.h | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/libguile/whippet/src/serial-tracer.h b/libguile/whippet/src/serial-tracer.h new file mode 100644 index 000000000..a3289e30c --- /dev/null +++ b/libguile/whippet/src/serial-tracer.h @@ -0,0 +1,88 @@ +#ifndef SERIAL_TRACER_H +#define SERIAL_TRACER_H + +#include <sys/mman.h> +#include <unistd.h> + +#include "assert.h" +#include "debug.h" +#include "simple-worklist.h" +#include "root-worklist.h" +#include "tracer.h" + +struct gc_tracer { + struct gc_heap *heap; + int trace_roots_only; + struct root_worklist roots; + struct simple_worklist worklist; +}; + +struct gc_trace_worker { + struct gc_tracer *tracer; + struct gc_trace_worker_data *data; +}; + +static inline struct gc_trace_worker_data* +gc_trace_worker_data(struct gc_trace_worker *worker) { + return worker->data; +} + +static int +gc_tracer_init(struct gc_tracer *tracer, struct gc_heap *heap, + size_t parallelism) { + tracer->heap = heap; + tracer->trace_roots_only = 0; + root_worklist_init(&tracer->roots); + return simple_worklist_init(&tracer->worklist); +} +static void gc_tracer_prepare(struct gc_tracer *tracer) {} +static void gc_tracer_release(struct gc_tracer *tracer) { + simple_worklist_release(&tracer->worklist); +} + +static inline void +gc_tracer_add_root(struct gc_tracer *tracer, struct gc_root root) { + root_worklist_push(&tracer->roots, root); +} + +static inline void +gc_trace_worker_enqueue(struct gc_trace_worker *worker, struct gc_ref ref) { + simple_worklist_push(&worker->tracer->worklist, ref); +} + +static inline void +tracer_trace_with_data(struct gc_tracer *tracer, struct gc_heap *heap, + struct gc_trace_worker *worker, + struct gc_trace_worker_data *data) { + worker->data = data; + do { + struct gc_root root = root_worklist_pop(&tracer->roots); + if (root.kind == GC_ROOT_KIND_NONE) + break; + trace_root(root, heap, worker); + } while (1); + root_worklist_reset(&tracer->roots); + if (!tracer->trace_roots_only) { + do { + struct gc_ref obj = simple_worklist_pop(&tracer->worklist); + if (gc_ref_is_null(obj)) + break; + trace_one(obj, heap, worker); + } while (1); + } +} +static inline void +gc_tracer_trace(struct gc_tracer *tracer) { + struct gc_trace_worker worker = { tracer }; + gc_trace_worker_call_with_data(tracer_trace_with_data, tracer, tracer->heap, + &worker); +} + +static inline void +gc_tracer_trace_roots(struct gc_tracer *tracer) { + tracer->trace_roots_only = 1; + gc_tracer_trace(tracer); + tracer->trace_roots_only = 0; +} + +#endif // SERIAL_TRACER_H |