5 #ifndef KRK_DISABLE_THREADS
11 #if defined(__linux__)
12 # include <sys/syscall.h>
13 # define gettid() syscall(SYS_gettid)
14 #elif defined(__toaru__)
17 # define gettid() GetCurrentThreadId()
37 unsigned int started:1;
49 pthread_mutex_t mutex;
52 KRK_Function(current_thread) {
57 #define IS_Thread(o) (krk_isInstanceOf(o, KRK_BASE_CLASS(Thread)))
58 #define AS_Thread(o) ((struct Thread *)AS_OBJECT(o))
59 #define CURRENT_CTYPE struct Thread *
60 #define CURRENT_NAME self
62 static volatile int _threadLock = 0;
63 static void * _startthread(
void * _threadObj) {
64 #if defined(__APPLE__) && defined(__aarch64__)
65 krk_forceThreadData();
69 vm.globalFlags |= KRK_GLOBAL_THREADS;
70 _obtain_lock(_threadLock);
71 if (
vm.threads->next) {
75 _release_lock(_threadLock);
78 struct Thread *
self = _threadObj;
95 _obtain_lock(_threadLock);
103 previous = previous->
next;
105 _release_lock(_threadLock);
115 return INTEGER_VAL(self->tid);
120 return krk_runtimeError(KRK_EXC(ThreadError),
"Thread can not join itself.");
122 return krk_runtimeError(KRK_EXC(ThreadError),
"Thread has not been started.");
124 pthread_join(self->nativeRef, NULL);
128 KRK_Method(
Thread,start) {
132 return krk_runtimeError(KRK_EXC(ThreadError),
"Thread has already been started.");
136 pthread_create(&self->nativeRef, NULL, _startthread, (
void*)
self);
141 KRK_Method(
Thread,is_alive) {
143 return BOOLEAN_VAL(self->alive);
148 #define IS_Lock(o) (krk_isInstanceOf(o, KRK_BASE_CLASS(Lock)))
149 #define AS_Lock(o) ((struct Lock *)AS_OBJECT(o))
150 #define CURRENT_CTYPE struct Lock *
152 KRK_Method(
Lock,__init__) {
154 pthread_mutex_init(&self->mutex, NULL);
158 static inline void _pushLockStatus(
struct Lock *
self,
struct StringBuilder * sb) {
161 if (self->mutex.__data.__owner) {
162 pushStringBuilderStr(sb,
" (locked)", 9);
164 pushStringBuilderStr(sb,
" (unlocked)", 11);
173 KRK_Method(
Lock,__repr__) {
176 pushStringBuilderStr(&sb,
"<Lock ", 6);
181 size_t len = snprintf(tmp, 100,
"%p", (
void*)
self);
182 pushStringBuilderStr(&sb, tmp, len);
185 _pushLockStatus(
self,&sb);
187 pushStringBuilder(&sb,
'>');
188 return finishStringBuilder(&sb);
191 KRK_Method(
Lock,__enter__) {
193 pthread_mutex_lock(&self->mutex);
197 KRK_Method(
Lock,__exit__) {
198 pthread_mutex_unlock(&self->mutex);
214 "@brief Methods and classes for creating platform threads.");
216 KRK_DOC(BIND_FUNC(threadsModule, current_thread),
217 "@brief Obtain a reference to the current thread.\n"
219 "Returns the @ref Thread object associated with the calling thread, if one exists.");
221 KrkClass * ThreadError =
krk_makeClass(threadsModule, &KRK_EXC(ThreadError),
"ThreadError",
vm.exceptions->OSError);
223 "Raised in various situations when an action on a thread is invalid."
229 "Base class for building threaded execution contexts.\n\n"
230 "The @ref Thread class should be subclassed and the subclass should implement a @c run method."
233 KRK_DOC(BIND_METHOD(
Thread,start),
"Start the thread. A thread may only be started once.");
234 KRK_DOC(BIND_METHOD(
Thread,join),
"Join the thread. Does not return until the thread finishes.");
235 KRK_DOC(BIND_METHOD(
Thread,is_alive),
"Query the status of the thread.");
236 KRK_DOC(BIND_PROP(
Thread,tid),
"The platform-specific thread identifier, if available. Usually an integer.");
241 "Represents an atomic mutex.\n\n"
242 "@ref Lock objects allow for exclusive access to a resource and can be used in a @c with block."
244 Lock->allocSize =
sizeof(
struct Lock);
245 KRK_DOC(BIND_METHOD(
Lock,__init__),
"Initialize a system mutex.");
246 KRK_DOC(BIND_METHOD(
Lock,__enter__),
"Acquire the lock.");
247 KRK_DOC(BIND_METHOD(
Lock,__exit__),
"Release the lock.");
248 BIND_METHOD(
Lock,__repr__);
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Top-level header with configuration macros.
Represents a managed call state in a VM thread.
KrkClass * krk_makeClass(KrkInstance *module, KrkClass **_class, const char *name, KrkClass *base)
Convenience function for creating new types.
KrkTable methods
General attributes table.
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
struct KrkClass * _class
Metaclass.
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
KrkTable fields
Attributes table.
The most basic object type.
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
void krk_attachNamedObject(KrkTable *table, const char name[], KrkObj *obj)
Attach an object to an attribute table.
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
Execution state of a VM thread.
struct KrkThreadState * next
Stack reference or primative value.
Simple atomic structure for waiting.
Inline flexible string array.
Object representation of a system thread.
Utilities for creating native bindings.
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
void krk_resetStack(void)
Reset the current thread's stack state to the top level.
void krk_module_init_threading(void)
Initialize the built-in 'threading' module.
KrkValue krk_callStack(int argCount)
Call a callable on the stack with argCount arguments.
#define vm
Convenience macro for namespacing.
threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
void krk_push(KrkValue value)
Push a stack value.