/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This source file is part of SableVM. * * * * See the file "LICENSE" for the copyright information and for * * the terms and conditions for copying, distribution and * * modification of this source file. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef SVM_THREAD_H #define SVM_THREAD_H #if 0 #define THD0(str) \ printf("T(%d) " str "\n", env->thread.id); fflush(NULL) #define THD1(str, p1) \ printf("T(%d) " str "\n", env->thread.id, p1); fflush(NULL) #define THD2(str, p1, p2) \ printf("T(%d) " str "\n", env->thread.id, p1, p2); fflush(NULL) #define THD3(str, p1, p2, p3) \ printf("T(%d) " str "\n", env->thread.id, p1, p2, p3); fflush(NULL) #define THD4(str, p1, p2, p3, p4) \ printf("T(%d) " str "\n", env->thread.id, p1, p2, p3, p4); fflush(NULL) #define THD5(str, p1, p2, p3, p4, p5) \ printf("T(%d) " str "\n", env->thread.id, p1, p2, p3, p4, p5); fflush(NULL) #else #define THD0(str) #define THD1(str, p1) #define THD2(str, p1, p2) #define THD3(str, p1, p2, p3) #define THD4(str, p1, p2, p3, p4) #define THD5(str, p1, p2, p3, p4, p5) #endif #define _svmm_mutex_init(mutex) \ pthread_mutex_init (&mutex, NULL) #define _svmm_mutex_destroy(mutex) \ pthread_mutex_destroy (&mutex) #define _svmm_mutex_new_name(varname) \ pthread_mutex_t *varname #define _svmm_mutex_lock(mutex) \ { \ pthread_mutex_t *_svmx_pmutex = &mutex; \ pthread_mutex_lock (_svmx_pmutex) #define _svmm_mutex_unlock() \ pthread_mutex_unlock (_svmx_pmutex); \ } #define _svmm_mutex_trylock(mutex) \ pthread_mutex_trylock(&mutex) #define _svmm_mutex_unlock_after_try(mutex) \ pthread_mutex_unlock(&mutex) #define _svmm_cond_init(cond) \ pthread_cond_init (&cond, NULL) #define _svmm_cond_destroy(cond) \ pthread_cond_destroy (&cond) #define _svmm_cond_wait(cond, mutex) \ pthread_cond_wait (&cond, &mutex) #define _svmm_cond_signal(cond) \ pthread_cond_signal (&cond) #define _svmm_cond_broadcast(cond) \ pthread_cond_broadcast (&cond) #ifndef NDEBUG #define _svmm_set_instance(inst) \ env->mtrace.instance[env->mtrace.lastopno] = inst; \ if (env->mtrace.globalno[env->mtrace.lastopno] < MX_GLOBAL_TRACE_NO) \ { env->vm->mtrace.instance[env->mtrace.globalno[env->mtrace.lastopno]] \ = inst; } #define _svmm_register_operation(oper, inst) \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = NULL; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = oper; \ env->mtrace.instance[env->mtrace.lastopno] = inst; \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ int no = env->mtrace.globalno[env->mtrace.lastopno]; \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = NULL; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = oper; \ env->vm->mtrace.instance[no] = inst; \ env->vm->mtrace.opdone[no] = 1; } */ #define _svmm_register_instance(inst) \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = NULL; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = -1; \ env->mtrace.instance[env->mtrace.lastopno] = inst; \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ int no = env->mtrace.globalno[env->mtrace.lastopno]; \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = NULL; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = -1; \ env->vm->mtrace.instance[no] = inst; \ env->vm->mtrace.opdone[no] = 1; } */ #define _svmm_register_gc() \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = NULL; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 'g'; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ int no = env->mtrace.globalno[env->mtrace.lastopno]; \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = NULL; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 'g'; \ env->vm->mtrace.instance[no] = NULL; \ env->vm->mtrace.opdone[no] = 1; } */ #define _svmm_mutex_lock_v(mutex) \ { \ pthread_mutex_t *_svmx_pmutex = &mutex; \ THD4("MX_LCK %d [%s:%s:%i]", _svmx_pmutex, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = _svmx_pmutex; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 1; \ env->mtrace.opdone[env->mtrace.lastopno] = 0; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ \ /* { int no = env->mtrace.globalno[env->mtrace.lastopno]; \ if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = _svmx_pmutex; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 1; \ env->vm->mtrace.opdone[no] = 0; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_mutex_lock (_svmx_pmutex); \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (no <= MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.opdone[no] = 1; } \ _svmm_count_inc("mlock"); } */ #define _svmm_mutex_lock_name(varname) \ { THD4("MX_LCK %d [%s:%s:%i]", varname, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = varname; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 1; \ env->mtrace.opdone[env->mtrace.lastopno] = 0; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ \ /* { int no = env->mtrace.globalno[env->mtrace.lastopno]; \ if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = varname; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 1; \ env->vm->mtrace.opdone[no] = 0; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_mutex_lock (varname); \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (no <= MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.opdone[no] = 1; } \ _svmm_count_inc("mlock"); } */ } #define _svmm_mutex_unlock_v() \ THD4("MX_UNL %d [%s:%s:%i]", _svmx_pmutex, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = _svmx_pmutex; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 0; \ env->mtrace.opdone[env->mtrace.lastopno] = 0; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ \ /* { int no = env->mtrace.globalno[env->mtrace.lastopno]; \ if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = _svmx_pmutex; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 0; \ env->vm->mtrace.opdone[no] = 0; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_mutex_unlock (_svmx_pmutex); \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (no <= MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.opdone[no] = 1; } \ _svmm_count_inc("munlock"); } */ \ } #define _svmm_mutex_unlock_name(varname) \ THD4("MX_UNL %d [%s:%s:%i]", varname, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = varname; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 0; \ env->mtrace.opdone[env->mtrace.lastopno] = 0; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ \ /* { int no = env->mtrace.globalno[env->mtrace.lastopno]; \ if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = varname; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 0; \ env->vm->mtrace.opdone[no] = 0; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_mutex_unlock (varname); \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (no <= MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.opdone[no] = 1; } \ _svmm_count_inc("munlock"); } */ #define _svmm_cond_wait_v(cond, mutex) \ { THD5("CV_WT %d:%d [%s:%s:%i]", &cond, &mutex, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = (void*) &cond; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 2; \ env->mtrace.opdone[env->mtrace.lastopno] = 0; \ env->mtrace.instance[env->mtrace.lastopno] = \ (_svmt_object_instance*) NULL; \ \ /* { int no = env->mtrace.globalno[env->mtrace.lastopno]; \ if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = (void*) &cond; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 2; \ env->vm->mtrace.opdone[no] = 0; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_cond_wait (&cond, &mutex); \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (no <= MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.opdone[no] = 1; } \ _svmm_count_inc("condwait"); } */ } #define _svmm_cond_wait_name(cond, varname) \ { THD5("CV_WT %d:%d [%s:%s:%i]", &cond, &mutex, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = (void*) &cond; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 2; \ env->mtrace.opdone[env->mtrace.lastopno] = 0; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ \ /* { int no = env->mtrace.globalno[env->mtrace.lastopno]; \ if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = (void*) &cond; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 2; \ env->vm->mtrace.opdone[no] = 0; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_cond_wait (&cond, varname); \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (no <= MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.opdone[no] = 1; } \ _svmm_count_inc("waitname"); } */ } #define _svmm_cond_timedwait(cond, mutex, abstime) \ { THD5("CV_TWT %d:%d [%s:%s:%i]", &cond, &mutex, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = (void*) &cond; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 2; \ env->mtrace.opdone[env->mtrace.lastopno] = 0; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ \ /* { int no = env->mtrace.globalno[env->mtrace.lastopno]; \ if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = (void*) &cond; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 2; \ env->vm->mtrace.opdone[no] = 0; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_cond_timedwait (&cond, &mutex, &abstime); \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ /* if (no <= MX_GLOBAL_TRACE_NO) { \ env->vm->mtrace.opdone[no] = 1; } \ _svmm_count_inc("condwait"); } */ } #define _svmm_cond_signal_v(__env, cond) \ { THD4("CV_SIG %d [%s:%s:%i]", &cond, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = (void*) &cond; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 3; \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ \ /* if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ int no = env->mtrace.globalno[env->mtrace.lastopno]; \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = (void*) &cond; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 3; \ env->vm->mtrace.opdone[no] = 1; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_cond_signal (&cond); \ _svmm_count_inc("condsig"); } #define _svmm_cond_broadcast_v(__env, cond) \ { THD4("CV_BRC %d [%s:%s:%i]", &cond, \ __FILE__, __func__, __LINE__); \ env->mtrace.lastopno = (env->mtrace.lastopno + 1 ) % MX_TRACE_NO; \ env->mtrace.ptr[env->mtrace.lastopno] = (void*) &cond; \ env->mtrace.globalno[env->mtrace.lastopno] = \ ++env->vm->mutex_lastopno; \ env->mtrace.file[env->mtrace.lastopno] = __FILE__; \ env->mtrace.line[env->mtrace.lastopno] = __LINE__; \ env->mtrace.lockop[env->mtrace.lastopno] = 3; \ env->mtrace.opdone[env->mtrace.lastopno] = 1; \ env->mtrace.instance[env->mtrace.lastopno] = NULL; \ \ /* if (env->vm->mutex_lastopno < MX_GLOBAL_TRACE_NO) { \ int no = env->mtrace.globalno[env->mtrace.lastopno]; \ env->vm->mtrace.thread_id[no] = env->thread.id; \ env->vm->mtrace.ptr[no] = (void*) &cond; \ env->vm->mtrace.file[no] = __FILE__; \ env->vm->mtrace.line[no] = __LINE__; \ env->vm->mtrace.lockop[no] = 3; \ env->vm->mtrace.opdone[no] = 1; \ env->vm->mtrace.instance[no] = NULL; } */ \ \ pthread_cond_broadcast (&cond); \ _svmm_count_inc("broadsig"); } #else /* !NDEBUG */ #define _svmm_set_instance(inst) #define _svmm_register_operation(oper, inst) #define _svmm_register_instance(inst) #define _svmm_register_gc() #define _svmm_mutex_lock_v(mutex) _svmm_mutex_lock(mutex) #define _svmm_mutex_lock_name(varname) pthread_mutex_lock (varname) #define _svmm_mutex_unlock_v() _svmm_mutex_unlock() #define _svmm_mutex_unlock_name(varname) pthread_mutex_unlock (varname) #define _svmm_cond_wait_v(cond, mutex) _svmm_cond_wait(cond, mutex) #define _svmm_cond_wait_name(cond, varname) \ pthread_cond_wait (&cond, varname) #define _svmm_cond_timedwait(cond, mutex, abstime) \ pthread_cond_timedwait (&cond, &mutex, &abstime) #define _svmm_cond_signal_v(__env, cond) _svmm_cond_signal(cond) #define _svmm_cond_broadcast_v(__env, cond) _svmm_cond_broadcast(cond) #endif /* !NDEBUG */ #define _svmm_cond_broadcast_ptr(cond) \ pthread_cond_broadcast (cond) #define _svmm_kill(thread, signal) \ pthread_kill (thread, signal) #define _svmm_enter_object_monitor_non_blocking(env, instance, succeeded) \ _svmh_enter_object_monitor_non_blocking (env, instance, &succeeded) #define _svmm_assert_free_body(fbody) \ { assert(*fbody->body.jobject == NULL); \ assert(fbody->body.owner == NULL); \ assert(fbody->body.list_blocked_head == NULL); \ assert(fbody->body.list_blocked_tail == NULL); \ assert(fbody->body.list_wait_head == NULL); \ assert(fbody->body.list_wait_tail == NULL); } #define _svmm_swap_thread_bodies(t1,t2) \ { _svmt_JNIEnv *ttt = t1->locking.encloses; \ THD4("swap t1(b1) <=> t2(b2) : %i(%i) <=> %i(%i)", \ t1->thread.id, t1->locking.encloses->thread.id, \ t2->thread.id, t2->locking.encloses->thread.id); \ assert (t1 == t1->locking.encloses->body.encloser); \ assert (t2 == t2->locking.encloses->body.encloser); \ t1->locking.encloses = t2->locking.encloses; \ t2->locking.encloses = ttt; \ ttt = t1->locking.encloses->body.encloser; \ t1->locking.encloses->body.encloser = \ t2->locking.encloses->body.encloser; \ t2->locking.encloses->body.encloser = ttt; \ _svmm_count_inc("swapbd"); } #ifndef NDEBUG #define _svmm_assert_not_encloser(inst) \ _svmh_assert_not_encloser(env, inst, __FILE__, __LINE__) #else #define _svmm_assert_not_encloser(inst) #endif static _svmt_JNIEnv *_svmf_get_current_env (void); #endif /* not SVM_THREAD_H */