commit e5d2c04761eb5ceeab645971d55e26efd8f8c0e0
parent 9ad9c4bd442cca8f5bce81653f785480287f30e6
Author: Andres Navarro <canavarro82@gmail.com>
Date: Wed, 22 Aug 2012 02:44:32 -0300
Modified the GIL to be reentrant (still uses a simple mutex, the number of times the lock was acquired is kept in the klisp_State struct).
Diffstat:
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/src/klimits.h b/src/klimits.h
@@ -89,8 +89,28 @@
/* XXX for now ignore the return values */
#ifndef klisp_lock
#include <pthread.h>
-#define klisp_lock(K) ((void) (pthread_mutex_lock(&G(K)->gil)))
-#define klisp_unlock(K) ((void) (pthread_mutex_unlock(&G(K)->gil)))
+#define klisp_lock(K) ({ \
+ if (K->gil_count == 0) { \
+ K->gil_count = 1; \
+ UNUSED(pthread_mutex_lock(&G(K)->gil)); \
+ } else { \
+ ++K->gil_count; \
+ }})
+
+#define klisp_unlock(K) ({ \
+ if (K->gil_count <= 1) { \
+ K->gil_count = 0; \
+ UNUSED(pthread_mutex_unlock(&G(K)->gil)); \
+ } else { \
+ --K->gil_count; \
+ }})
+
+#define klisp_unlock_all(K) ({ \
+ if (K->gil_count > 0) { \
+ K->gil_count = 1; \
+ klisp_unlock(K); \
+ }})
+
#endif
/* These were the original defines */
diff --git a/src/kstate.c b/src/kstate.c
@@ -98,7 +98,8 @@ static void f_klispopen (klisp_State *K, void *ud) {
static void preinit_state (klisp_State *K, global_State *g) {
G(K) = g;
-
+
+ K->gil_count = 0;
K->curr_cont = KNIL;
K->next_obj = KINERT;
K->next_func = NULL;
diff --git a/src/kstate.h b/src/kstate.h
@@ -131,7 +131,9 @@ typedef struct global_State {
/* The main thread */
klisp_State *mainthread;
/* The GIL (Global Interpreter Lock) */
- /* (at least for now) we'll use a non recursive mutex */
+ /* This is a regular mutex, but we use it to emulate a recursive one.
+ The number of times the lock was acquired is maintained in the
+ locking thread in gil_count */
pthread_mutex_t gil;
} global_State;
@@ -139,6 +141,7 @@ struct klisp_State {
CommonHeader; /* This represents a thread object */
global_State *k_G;
/* Current state of execution */
+ int32_t gil_count; /* the number of times the GIL was acquired */
TValue curr_cont; /* the current continuation of this thread */
/*
** If next_env is NIL, then the next_func is from a continuation