Author: mladen.turk(a)jboss.com
Date: 2007-10-09 07:41:45 -0400 (Tue, 09 Oct 2007)
New Revision: 1092
Modified:
trunk/sight/java/org/jboss/sight/NativeObject.java
trunk/sight/java/org/jboss/sight/Pool.java
trunk/sight/native/include/sight_local.h
trunk/sight/native/share/dir.c
trunk/sight/native/share/file.c
trunk/sight/native/share/finfo.c
trunk/sight/native/share/library.c
trunk/sight/native/share/no.c
Log:
Use thread locks instead atomics for pool GC
Modified: trunk/sight/java/org/jboss/sight/NativeObject.java
===================================================================
--- trunk/sight/java/org/jboss/sight/NativeObject.java 2007-10-06 09:53:30 UTC (rev 1091)
+++ trunk/sight/java/org/jboss/sight/NativeObject.java 2007-10-09 11:41:45 UTC (rev 1092)
@@ -41,7 +41,8 @@
private static native long alloc()
throws OutOfMemoryError;
private static native void init0(NativeObject thiz,
- long instance, long parent)
+ long instance, long parent,
+ boolean lockable)
throws OutOfMemoryError;
private static native void free0(long instance);
private static native void clear0(long instance);
@@ -65,16 +66,30 @@
* pool. If it is non-zero, the new pool will inherit all
* of its parent pool's attributes, except the apr_pool_t will
* be a sub-pool.
+ * @param lockable Defines if the created object can have child objects
*/
- protected NativeObject(long parent)
+ protected NativeObject(long parent, boolean lockable)
throws OutOfMemoryError
{
POOL = 0;
INSTANCE = alloc();
- init0(this, INSTANCE, parent);
+ init0(this, INSTANCE, parent, lockable);
}
/**
+ * Create new NativeObject
+ * @param parent The parent pool. If this is 0, the new pool is a root
+ * pool. If it is non-zero, the new pool will inherit all
+ * of its parent pool's attributes, except the apr_pool_t will
+ * be a sub-pool.
+ */
+ protected NativeObject(long parent)
+ throws OutOfMemoryError
+ {
+ this(parent, false);
+ }
+
+ /**
* Interrupt the pending native operation.
*/
public void interrupt()
@@ -87,9 +102,11 @@
*/
public void destroy()
{
- free0(INSTANCE);
- INSTANCE = 0;
- POOL = 0;
+ synchronized(this) {
+ free0(INSTANCE);
+ INSTANCE = 0;
+ POOL = 0;
+ }
}
/**
@@ -97,7 +114,9 @@
*/
public void clear()
{
- clear0(INSTANCE);
+ synchronized(this) {
+ clear0(INSTANCE);
+ }
}
/**
Modified: trunk/sight/java/org/jboss/sight/Pool.java
===================================================================
--- trunk/sight/java/org/jboss/sight/Pool.java 2007-10-06 09:53:30 UTC (rev 1091)
+++ trunk/sight/java/org/jboss/sight/Pool.java 2007-10-09 11:41:45 UTC (rev 1092)
@@ -45,7 +45,7 @@
*/
public Pool()
{
- super(0);
+ super(0, true);
}
/**
@@ -57,7 +57,7 @@
*/
public Pool(Pool parent)
{
- super(parent.POOL);
+ super(parent.POOL, true);
}
protected void onDestroy()
Modified: trunk/sight/native/include/sight_local.h
===================================================================
--- trunk/sight/native/include/sight_local.h 2007-10-06 09:53:30 UTC (rev 1091)
+++ trunk/sight/native/include/sight_local.h 2007-10-09 11:41:45 UTC (rev 1092)
@@ -361,7 +361,10 @@
/* XXX : BSD as more */
} sight_procstate_e;
-apr_status_t sight_create_pool(apr_pool_t **, apr_pool_t *);
+apr_status_t sight_pool_create(apr_pool_t **, apr_pool_t *, int);
+apr_status_t sight_pool_clear(apr_pool_t *);
+apr_status_t sight_pool_lock(apr_thread_mutex_t **, apr_pool_t *);
+apr_status_t sight_pool_lock_parent(apr_thread_mutex_t **, apr_pool_t *);
jobjectArray sight_new_cc_array(JNIEnv *, sight_cclass_e, jsize);
jbyteArray sight_new_byte_array(JNIEnv *, jbyte *, jsize);
@@ -381,20 +384,23 @@
#define SIGHT_GLOBAL_TRY if (apr_atomic_inc32(sight_global_atomic))
#define SIGHT_GLOBAL_END() apr_atomic_dec32(sight_global_atomic)
#define SIGHT_GLOBAL_BRK() apr_atomic_dec32(sight_global_atomic)
-#define SIGHT_LOCAL_TRY(N) { apr_uint32_t _SGATOM =
apr_atomic_inc32(sight_global_atomic); \
- if ((N)) apr_atomic_inc32(&(N)->refcount);
\
- if ((N) && _SGATOM)
-#define SIGHT_LOCAL_END(N) apr_atomic_dec32(&(N)->refcount); }
apr_atomic_dec32(sight_global_atomic)
-#define SIGHT_LOCAL_BRK(N) apr_atomic_dec32(&(N)->refcount);
apr_atomic_dec32(sight_global_atomic)
+/* More then 256 references is insane */
+#define SIGHT_MAXLREF 256
+#define SIGHT_LOCAL_TRY(N) if ((N) && apr_atomic_inc32(&(N)->refcount)
< SIGHT_MAXLREF) { \
+ if (apr_atomic_read32(&(N)->interrupted) == 0)
+
+#define SIGHT_LOCAL_END(N) } if ((N)) apr_atomic_dec32(&(N)->refcount)
+#define SIGHT_LOCAL_BRK(N) apr_atomic_dec32(&(N)->refcount)
+
#else
#define SIGHT_GLOBAL_TRY
-#define SIGHT_GLOBAL_END()
-#define SIGHT_GLOBAL_BRK()
+#define SIGHT_GLOBAL_END() (void)0
+#define SIGHT_GLOBAL_BRK() (void)0
#define SIGHT_LOCAL_TRY(N) if ((N))
-#define SIGHT_LOCAL_END(N)
-#define SIGHT_LOCAL_BRK(N)
+#define SIGHT_LOCAL_END(N) (void)0
+#define SIGHT_LOCAL_BRK(N) (void)0
#endif /* SIGHT_APR_REFCOUNT */
Modified: trunk/sight/native/share/dir.c
===================================================================
--- trunk/sight/native/share/dir.c 2007-10-06 09:53:30 UTC (rev 1091)
+++ trunk/sight/native/share/dir.c 2007-10-09 11:41:45 UTC (rev 1092)
@@ -159,7 +159,7 @@
UNREFERENCED_O;
SIGHT_GLOBAL_TRY {
- if ((rv = sight_create_pool(&p, sight_temp_pool)) != APR_SUCCESS) {
+ if ((rv = apr_pool_create(&p, sight_temp_pool)) != APR_SUCCESS) {
throwAprException(_E, rv);
SIGHT_GLOBAL_BRK();
goto cleanup;
Modified: trunk/sight/native/share/file.c
===================================================================
--- trunk/sight/native/share/file.c 2007-10-06 09:53:30 UTC (rev 1091)
+++ trunk/sight/native/share/file.c 2007-10-09 11:41:45 UTC (rev 1092)
@@ -30,6 +30,7 @@
#include "sight_types.h"
extern apr_pool_t *sight_global_pool;
+extern apr_pool_t *sight_temp_pool;
static void file_cleanup(int mode, sight_object_t *no)
{
@@ -497,23 +498,25 @@
SIGHT_ALLOC_CSTRING(name);
UNREFERENCED_O;
- if (!sight_global_pool) {
- throwNullPointerException(_E, THROW_FMARK,
- sight_strerror(SIGHT_ENOPOOL));
- rv = APR_ENOPOOL;
- goto cleanup;
- }
- if ((rv = apr_pool_create(&p, sight_global_pool)) != APR_SUCCESS) {
- throwAprException(_E, rv);
- p = NULL;
- goto cleanup;
- }
- rv = apr_file_attrs_set(J2S(name), fa, fm, p);
- if (rv != APR_SUCCESS)
- throwAprException(_E, rv);
-cleanup:
- if (sight_global_pool && p)
- apr_pool_destroy(p);
+ SIGHT_GLOBAL_TRY {
+ if (!sight_temp_pool) {
+ throwNullPointerException(_E, THROW_FMARK,
+ sight_strerror(SIGHT_ENOPOOL));
+ rv = APR_ENOPOOL;
+ goto cleanup;
+ }
+ if ((rv = apr_pool_create(&p, sight_temp_pool)) != APR_SUCCESS) {
+ throwAprException(_E, rv);
+ p = NULL;
+ goto cleanup;
+ }
+ rv = apr_file_attrs_set(J2S(name), fa, fm, p);
+ if (rv != APR_SUCCESS)
+ throwAprException(_E, rv);
+ cleanup:
+ if (sight_temp_pool && p)
+ apr_pool_destroy(p);
+ } SIGHT_GLOBAL_END();
SIGHT_FREE_CSTRING(name);
return rv;
}
Modified: trunk/sight/native/share/finfo.c
===================================================================
--- trunk/sight/native/share/finfo.c 2007-10-06 09:53:30 UTC (rev 1091)
+++ trunk/sight/native/share/finfo.c 2007-10-09 11:41:45 UTC (rev 1092)
@@ -206,8 +206,8 @@
SIGHT_ALLOC_CSTRING(name);
SIGHT_GLOBAL_TRY {
- if ((rv = sight_create_pool(&p, sight_temp_pool)) != APR_SUCCESS) {
- throwAprException(_E, rv);
+ if ((rv = apr_pool_create(&p, sight_temp_pool)) != APR_SUCCESS) {
+ throwAprMemoryException(_E, THROW_FMARK, rv);
}
else {
memset(&info, 0, sizeof(apr_finfo_t));
Modified: trunk/sight/native/share/library.c
===================================================================
--- trunk/sight/native/share/library.c 2007-10-06 09:53:30 UTC (rev 1091)
+++ trunk/sight/native/share/library.c 2007-10-09 11:41:45 UTC (rev 1092)
@@ -168,14 +168,12 @@
sight_unload_classes(_E);
return JNI_FALSE;
}
- if (apr_pool_create(&sight_global_pool, NULL) != APR_SUCCESS) {
+ if (sight_pool_create(&sight_global_pool, NULL, 1) != APR_SUCCESS) {
return JNI_FALSE;
}
- if (apr_pool_create(&sight_temp_pool, NULL) != APR_SUCCESS) {
+ if (sight_pool_create(&sight_temp_pool, NULL, 1) != APR_SUCCESS) {
return JNI_FALSE;
}
- apr_pool_tag(sight_global_pool, "sight_global_pool");
- apr_pool_tag(sight_temp_pool, "sight_temp_pool");
if (apr_thread_mutex_create(&sight_global_mutex,
APR_THREAD_MUTEX_DEFAULT,
@@ -184,6 +182,7 @@
}
apr_atomic_init(sight_global_pool);
if (sight_main(sight_global_pool) != APR_SUCCESS) {
+ apr_pool_destroy(sight_temp_pool);
apr_pool_destroy(sight_global_pool);
sight_global_pool = NULL;
sight_unload_classes(_E);
@@ -193,23 +192,89 @@
return JNI_TRUE;
}
-apr_status_t sight_create_pool(apr_pool_t **pool, apr_pool_t *parent)
+apr_status_t sight_pool_create(apr_pool_t **pool, apr_pool_t *parent,
+ int lockable)
{
+ apr_status_t rc;
apr_allocator_t *allocator = NULL;
- apr_status_t rc;
+ apr_thread_mutex_t *mutex = NULL;
- *pool = NULL;
- if ((rc = apr_allocator_create(&allocator)) != APR_SUCCESS) {
+ if ((rc = apr_allocator_create(&allocator)) != APR_SUCCESS)
return rc;
- }
- if ((rc = apr_pool_create_ex(pool, parent,
- NULL, allocator)) != APR_SUCCESS) {
+
+ if ((rc = apr_pool_create_ex(pool, parent, NULL,
+ allocator)) != APR_SUCCESS) {
+ apr_allocator_destroy(allocator);
return rc;
}
+ if (lockable) {
+ if ((rc = apr_thread_mutex_create(&mutex,
+ APR_THREAD_MUTEX_DEFAULT,
+ *pool)) != APR_SUCCESS) {
+ apr_allocator_destroy(allocator);
+ *pool = NULL;
+ return rc;
+ }
+
+ }
+ else if (parent) {
+ /* Use parents allocator mutex */
+ mutex = apr_allocator_mutex_get(apr_pool_allocator_get(parent));
+ }
+ apr_allocator_mutex_set(allocator, mutex);
apr_allocator_owner_set(allocator, *pool);
return APR_SUCCESS;
}
+apr_status_t sight_pool_clear(apr_pool_t *pool)
+{
+ apr_status_t rc;
+ apr_allocator_t *allocator = apr_pool_allocator_get(pool);
+ apr_thread_mutex_t *mutex = apr_allocator_mutex_get(allocator);
+
+ apr_pool_clear(pool);
+ if (mutex) {
+ mutex = NULL;
+ if ((rc = apr_thread_mutex_create(&mutex,
+ APR_THREAD_MUTEX_DEFAULT,
+ pool)) != APR_SUCCESS) {
+ return rc;
+ }
+ }
+ apr_allocator_mutex_set(allocator, mutex);
+ return APR_SUCCESS;
+}
+
+apr_status_t sight_pool_lock(apr_thread_mutex_t **mutex, apr_pool_t *pool)
+{
+ if (pool) {
+ apr_allocator_t *allocator = apr_pool_allocator_get(pool);
+ apr_thread_mutex_t *lock;
+
+ if ((lock = apr_allocator_mutex_get(allocator))) {
+ if (mutex)
+ *mutex = lock;
+ return apr_thread_mutex_lock(lock);
+ }
+ }
+ if (mutex)
+ *mutex = NULL;
+ return APR_ENOPOOL;
+}
+
+apr_status_t sight_pool_lock_parent(apr_thread_mutex_t **mutex, apr_pool_t *pool)
+{
+ if (pool) {
+ apr_pool_t *parent = apr_pool_parent_get(pool);
+ apr_allocator_t *allocator = apr_pool_allocator_get(parent);
+
+ if ((*mutex = apr_allocator_mutex_get(allocator)) != NULL)
+ return apr_thread_mutex_lock(*mutex);
+ }
+ *mutex = NULL;
+ return APR_SUCCESS;
+}
+
static void dump_stats()
{
fprintf(stderr, "\nNativeObject statistics ......\n");
@@ -245,6 +310,9 @@
fprintf(stderr, "\nLibrary terminate ............\n");
fprintf(stderr, "Global Atomic counter : %d\n", sight_global_a);
#endif
+ sight_pool_lock(NULL, sight_temp_pool);
+ sight_pool_lock(NULL, sight_global_pool);
+
#if SIGHT_APR_REFCOUNT
/* Wait until all JNI calls are done
*/
@@ -334,6 +402,7 @@
SIGHT_EXPORT_DECLARE(void, Library, clear0)(SIGHT_STDARGS)
{
+ apr_status_t rc;
UNREFERENCED_O;
if (sight_global_pool) {
@@ -346,6 +415,9 @@
fprintf(stderr, "\nLibrary clear ................\n");
fprintf(stderr, "Global Atomic counter : %d\n", sight_global_a);
#endif
+ sight_pool_lock(NULL, sight_temp_pool);
+ sight_pool_lock(NULL, sight_global_pool);
+
#if SIGHT_APR_REFCOUNT
while (in_object_count) {
@@ -371,8 +443,15 @@
#endif
- apr_pool_clear(sight_global_pool);
+ sight_pool_clear(sight_temp_pool);
+ sight_pool_clear(sight_global_pool);
apr_atomic_set32(sight_global_atomic, 1);
+ if ((rc = apr_thread_mutex_create(&sight_global_mutex,
+ APR_THREAD_MUTEX_DEFAULT,
+ sight_global_pool)) != APR_SUCCESS) {
+ throwAprException(_E, rc);
+ return;
+ }
}
#ifdef SIGHT_DO_STATS
dump_stats();
Modified: trunk/sight/native/share/no.c
===================================================================
--- trunk/sight/native/share/no.c 2007-10-06 09:53:30 UTC (rev 1091)
+++ trunk/sight/native/share/no.c 2007-10-09 11:41:45 UTC (rev 1092)
@@ -158,13 +158,15 @@
SIGHT_EXPORT_DECLARE(void, NativeObject, init0)(SIGHT_STDARGS,
jobject thiz,
jlong instance,
- jlong parent)
+ jlong parent,
+ jboolean lock)
{
jclass c;
apr_pool_t *pool = NULL;
sight_object_t *no = J2P(instance, sight_object_t *);
- apr_pool_t *pp = J2P(parent, apr_pool_t *);
+ apr_pool_t *ppool = J2P(parent, apr_pool_t *);
apr_status_t rc;
+ apr_thread_mutex_t *mutex;
UNREFERENCED_O;
@@ -173,13 +175,19 @@
#endif
if (!no)
return;
- SIGHT_GLOBAL_TRY {
- if (!pp)
- pp = sight_global_pool;
-
- if ((rc = sight_create_pool(&pool, pp)) != APR_SUCCESS) {
+ if (!ppool) {
+ /* Use the global pool */
+ ppool = sight_global_pool;
+ }
+ if (!ppool) {
+ /* Global pool is missing */
+ throwAprMemoryException(_E, THROW_FMARK, APR_ENOPOOL);
+ return;
+ }
+ if ((rc = sight_pool_lock(&mutex, ppool)) == APR_SUCCESS) {
+ if ((rc = sight_pool_create(&pool, ppool, lock)) != APR_SUCCESS) {
throwAprMemoryException(_E, THROW_FMARK, rc);
- SIGHT_GLOBAL_END();
+ apr_thread_mutex_unlock(mutex);
return;
}
@@ -191,8 +199,11 @@
native_object_cleanup,
apr_pool_cleanup_null);
SET_IFIELD_J(0001, no->object, P2J(pool));
-
- } SIGHT_GLOBAL_END();
+ apr_thread_mutex_unlock(mutex);
+ } else {
+ /* Pool is locked or invalid */
+ throwAprMemoryException(_E, THROW_FMARK, rc);
+ }
}
SIGHT_EXPORT_DECLARE(void, NativeObject, cbset0)(SIGHT_STDARGS,
@@ -226,6 +237,7 @@
{
sight_object_t *no = J2P(instance, sight_object_t *);
jobject object = NULL;
+ apr_thread_mutex_t *mutex;
#if SIGHT_APR_REFCOUNT
apr_uint32_t ioc = 0;
apr_uint32_t refcount;
@@ -238,7 +250,8 @@
#endif
if (!no)
return;
- SIGHT_GLOBAL_TRY {
+ /* Check if parent is locked */
+ if (sight_pool_lock_parent(&mutex, no->pool) == APR_SUCCESS) {
apr_atomic_inc32(&no->interrupted);
if (no->object) {
object = (*_E)->NewLocalRef(_E, no->object);
@@ -284,14 +297,17 @@
(*_E)->DeleteLocalRef(_E, object);
if (no->cb.object)
(*_E)->DeleteGlobalRef(_E, no->cb.object);
+ if (mutex)
+ apr_thread_mutex_unlock(mutex);
free(no);
- } SIGHT_GLOBAL_END();
+ }
}
SIGHT_EXPORT_DECLARE(void, NativeObject, clear0)(SIGHT_STDARGS,
jlong instance)
{
sight_object_t *no = J2P(instance, sight_object_t *);
+ apr_thread_mutex_t *mutex;
#if SIGHT_APR_REFCOUNT
apr_uint32_t ioc = 0;
apr_uint32_t refcount;
@@ -303,7 +319,7 @@
#endif
if (!no)
return;
- SIGHT_GLOBAL_TRY {
+ if (sight_pool_lock_parent(&mutex, no->pool) == APR_SUCCESS) {
apr_atomic_inc32(&no->interrupted);
#if SIGHT_APR_REFCOUNT
refcount = apr_atomic_read32(&no->refcount);
@@ -333,7 +349,7 @@
if (no->clean)
(*no->clean)(POOL_CLEAR, no);
if (no->pool) {
- apr_pool_clear(no->pool);
+ sight_pool_clear(no->pool);
apr_pool_cleanup_register(no->pool, (const void *)no,
native_object_cleanup,
apr_pool_cleanup_null);
@@ -341,7 +357,9 @@
no->native = NULL;
}
apr_atomic_set32(&no->interrupted, 0);
- } SIGHT_GLOBAL_END();
+ if (mutex)
+ apr_thread_mutex_unlock(mutex);
+ }
}
SIGHT_EXPORT_DECLARE(void, NativeObject, intr0)(SIGHT_STDARGS,