mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-19 05:39:17 +02:00
Issue #320 - Track threads that have not yet run
This allows (thread-join!) to be able to wait on these new threads
This commit is contained in:
parent
c49c753f9d
commit
d1dbd7fae9
4 changed files with 62 additions and 6 deletions
50
gc.c
50
gc.c
|
@ -66,8 +66,11 @@ static int mark_stack_i = 0;
|
||||||
// thread terminates (normally or not).
|
// thread terminates (normally or not).
|
||||||
static gc_thread_data *primordial_thread = NULL;
|
static gc_thread_data *primordial_thread = NULL;
|
||||||
|
|
||||||
|
/** Data new mutator threads that are not running yet */
|
||||||
|
static ck_array_t new_mutators;
|
||||||
/** Data for each individual mutator thread */
|
/** Data for each individual mutator thread */
|
||||||
ck_array_t Cyc_mutators, old_mutators;
|
static ck_array_t Cyc_mutators;
|
||||||
|
static ck_array_t old_mutators;
|
||||||
static pthread_mutex_t mutators_lock;
|
static pthread_mutex_t mutators_lock;
|
||||||
|
|
||||||
static void my_free(void *p, size_t m, bool d)
|
static void my_free(void *p, size_t m, bool d)
|
||||||
|
@ -214,6 +217,10 @@ void gc_initialize(void)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ck_array_init(&new_mutators, CK_ARRAY_MODE_SPMC, &my_allocator, 10) == 0) {
|
||||||
|
fprintf(stderr, "Unable to initialize mutator array\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
if (ck_array_init(&old_mutators, CK_ARRAY_MODE_SPMC, &my_allocator, 10) == 0) {
|
if (ck_array_init(&old_mutators, CK_ARRAY_MODE_SPMC, &my_allocator, 10) == 0) {
|
||||||
fprintf(stderr, "Unable to initialize mutator array\n");
|
fprintf(stderr, "Unable to initialize mutator array\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -230,7 +237,25 @@ void gc_initialize(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add data for a new mutator
|
* @brief Add data for a new mutator that is not yet scheduled to run.
|
||||||
|
* This is done so there is a record in the system even if the
|
||||||
|
* thread is not running, to prevent race conditions for any
|
||||||
|
* functions (EG: thread-join!) that need to access the thread.
|
||||||
|
* @param thd Thread data for the mutator
|
||||||
|
*/
|
||||||
|
void gc_add_new_unrunning_mutator(gc_thread_data * thd)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&mutators_lock);
|
||||||
|
if (ck_array_put_unique(&new_mutators, (void *)thd) < 0) {
|
||||||
|
fprintf(stderr, "Unable to allocate memory for a new thread, exiting\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ck_array_commit(&new_mutators);
|
||||||
|
pthread_mutex_unlock(&mutators_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add data for a new mutator that is starting to run.
|
||||||
* @param thd Thread data for the mutator
|
* @param thd Thread data for the mutator
|
||||||
*/
|
*/
|
||||||
void gc_add_mutator(gc_thread_data * thd)
|
void gc_add_mutator(gc_thread_data * thd)
|
||||||
|
@ -246,6 +271,10 @@ void gc_add_mutator(gc_thread_data * thd)
|
||||||
// Main thread is always the first one added
|
// Main thread is always the first one added
|
||||||
if (primordial_thread == NULL) {
|
if (primordial_thread == NULL) {
|
||||||
primordial_thread = thd;
|
primordial_thread = thd;
|
||||||
|
} else {
|
||||||
|
// At this point the mutator is running, so remove it from the new list
|
||||||
|
ck_array_remove(&new_mutators, (void *)thd);
|
||||||
|
ck_array_commit(&new_mutators);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +319,23 @@ int gc_is_mutator_active(gc_thread_data *thd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Determine if the given mutator is in the list of new threads.
|
||||||
|
* @param thd Thread data object of the m
|
||||||
|
* @return A true value if the mutator is found, 0 otherwise.
|
||||||
|
*/
|
||||||
|
int gc_is_mutator_new(gc_thread_data *thd)
|
||||||
|
{
|
||||||
|
ck_array_iterator_t iterator;
|
||||||
|
gc_thread_data *m;
|
||||||
|
CK_ARRAY_FOREACH(&new_mutators, &iterator, &m) {
|
||||||
|
if (m == thd) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free thread data for all terminated mutators
|
* @brief Free thread data for all terminated mutators
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -349,9 +349,11 @@ struct gc_thread_data_t {
|
||||||
|
|
||||||
/* GC prototypes */
|
/* GC prototypes */
|
||||||
void gc_initialize(void);
|
void gc_initialize(void);
|
||||||
|
void gc_add_new_unrunning_mutator(gc_thread_data * thd);
|
||||||
void gc_add_mutator(gc_thread_data * thd);
|
void gc_add_mutator(gc_thread_data * thd);
|
||||||
void gc_remove_mutator(gc_thread_data * thd);
|
void gc_remove_mutator(gc_thread_data * thd);
|
||||||
int gc_is_mutator_active(gc_thread_data *thd);
|
int gc_is_mutator_active(gc_thread_data *thd);
|
||||||
|
int gc_is_mutator_new(gc_thread_data *thd);
|
||||||
void gc_sleep_ms(int ms);
|
void gc_sleep_ms(int ms);
|
||||||
gc_heap *gc_heap_create(int heap_type, size_t size, size_t max_size,
|
gc_heap *gc_heap_create(int heap_type, size_t size, size_t max_size,
|
||||||
size_t chunk_size, gc_thread_data *thd);
|
size_t chunk_size, gc_thread_data *thd);
|
||||||
|
|
|
@ -33,7 +33,8 @@
|
||||||
(thread-start! t2)
|
(thread-start! t2)
|
||||||
|
|
||||||
(write (thread? t))
|
(write (thread? t))
|
||||||
(thread-sleep! 1)
|
(write (thread? t2))
|
||||||
|
(newline)
|
||||||
;; Main thread - wait for thread to broadcast it is done
|
;; Main thread - wait for thread to broadcast it is done
|
||||||
(thread-join! t)
|
(thread-join! t)
|
||||||
(thread-join! t2)
|
(thread-join! t2)
|
||||||
|
|
13
srfi/18.sld
13
srfi/18.sld
|
@ -71,7 +71,13 @@
|
||||||
;; - name
|
;; - name
|
||||||
;; - specific
|
;; - specific
|
||||||
;; - internal
|
;; - internal
|
||||||
(vector 'cyc-thread-obj thunk #f name-str #f #f)))
|
(vector
|
||||||
|
'cyc-thread-obj
|
||||||
|
thunk
|
||||||
|
(%alloc-thread-data) ;; Internal data for new thread
|
||||||
|
name-str
|
||||||
|
#f
|
||||||
|
#f)))
|
||||||
|
|
||||||
(define (thread-name t) (vector-ref t 3))
|
(define (thread-name t) (vector-ref t 3))
|
||||||
(define (thread-specific t) (vector-ref t 4))
|
(define (thread-specific t) (vector-ref t 4))
|
||||||
|
@ -100,6 +106,7 @@
|
||||||
(define-c %alloc-thread-data
|
(define-c %alloc-thread-data
|
||||||
"(void *data, int argc, closure _, object k)"
|
"(void *data, int argc, closure _, object k)"
|
||||||
" gc_thread_data *td = malloc(sizeof(gc_thread_data));
|
" gc_thread_data *td = malloc(sizeof(gc_thread_data));
|
||||||
|
gc_add_new_unrunning_mutator(td); /* Register this thread */
|
||||||
make_c_opaque(co, td);
|
make_c_opaque(co, td);
|
||||||
return_closcall1(data, k, &co); ")
|
return_closcall1(data, k, &co); ")
|
||||||
|
|
||||||
|
@ -112,7 +119,6 @@
|
||||||
(thunk)))))
|
(thunk)))))
|
||||||
(vector-set! t 5 (%get-thread-data)) ;; Temporarily make parent thread
|
(vector-set! t 5 (%get-thread-data)) ;; Temporarily make parent thread
|
||||||
;; data available for child init
|
;; data available for child init
|
||||||
(vector-set! t 2 (%alloc-thread-data)) ;; Data for new thread
|
|
||||||
(Cyc-minor-gc)
|
(Cyc-minor-gc)
|
||||||
(Cyc-spawn-thread! thread-params)
|
(Cyc-spawn-thread! thread-params)
|
||||||
))
|
))
|
||||||
|
@ -131,7 +137,8 @@
|
||||||
set_thread_blocked(data, k);
|
set_thread_blocked(data, k);
|
||||||
/* Cannot join to detached thread! pthread_join(td->thread_id, NULL);*/
|
/* Cannot join to detached thread! pthread_join(td->thread_id, NULL);*/
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!gc_is_mutator_active(td)){
|
if (!gc_is_mutator_new(td) &&
|
||||||
|
!gc_is_mutator_active(td)){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gc_sleep_ms(250);
|
gc_sleep_ms(250);
|
||||||
|
|
Loading…
Add table
Reference in a new issue