+2004-10-28 Rhys Weatherley <rweather@southern-storm.com.au>
+
+ * 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 <evin@users.sourceforge.net>
* jit/jit-rules-x86.c (output_branch): correct the offset
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],
{
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;
*/
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;
/*
* 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.
*/
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.
{
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;
dbg->events = event;
}
dbg->last_event = event;
- wakeup_all(dbg);
+ jit_monitor_signal(&(dbg->queue_lock));
+ jit_monitor_unlock(&(dbg->queue_lock));
}
/*@
@*/
int jit_debugging_possible(void)
{
- /* TODO */
- return 1;
+ return JIT_THREADS_SUPPORTED;
}
/*@
}
dbg->context = context;
context->debugger = dbg;
+ jit_monitor_create(&(dbg->queue_lock));
+ jit_monitor_create(&(dbg->run_lock));
return dbg;
}
else
@*/
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;
}
/*@
(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;
+ }
}
/*@
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);
}
/*@
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;
}
/*@
*/
#include "jit-internal.h"
+#if TIME_WITH_SYS_TIME
+ #include <sys/time.h>
+ #include <time.h>
+#else
+ #if HAVE_SYS_TIME_H
+ #include <sys/time.h>
+ #elif !defined(__palmos__)
+ #include <time.h>
+ #endif
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <errno.h>
#if defined(JIT_THREADS_PTHREAD)
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 */
/*
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
+}
#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
/*
#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