Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[wasm] add no thread variant for freestanding environment
This implementation does nothing around preemptive context switching because there is no native thread.
- Loading branch information
1 parent
d6d52a7
commit 420622b
Showing
5 changed files
with
306 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,278 @@ | ||
/* | ||
A thread interface implementation without any system thread. | ||
Assumption: | ||
* There is a only single thread in the ruby process | ||
* No signal happens targeting the ruby process | ||
Note: | ||
* No thread switching in the VM | ||
* No timer thread because thread switching won't happen | ||
* No mutex guard because the VM won't be racy | ||
*/ | ||
|
||
#ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION | ||
|
||
#include <time.h> | ||
|
||
#define DEBUG_OUT() (void)(0); | ||
|
||
#define TIME_QUANTUM_MSEC (100) | ||
#define TIME_QUANTUM_USEC (TIME_QUANTUM_MSEC * 1000) | ||
#define TIME_QUANTUM_NSEC (TIME_QUANTUM_USEC * 1000) | ||
|
||
// Do nothing for GVL | ||
static void | ||
gvl_acquire(rb_global_vm_lock_t *gvl, rb_thread_t *th) | ||
{ | ||
} | ||
|
||
static void | ||
gvl_release(rb_global_vm_lock_t *gvl) | ||
{ | ||
} | ||
|
||
static void | ||
gvl_yield(rb_global_vm_lock_t *gvl, rb_thread_t *th) | ||
{ | ||
} | ||
|
||
void | ||
rb_gvl_init(rb_global_vm_lock_t *gvl) | ||
{ | ||
} | ||
|
||
static void | ||
gvl_destroy(rb_global_vm_lock_t *gvl) | ||
{ | ||
} | ||
|
||
// Do nothing for mutex guard | ||
void | ||
rb_native_mutex_lock(rb_nativethread_lock_t *lock) | ||
{ | ||
} | ||
|
||
void | ||
rb_native_mutex_unlock(rb_nativethread_lock_t *lock) | ||
{ | ||
} | ||
|
||
int | ||
rb_native_mutex_trylock(rb_nativethread_lock_t *lock) | ||
{ | ||
return 0; | ||
} | ||
|
||
void | ||
rb_native_mutex_initialize(rb_nativethread_lock_t *lock) | ||
{ | ||
} | ||
|
||
void | ||
rb_native_mutex_destroy(rb_nativethread_lock_t *lock) | ||
{ | ||
} | ||
|
||
void | ||
rb_native_cond_initialize(rb_nativethread_cond_t *cond) | ||
{ | ||
} | ||
|
||
void | ||
rb_native_cond_destroy(rb_nativethread_cond_t *cond) | ||
{ | ||
} | ||
|
||
void | ||
rb_native_cond_signal(rb_nativethread_cond_t *cond) | ||
{ | ||
} | ||
|
||
void | ||
rb_native_cond_broadcast(rb_nativethread_cond_t *cond) | ||
{ | ||
} | ||
|
||
void | ||
rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex) | ||
{ | ||
} | ||
|
||
void | ||
rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec) | ||
{ | ||
} | ||
|
||
// The only one thread in process | ||
static rb_thread_t *ruby_native_thread; | ||
|
||
rb_thread_t * | ||
ruby_thread_from_native(void) | ||
{ | ||
return ruby_native_thread; | ||
} | ||
|
||
int | ||
ruby_thread_set_native(rb_thread_t *th) | ||
{ | ||
if (th && th->ec) { | ||
rb_ractor_set_current_ec(th->ractor, th->ec); | ||
} | ||
ruby_native_thread = th; | ||
return 1; // always succeed | ||
} | ||
|
||
void | ||
Init_native_thread(rb_thread_t *th) | ||
{ | ||
// no TLS setup and no thread id setup | ||
ruby_thread_set_native(th); | ||
fill_thread_id_str(th); | ||
} | ||
|
||
static void | ||
native_thread_destroy(rb_thread_t *th) | ||
{ | ||
} | ||
|
||
void | ||
ruby_init_stack(volatile VALUE *addr) | ||
{ | ||
} | ||
|
||
static int | ||
native_thread_init_stack(rb_thread_t *th) | ||
{ | ||
return 0; // success | ||
} | ||
|
||
static int | ||
native_thread_create(rb_thread_t *th) | ||
{ | ||
th->status = THREAD_KILLED; | ||
rb_ractor_living_threads_remove(th->ractor, th); | ||
rb_notimplement(); | ||
} | ||
|
||
// Do nothing for handling ubf because no other thread doesn't exist and unblock anything | ||
#define register_ubf_list(th) (void)(th) | ||
#define unregister_ubf_list(th) (void)(th) | ||
#define ubf_select 0 | ||
|
||
inline static void | ||
ubf_wakeup_all_threads(void) | ||
{ | ||
return; | ||
} | ||
|
||
inline static int | ||
ubf_threads_empty(void) | ||
{ | ||
return 1; // true | ||
} | ||
|
||
inline static void | ||
ubf_list_atfork() | ||
{ | ||
} | ||
|
||
inline static void | ||
ubf_timer_disarm(void) | ||
{ | ||
} | ||
|
||
|
||
// No timer thread because thread switching won't happen | ||
#define TIMER_THREAD_CREATED_P() (1) | ||
inline static void | ||
rb_thread_create_timer_thread(void) | ||
{ | ||
} | ||
|
||
void | ||
rb_thread_wakeup_timer_thread(int sig) | ||
{ | ||
} | ||
|
||
inline static int | ||
native_stop_timer_thread(void) | ||
{ | ||
return 1; // success | ||
} | ||
|
||
inline static void | ||
native_reset_timer_thread(void) | ||
{ | ||
} | ||
|
||
// Do nothing for thread naming | ||
inline static void | ||
native_set_thread_name(rb_thread_t *th) | ||
{ | ||
} | ||
|
||
inline static void | ||
native_set_another_thread_name(rb_nativethread_id_t thread_id, VALUE name) | ||
{ | ||
} | ||
|
||
// Don't expose native thread id for now to keep system's thread API agnostic | ||
#define USE_NATIVE_THREAD_NATIVE_THREAD_ID 0 | ||
|
||
// No reserved fd for piping threads | ||
int | ||
rb_reserved_fd_p(int fd) | ||
{ | ||
return 0; // not reserved | ||
} | ||
|
||
// Don't expose native thread info for now to keep system's thread API agnostic | ||
rb_nativethread_id_t | ||
rb_nativethread_self(void) | ||
{ | ||
return NULL; | ||
} | ||
|
||
// Do nothing for sigwait things because of no signal assumption | ||
// Q(katei): is this correct description? | ||
int | ||
rb_sigwait_fd_get(const rb_thread_t *th) | ||
{ | ||
return -1; | ||
} | ||
|
||
NORETURN(void rb_sigwait_fd_put(rb_thread_t *, int)); | ||
void | ||
rb_sigwait_fd_put(rb_thread_t *th, int fd) | ||
{ | ||
rb_bug("not implemented, should not be called rb_sigwait_fd_put"); | ||
} | ||
|
||
NORETURN(void rb_sigwait_sleep(const rb_thread_t *, int, const rb_hrtime_t *)); | ||
void | ||
rb_sigwait_sleep(const rb_thread_t *th, int sigwait_fd, const rb_hrtime_t *rel) | ||
{ | ||
rb_bug("not implemented, should not be called rb_sigwait_sleep"); | ||
} | ||
|
||
static void | ||
native_sleep(rb_thread_t *th, rb_hrtime_t *rel) | ||
{ | ||
// No signal assumption allows the use of uninterruptible sleep | ||
struct timespec ts; | ||
(void)clock_nanosleep(CLOCK_REALTIME, 0, rb_hrtime2timespec(&ts, rel), NULL); | ||
} | ||
|
||
static int | ||
native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout, rb_thread_t *th) | ||
{ | ||
return rb_fd_select(n, readfds, writefds, exceptfds, timeout); | ||
} | ||
|
||
static VALUE | ||
rb_thread_start_unblock_thread(void) | ||
{ | ||
return Qfalse; | ||
} | ||
#endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#ifndef RUBY_THREAD_NONE_H | ||
#define RUBY_THREAD_NONE_H | ||
|
||
#define RB_NATIVETHREAD_LOCK_INIT (void)(0) | ||
#define RB_NATIVETHREAD_COND_INIT (void)(0) | ||
|
||
// no-thread impl doesn't use TLS but define this to avoid using tls key | ||
// based implementation in vm.c | ||
#define RB_THREAD_LOCAL_SPECIFIER | ||
|
||
typedef struct native_thread_data_struct {} native_thread_data_t; | ||
|
||
typedef struct rb_global_vm_lock_struct {} rb_global_vm_lock_t; | ||
|
||
RUBY_EXTERN struct rb_execution_context_struct *ruby_current_ec; | ||
|
||
#endif /* RUBY_THREAD_NONE_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters