#include "tlang.h" #if defined(USE_THREADS) bool thread_init=false; #if defined(GEKKO) #include #include #else #include #endif tmutex_t global_mutex; tmutex_t Mutex_Create() { #if defined(GEKKO) mutex_t mutex=LWP_MUTEX_NULL; LWP_MutexInit(&mutex,true); return (tmutex_t)mutex; #else pthread_mutex_t* mtx= (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t)); memset(mtx,0,sizeof(pthread_mutex_t)); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); #if defined(PTHREAD_MUTEX_RECURSIVE_NP) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); #else pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); #endif pthread_mutex_init(mtx,&attr); return (tmutex_t)mtx; #endif } void Mutex_Free(tmutex_t mutex) { #if defined(GEKKO) LWP_MutexDestroy((mutex_t)mutex); #else pthread_mutex_destroy((pthread_mutex_t*)mutex); free(mutex); #endif } int64_t Mutex_Lock(tmutex_t mutex) { #if defined(GEKKO) return LWP_MutexLock((mutex_t)mutex); #else return pthread_mutex_lock((pthread_mutex_t*)mutex); #endif } int64_t Mutex_Unlock(tmutex_t mutex) { #if defined(GEKKO) LWP_MutexUnlock((mutex_t)mutex); #else return pthread_mutex_unlock((pthread_mutex_t*)mutex); #endif } void Global_Mutex_Lock() { if(thread_init) Mutex_Lock(global_mutex); } void Global_Mutex_Unlock() { if(thread_init) Mutex_Unlock(global_mutex); } void Threading_Thread_Create(void*(*entry)(void*),void* arg) { #if defined(GEKKO) lwp_t lwp=LWP_THREAD_NULL; LWP_CreateThread(&lwp,entry,arg,NULL,0,64); #else pthread_t thrd; pthread_create(&thrd,NULL,entry,arg); pthread_detach(thrd); #endif } typedef struct { tobject_t* obj; runtime_t* rt; } __thread_arg_ctx; static void* __create_thread_thread_func(void* data) { __thread_arg_ctx* ctx = (__thread_arg_ctx*)data; list_tobject_t objs; list_create(ctx->rt,&objs,0); tobject_t* obj=tobject_call(ctx->rt->globals,ctx->obj,&objs); tobject_freeifzero(obj); tobject_rmref(ctx->obj); free(data); } void __create_mutex_destroy(tobject_t* obj) { Mutex_Free((tmutex_t)obj->ptr_data); } tobject_t* __create_mutex_lock_external_method(runtime_t* rt,void* ptr,list_tobject_t* args) { Mutex_Lock((tmutex_t)ptr); return tobject_basic(rt,tundef); } tobject_t* __create_mutex_unlock_external_method(runtime_t* rt,void* ptr,list_tobject_t* args) { Mutex_Unlock((tmutex_t)ptr); return tobject_basic(rt,tundef); } tobject_t* __create_mutex_external_method(runtime_t* rt,void* ptr,list_tobject_t* args) { tobject_t* o = tobject_create(rt); o->type = tdict; o->data.dict = dict_create(); tmutex_t* mutex=Mutex_Create(); o->ptr_data = mutex; runtime_create_method_on_dict(o->data.dict,"lock",rt,mutex,__create_mutex_lock_external_method,NULL); runtime_create_method_on_dict(o->data.dict,"unlock",rt,mutex,__create_mutex_unlock_external_method,NULL); o->free = __create_mutex_destroy; return o; } tobject_t* __create_thread_external_method(runtime_t* rt,void* ptr,list_tobject_t* args) { if(args->length > 0) { tobject_t* data=args->items[0]; if(data->type == tinternalmethod || data->type == texternalmethod) { data->count++; __thread_arg_ctx* ctx = (__thread_arg_ctx*)malloc(sizeof(__thread_arg_ctx)); ctx->obj = data; ctx->rt = rt; Threading_Thread_Create(__create_thread_thread_func,(void*)ctx); } } return tobject_basic(rt,tundef); } void runtime_register_threads(runtime_t* rt,dict_t* create) { if(!thread_init) { global_mutex = Mutex_Create(); thread_init = true; } runtime_create_method_on_dict(create,"thread",rt,NULL,__create_thread_external_method,NULL); runtime_create_method_on_dict(create,"mutex",rt,NULL,__create_mutex_external_method,NULL); } #else void Global_Mutex_Lock() { } void Global_Mutex_Unlock() { } #endif