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:
Justin Ethier 2019-06-10 13:16:39 -04:00
parent c49c753f9d
commit d1dbd7fae9
4 changed files with 62 additions and 6 deletions

50
gc.c
View file

@ -66,8 +66,11 @@ static int mark_stack_i = 0;
// thread terminates (normally or not).
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 */
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 void my_free(void *p, size_t m, bool d)
@ -214,6 +217,10 @@ void gc_initialize(void)
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) {
fprintf(stderr, "Unable to initialize mutator array\n");
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
*/
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
if (primordial_thread == NULL) {
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;
}
/**
* @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
*/

View file

@ -349,9 +349,11 @@ struct gc_thread_data_t {
/* GC prototypes */
void gc_initialize(void);
void gc_add_new_unrunning_mutator(gc_thread_data * thd);
void gc_add_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_new(gc_thread_data *thd);
void gc_sleep_ms(int ms);
gc_heap *gc_heap_create(int heap_type, size_t size, size_t max_size,
size_t chunk_size, gc_thread_data *thd);

View file

@ -33,7 +33,8 @@
(thread-start! t2)
(write (thread? t))
(thread-sleep! 1)
(write (thread? t2))
(newline)
;; Main thread - wait for thread to broadcast it is done
(thread-join! t)
(thread-join! t2)

View file

@ -71,7 +71,13 @@
;; - name
;; - specific
;; - 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-specific t) (vector-ref t 4))
@ -100,6 +106,7 @@
(define-c %alloc-thread-data
"(void *data, int argc, closure _, object k)"
" gc_thread_data *td = malloc(sizeof(gc_thread_data));
gc_add_new_unrunning_mutator(td); /* Register this thread */
make_c_opaque(co, td);
return_closcall1(data, k, &co); ")
@ -112,7 +119,6 @@
(thunk)))))
(vector-set! t 5 (%get-thread-data)) ;; Temporarily make parent thread
;; data available for child init
(vector-set! t 2 (%alloc-thread-data)) ;; Data for new thread
(Cyc-minor-gc)
(Cyc-spawn-thread! thread-params)
))
@ -131,7 +137,8 @@
set_thread_blocked(data, k);
/* Cannot join to detached thread! pthread_join(td->thread_id, NULL);*/
while (1) {
if (!gc_is_mutator_active(td)){
if (!gc_is_mutator_new(td) &&
!gc_is_mutator_active(td)){
break;
}
gc_sleep_ms(250);