mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-19 05:39:17 +02:00
srfi-18: pthread-terminate! takes a thread object as argument
Handle this by checking if the argument is the primordial thread, current thread or another thread. The first two cases remain almost identical to the previous implementation. To terminate a thread (which is not the caller) we use a pthread key which contains the thread data. The destructor is set to Cyc_end_thread and will terminate the thread when pthread_cancel is called. This ensures that Cyc_end_thread is called with the correct thread data by the thread which will be terminated.
This commit is contained in:
parent
7d32069e2a
commit
23301bfd1a
2 changed files with 35 additions and 3 deletions
|
@ -8,6 +8,7 @@
|
|||
* This file contains the C runtime used by compiled programs.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ck_hs.h>
|
||||
#include <ck_ht.h>
|
||||
#include <ck_pr.h>
|
||||
|
@ -211,6 +212,8 @@ const object Cyc_RECORD_MARKER = &__RECORD;
|
|||
static ck_hs_t lib_table;
|
||||
static ck_hs_t symbol_table;
|
||||
static int symbol_table_initial_size = 4096;
|
||||
static int cyclone_thread_key_create = 1;
|
||||
static pthread_key_t cyclone_thread_key;
|
||||
static pthread_mutex_t symbol_table_lock;
|
||||
|
||||
char **env_variables = NULL;
|
||||
|
@ -7125,6 +7128,11 @@ void *Cyc_init_thread(object thread_and_thunk, int argc, object * args)
|
|||
gc_add_mutator(thd);
|
||||
ck_pr_cas_int((int *)&(thd->thread_state), CYC_THREAD_STATE_NEW,
|
||||
CYC_THREAD_STATE_RUNNABLE);
|
||||
if (ck_pr_cas_int(&cyclone_thread_key_create, 1, 0)) {
|
||||
int r = pthread_key_create(&cyclone_thread_key, Cyc_end_thread);
|
||||
assert(r == 0);
|
||||
}
|
||||
pthread_setspecific(cyclone_thread_key, thd);
|
||||
Cyc_start_trampoline(thd);
|
||||
return NULL;
|
||||
}
|
||||
|
|
30
srfi/18.sld
30
srfi/18.sld
|
@ -132,9 +132,33 @@
|
|||
t))
|
||||
|
||||
(define (thread-yield!) (thread-sleep! 1))
|
||||
(define-c thread-terminate!
|
||||
"(void *data, object _, int argc, object *args)"
|
||||
" Cyc_end_thread(data); ")
|
||||
|
||||
(define-c %thread-terminate!
|
||||
"(void *data, int argc, closure _, object k, object thread_data_opaque)"
|
||||
" gc_thread_data *td;
|
||||
if (thread_data_opaque == boolean_f) {
|
||||
/* primordial thread */
|
||||
__halt(boolean_f);
|
||||
} else {
|
||||
td = (gc_thread_data *)(opaque_ptr(thread_data_opaque));
|
||||
if (td == data) {
|
||||
Cyc_end_thread(td);
|
||||
} else {
|
||||
pthread_cancel(td->thread_id);
|
||||
}
|
||||
}
|
||||
return_closcall1(data, k, boolean_t);")
|
||||
(define (thread-terminate! t)
|
||||
(cond
|
||||
((and (thread? t)
|
||||
(or (Cyc-opaque? (vector-ref t 2)) (equal? *primordial-thread* t)))
|
||||
(begin
|
||||
(Cyc-minor-gc)
|
||||
(vector-set! t 5 (%get-thread-data)) ;; remember calling thread
|
||||
(%thread-terminate! (vector-ref t 2))
|
||||
#t))
|
||||
(else
|
||||
#f))) ;; TODO: raise an error instead?
|
||||
|
||||
;; TODO: not good enough, need to return value from thread
|
||||
;; TODO: perhaps not an ideal solution using a loop/polling below, but good
|
||||
|
|
Loading…
Add table
Reference in a new issue