From: Rhys Weatherley Date: Thu, 28 Oct 2004 01:23:08 +0000 (+0000) Subject: Implement some of the locking code for the debugging API. X-Git-Tag: r.0.0.6~32 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=7e107abaf2cbedd33073e2b5e14bd4ede4ba860a;p=francis%2Flibjit.git Implement some of the locking code for the debugging API. --- diff --git a/ChangeLog b/ChangeLog index b357014..e148e97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,10 @@ +2004-10-28 Rhys Weatherley + + * configure.in, jit/jit-debugger.c, jit/jit-thread.c, + jit/jit-thread.h: implement some of the locking code + for the debugging API. + 2004-10-12 Evin Robertson * jit/jit-rules-x86.c (output_branch): correct the offset diff --git a/configure.in b/configure.in index ad77139..bd97aab 100644 --- a/configure.in +++ b/configure.in @@ -93,6 +93,7 @@ AC_HEADER_STDC AC_CHECK_HEADERS(string.h strings.h memory.h stdlib.h stdarg.h varargs.h) AC_CHECK_HEADERS(tgmath.h math.h ieeefp.h pthread.h unistd.h sys/types.h) AC_CHECK_HEADERS(sys/mman.h fcntl.h dlfcn.h sys/cygwin.h sys/stat.h) +AC_CHECK_HEADERS(time.h sys/time.h) dnl A macro that helps detect the size of types in a cross-compile environment. AC_DEFUN([AC_COMPILE_CHECK_SIZEOF], diff --git a/jit/jit-debugger.c b/jit/jit-debugger.c index b677290..45d71c5 100644 --- a/jit/jit-debugger.c +++ b/jit/jit-debugger.c @@ -154,6 +154,7 @@ typedef struct jit_debugger_thread { struct jit_debugger_thread *next; jit_debugger_thread_id_t id; + jit_thread_id_t native_id; int volatile run_type; jit_function_t find_func; jit_nint last_data1; @@ -167,6 +168,8 @@ typedef struct jit_debugger_thread */ struct jit_debugger { + jit_monitor_t queue_lock; + jit_monitor_t run_lock; jit_context_t context; jit_debugger_linked_event_t * volatile events; jit_debugger_linked_event_t * volatile last_event; @@ -175,18 +178,12 @@ struct jit_debugger /* * Lock the debugger object. */ -static void lock_debugger(jit_debugger_t dbg) -{ - /* TODO */ -} +#define lock_debugger(dbg) jit_monitor_lock(&((dbg)->run_lock)) /* * Unlock the debugger object. */ -static void unlock_debugger(jit_debugger_t dbg) -{ - /* TODO */ -} +#define unlock_debugger(dbg) jit_monitor_unlock(&((dbg)->run_lock)) /* * Suspend the current thread until it is marked as running again. @@ -194,16 +191,16 @@ static void unlock_debugger(jit_debugger_t dbg) */ static void suspend_thread(jit_debugger_t dbg, jit_debugger_thread_t thread) { - /* TODO */ + while(thread->run_type == JIT_RUN_TYPE_STOPPED) + { + jit_monitor_wait(&(dbg->run_lock), -1); + } } /* * Wake all threads that are waiting on the debugger's monitor. */ -static void wakeup_all(jit_debugger_t dbg) -{ - /* TODO */ -} +#define wakeup_all(dbg) jit_monitor_signal_all(&((dbg)->run_lock)) /* * Get the information block for the current thread. @@ -238,6 +235,7 @@ static void add_event(jit_debugger_t dbg, jit_debugger_event_t *_event) { jit_debugger_linked_event_t *event = (jit_debugger_linked_event_t *)_event; event->next = 0; + jit_monitor_lock(&(dbg->queue_lock)); if(dbg->last_event) { dbg->last_event->next = event; @@ -247,7 +245,8 @@ static void add_event(jit_debugger_t dbg, jit_debugger_event_t *_event) dbg->events = event; } dbg->last_event = event; - wakeup_all(dbg); + jit_monitor_signal(&(dbg->queue_lock)); + jit_monitor_unlock(&(dbg->queue_lock)); } /*@ @@ -258,8 +257,7 @@ static void add_event(jit_debugger_t dbg, jit_debugger_event_t *_event) @*/ int jit_debugging_possible(void) { - /* TODO */ - return 1; + return JIT_THREADS_SUPPORTED; } /*@ @@ -285,6 +283,8 @@ jit_debugger_t jit_debugger_create(jit_context_t context) } dbg->context = context; context->debugger = dbg; + jit_monitor_create(&(dbg->queue_lock)); + jit_monitor_create(&(dbg->run_lock)); return dbg; } else @@ -348,8 +348,11 @@ jit_debugger_t jit_debugger_from_context(jit_context_t context) @*/ jit_debugger_thread_id_t jit_debugger_get_self(jit_debugger_t dbg) { - /* TODO */ - return 0; + jit_thread_id_t id = jit_thread_self(); + jit_debugger_thread_id_t thread; + thread = jit_debugger_get_thread(dbg, &id); + jit_thread_release_self(id); + return thread; } /*@ @@ -380,8 +383,20 @@ int jit_debugger_get_native_thread (jit_debugger_t dbg, jit_debugger_thread_id_t thread, void *native_thread) { - /* TODO */ - return 0; + jit_debugger_thread_t th; + lock_debugger(dbg); + th = get_specific_thread(dbg, thread); + if(th) + { + jit_memcpy(native_thread, &(th->native_id), sizeof(th->native_id)); + unlock_debugger(dbg); + return 1; + } + else + { + unlock_debugger(dbg); + return 0; + } } /*@ @@ -398,7 +413,16 @@ int jit_debugger_get_native_thread void jit_debugger_set_breakable (jit_debugger_t dbg, const void *native_thread, int flag) { - /* TODO */ + jit_debugger_thread_t th; + jit_debugger_thread_id_t id; + id = jit_debugger_get_thread(dbg, native_thread); + lock_debugger(dbg); + th = get_specific_thread(dbg, id); + if(th) + { + th->breakable = flag; + } + unlock_debugger(dbg); } /*@ @@ -479,8 +503,26 @@ void jit_debugger_detach_self(jit_debugger_t dbg) int jit_debugger_wait_event (jit_debugger_t dbg, jit_debugger_event_t *event, jit_int timeout) { - /* TODO */ - return 0; + jit_debugger_linked_event_t *levent; + jit_monitor_lock(&(dbg->queue_lock)); + if((levent = dbg->events) == 0) + { + if(!jit_monitor_wait(&(dbg->queue_lock), timeout)) + { + jit_monitor_unlock(&(dbg->queue_lock)); + return 0; + } + levent = dbg->events; + } + *event = levent->event; + dbg->events = levent->next; + if(!(levent->next)) + { + dbg->last_event = 0; + } + jit_free(levent); + jit_monitor_unlock(&(dbg->queue_lock)); + return 1; } /*@ diff --git a/jit/jit-thread.c b/jit/jit-thread.c index aceb660..a013528 100644 --- a/jit/jit-thread.c +++ b/jit/jit-thread.c @@ -19,6 +19,20 @@ */ #include "jit-internal.h" +#if TIME_WITH_SYS_TIME + #include + #include +#else + #if HAVE_SYS_TIME_H + #include + #elif !defined(__palmos__) + #include + #endif +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include #if defined(JIT_THREADS_PTHREAD) @@ -53,6 +67,15 @@ static void init_win32_thread(void) control_key = TlsAlloc(); } +jit_thread_id_t _jit_thread_self(void) +{ + HANDLE new_handle; + DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &new_handle, + 0, 0, DUPLICATE_SAME_ACCESS); + return new_handle; +} + #else /* No thread package */ /* @@ -126,3 +149,53 @@ jit_thread_id_t _jit_thread_current_id(void) return 1; #endif } + +int _jit_monitor_wait(jit_monitor_t *mon, jit_int timeout) +{ +#if defined(JIT_THREADS_PTHREAD) + if(timeout < 0) + { + pthread_cond_wait(&(mon->_cond), &(mon->_mutex)); + return 1; + } + else + { + struct timeval tv; + struct timespec ts; + int result; + + gettimeofday(&tv, 0); + ts.tv_sec = tv.tv_sec + (long)(timeout / 1000); + ts.tv_nsec = (tv.tv_usec + (long)((timeout % 1000) * 1000)) * 1000L; + if(ts.tv_nsec >= 1000000000L) + { + ++(ts.tv_sec); + ts.tv_nsec -= 1000000000L; + } + + /* Wait until we are signalled or the timeout expires */ + do + { + result = pthread_cond_timedwait(&(mon->_cond), &(mon->_mutex), &ts); + } + while(result == EINTR); + return ((result == 0) ? 1 : 0); + } +#elif defined(JIT_THREADS_WIN32) + DWORD result; + ++(mon->_waiting); + if(timeout >= 0) + { + result = SignalObjectAndWait(mon->_mutex, mon->_cond, + (DWORD)timeout, FALSE); + } + else + { + result = SignalObjectAndWait(mon->_mutex, mon->_cond, INFINITE, FALSE); + } + WaitForSingleObject(mon->_mutex, INFINITE); + return (result == WAIT_OBJECT_0); +#else + return 0; +#endif +} diff --git a/jit/jit-thread.h b/jit/jit-thread.h index 3737cd8..b38da04 100644 --- a/jit/jit-thread.h +++ b/jit/jit-thread.h @@ -51,12 +51,19 @@ extern "C" { #if defined(JIT_THREADS_PTHREAD) typedef pthread_t jit_thread_id_t; #define jit_thread_id_equal(x,y) (pthread_equal((x), (y))) +#define jit_thread_self() (pthread_self()) +#define jit_thread_release_self(t) do { ; } while (0) #elif defined(JIT_THREADS_WIN32) typedef HANDLE jit_thread_id_t; #define jit_thread_id_equal(x,y) ((x) == (y)) +jit_thread_id_t _jit_thread_self(void); +#define jit_thread_self() _jit_thread_self() +#define jit_thread_release_self(t) CloseHandle((t)) #else typedef int jit_thread_id_t; #define jit_thread_id_equal(x,y) ((x) == (y)) +#define jit_thread_self() 1 +#define jit_thread_release_self(t) do { ; } while (0) #endif /* @@ -108,6 +115,104 @@ typedef int jit_mutex_t; #endif +/* + * Define the primitive monitor operations. + */ + +#if defined(JIT_THREADS_PTHREAD) + +typedef struct +{ + pthread_mutex_t _mutex; + pthread_cond_t _cond; + +} jit_monitor_t; +#define jit_monitor_create(mon) \ + do { \ + pthread_mutex_init(&((mon)->_mutex), 0); \ + pthread_cond_init(&((mon)->_cond), 0); \ + } while (0) +#define jit_monitor_destroy(mon) \ + do { \ + pthread_cond_destroy(&((mon)->_cond)); \ + pthread_mutex_destroy(&((mon)->_mutex)); \ + } while (0) +#define jit_monitor_lock(mon) \ + do { \ + pthread_mutex_lock(&((mon)->_mutex)); \ + } while (0) +#define jit_monitor_unlock(mon) \ + do { \ + pthread_mutex_unlock(&((mon)->_mutex)); \ + } while (0) +#define jit_monitor_signal(mon) \ + do { \ + pthread_cond_signal(&((mon)->_cond)); \ + } while (0) +#define jit_monitor_signal_all(mon) \ + do { \ + pthread_cond_broadcast(&((mon)->_cond)); \ + } while (0) + +#elif defined(JIT_THREADS_WIN32) + +typedef struct +{ + HANDLE _mutex; + HANDLE _cond; + LONG volatile _waiting; +} jit_monitor_t; +#define jit_monitor_create(mon) \ + do { \ + (mon)->_mutex = CreateMutex(NULL, FALSE, NULL); \ + (mon)->_cond = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL); \ + (mon)->_waiting = 0; \ + } while (0) +#define jit_monitor_destroy(mon) \ + do { \ + CloseHandle((mon)->_cond); \ + CloseHandle((mon)->_mutex); \ + } while (0) +#define jit_monitor_lock(mon) \ + do { \ + WaitForSingleObject((mon)->_mutex, INFINITE); \ + } while (0) +#define jit_monitor_unlock(mon) \ + do { \ + ReleaseMutex((mon)->_mutex); \ + } while (0) +#define jit_monitor_signal(mon) \ + do { \ + if((mon)->_waiting > 0) \ + { \ + --((mon)->_waiting); \ + ReleaseSemaphore((mon)->_cond, 1, NULL); \ + } \ + } while (0) +#define jit_monitor_signal_all(mon) \ + do { \ + LONG _count = (mon)->_waiting; \ + if(_count > 0) \ + { \ + (mon)->_waiting = 0; \ + ReleaseSemaphore((mon)->_cond, _count, NULL); \ + } \ + } while (0) + +#else + +typedef int jit_monitor_t; +#define jit_monitor_create(mon) do { ; } while (0) +#define jit_monitor_destroy(mon) do { ; } while (0) +#define jit_monitor_lock(mon) do { ; } while (0) +#define jit_monitor_unlock(mon) do { ; } while (0) +#define jit_monitor_signal(mon) do { ; } while (0) +#define jit_monitor_signal_all(mon) do { ; } while (0) + +#endif +int _jit_monitor_wait(jit_monitor_t *mon, jit_int timeout); +#define jit_monitor_wait(mon,timeout) _jit_monitor_wait((mon), (timeout)) + #ifdef __cplusplus }; #endif