bnicholes 2002/06/26 15:01:02
Modified: . NWGNUmakefile
misc/netware libprews.c aprlib.def
file_io/netware filestat.c
include/arch/netware apr_private.h
Log:
Removed the ReadWrite mutex that protects the stat cache table. Instead
implemented
separate stat cache tables per processor. This eliminates the lock contention
that was occuring each time a cache node expired and had to be refreshed.
Having a stat cache per processor may cause some data redundancy but ensures
that no other thread will be refreshing a node at the same time a thread
is reading it.
Revision Changes Path
1.6 +2 -4 apr/NWGNUmakefile
Index: NWGNUmakefile
===================================================================
RCS file: /home/cvs/apr/NWGNUmakefile,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- NWGNUmakefile 13 Jun 2002 00:40:50 -0000 1.5
+++ NWGNUmakefile 26 Jun 2002 22:01:02 -0000 1.6
@@ -220,10 +220,8 @@
FILES_nlm_Ximports = \
@libc.imp \
@ws2nlm.imp \
- @netware.imp \
- NXGetRandom \
- NXGetCtlInfo \
- NXSetCtlInfo \
+ @netware.imp \
+ CpuCurrentProcessor \
$(EOLIST)
#
1.6 +17 -6 apr/misc/netware/libprews.c
Index: libprews.c
===================================================================
RCS file: /home/cvs/apr/misc/netware/libprews.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- libprews.c 14 Mar 2002 16:50:11 -0000 1.5
+++ libprews.c 26 Jun 2002 22:01:02 -0000 1.6
@@ -15,10 +15,12 @@
#include "apr_pools.h"
+#define MAX_PROCESSORS 128
+
typedef struct app_data {
int initialized;
void* gPool;
- void* statCache;
+ void* statCache[MAX_PROCESSORS];
} APP_DATA;
/* library-private data...*/
@@ -174,26 +176,35 @@
return NULL;
}
-int setStatCache(void *data)
+int setStatCache(void *data, int proc)
{
APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
+ if ((proc < 0) || (proc > (MAX_PROCESSORS-1))) {
+ data = NULL;
+ return 0;
+ }
+
NXLock(gLibLock);
- if (app_data && !app_data->statCache) {
- app_data->statCache = data;
+ if (app_data && !app_data->statCache[proc]) {
+ app_data->statCache[proc] = data;
}
NXUnlock(gLibLock);
return 1;
}
-void* getStatCache()
+void* getStatCache(int proc)
{
APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
+ if ((proc < 0) || (proc > (MAX_PROCESSORS-1))) {
+ return NULL;
+ }
+
if (app_data) {
- return app_data->statCache;
+ return app_data->statCache[proc];
}
return NULL;
1.6 +1 -0 apr/misc/netware/aprlib.def
Index: aprlib.def
===================================================================
RCS file: /home/cvs/apr/misc/netware/aprlib.def,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- aprlib.def 5 Mar 2002 19:48:55 -0000 1.5
+++ aprlib.def 26 Jun 2002 22:01:02 -0000 1.6
@@ -1,3 +1,4 @@
MODULE LIBC.NLM
MODULE WS2_32.NLM
+IMPORT CpuCurrentProcessor
EXPORT @aprlib.imp
1.13 +12 -69 apr/file_io/netware/filestat.c
Index: filestat.c
===================================================================
RCS file: /home/cvs/apr/file_io/netware/filestat.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- filestat.c 11 Jun 2002 15:34:26 -0000 1.12
+++ filestat.c 26 Jun 2002 22:01:02 -0000 1.13
@@ -59,13 +59,6 @@
#include "apr_strings.h"
#include "apr_errno.h"
#include "apr_hash.h"
-#define USE_CSTAT_RWLOCK
-#ifdef USE_CSTAT_MUTEX
-#include "apr_thread_mutex.h"
-#endif
-#ifdef USE_CSTAT_RWLOCK
-#include "apr_thread_rwlock.h"
-#endif
static apr_filetype_e filetype_from_mode(mode_t mode)
{
@@ -222,28 +215,11 @@
apr_time_t expire;
};
-typedef struct apr_stat_cache_t apr_stat_cache_t;
-
-struct apr_stat_cache_t {
- apr_hash_t *statCache;
-#ifdef USE_CSTAT_MUTEX
- apr_thread_mutex_t *statcache_mutex;
-#endif
-#ifdef USE_CSTAT_RWLOCK
- apr_thread_rwlock_t *statcache_mutex;
-#endif
-};
+extern apr_int32_t CpuCurrentProcessor; /* system variable */
int cstat (const char *path, struct stat *buf, char **casedName, apr_pool_t
*pool)
{
- apr_stat_cache_t *statCacheData = (apr_stat_cache_t *)getStatCache();
- apr_hash_t *statCache = NULL;
-#ifdef USE_CSTAT_MUTEX
- apr_thread_mutex_t *statcache_mutex;
-#endif
-#ifdef USE_CSTAT_RWLOCK
- apr_thread_rwlock_t *statcache_mutex;
-#endif
+ apr_hash_t *statCache = (apr_hash_t *)getStatCache(CpuCurrentProcessor);
apr_pool_t *gPool = (apr_pool_t *)getGlobalPool();
apr_stat_entry_t *stat_entry;
struct stat *info;
@@ -263,46 +239,18 @@
return ret;
}
- /* If we have a statCacheData structure then use it.
+ /* If we have a statCache hash table then use it.
Otherwise we need to create it and initialized it
with a new mutex lock. */
- if (statCacheData) {
- statCache = statCacheData->statCache;
-#if defined(USE_CSTAT_MUTEX) || defined(USE_CSTAT_RWLOCK)
- statcache_mutex = statCacheData->statcache_mutex;
-#endif
- }
- else {
- statCacheData = (apr_stat_cache_t *)apr_palloc (gPool,
sizeof(apr_stat_cache_t));
+ if (!statCache) {
statCache = apr_hash_make(gPool);
-#ifdef USE_CSTAT_MUTEX
- apr_thread_mutex_create(&statcache_mutex, APR_THREAD_MUTEX_DEFAULT,
gPool);
- statCacheData->statcache_mutex = statcache_mutex;
-#endif
-#ifdef USE_CSTAT_RWLOCK
- apr_thread_rwlock_create(&statcache_mutex, gPool);
- statCacheData->statcache_mutex = statcache_mutex;
-#endif
- statCacheData->statCache = statCache;
- setStatCache((void*)statCacheData);
+ setStatCache((void*)statCache, CpuCurrentProcessor);
}
/* If we have a statCache then try to pull the information
from the cache. Otherwise just stat the file and return.*/
if (statCache) {
-#ifdef USE_CSTAT_MUTEX
- apr_thread_mutex_lock(statcache_mutex);
-#endif
-#ifdef USE_CSTAT_RWLOCK
- apr_thread_rwlock_rdlock(statcache_mutex);
-#endif
stat_entry = (apr_stat_entry_t*) apr_hash_get(statCache, path,
APR_HASH_KEY_STRING);
-#ifdef USE_CSTAT_MUTEX
- apr_thread_mutex_unlock(statcache_mutex);
-#endif
-#ifdef USE_CSTAT_RWLOCK
- apr_thread_rwlock_unlock(statcache_mutex);
-#endif
/* If we got an entry then check the expiration time. If the entry
hasn't expired yet then copy the information and return. */
if (stat_entry) {
@@ -316,16 +264,16 @@
}
}
+ /* Since we are creating a separate stat cache for each processor, we
+ don't need to worry about locking the hash table before
manipulating
+ it. */
if (!found) {
+ /* Bind the thread to the current cpu so that we don't wake
+ up on some other cpu and try to manipulate the wrong cache. */
+ NXThreadBind (CpuCurrentProcessor);
ret = stat(path, buf);
if (ret == 0) {
*casedName = case_filename(pool, path);
-#ifdef USE_CSTAT_MUTEX
- apr_thread_mutex_lock(statcache_mutex);
-#endif
-#ifdef USE_CSTAT_RWLOCK
- apr_thread_rwlock_wrlock(statcache_mutex);
-#endif
/* If we don't have a stat_entry then create one, copy
the data and add it to the hash table. */
if (!stat_entry) {
@@ -349,12 +297,7 @@
}
stat_entry->expire = now;
}
-#ifdef USE_CSTAT_MUTEX
- apr_thread_mutex_unlock(statcache_mutex);
-#endif
-#ifdef USE_CSTAT_RWLOCK
- apr_thread_rwlock_unlock(statcache_mutex);
-#endif
+ NXThreadBind (NX_THR_UNBOUND);
}
else
return ret;
1.10 +2 -2 apr/include/arch/netware/apr_private.h
Index: apr_private.h
===================================================================
RCS file: /home/cvs/apr/include/arch/netware/apr_private.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- apr_private.h 13 Mar 2002 20:39:17 -0000 1.9
+++ apr_private.h 26 Jun 2002 22:01:02 -0000 1.10
@@ -170,8 +170,8 @@
/* Application global data management */
int setGlobalPool(void *data);
void* getGlobalPool();
-int setStatCache(void *data);
-void* getStatCache();
+int setStatCache(void *data, int proc);
+void* getStatCache(int proc);
/* Redefine malloc to use the library malloc call so
that all of the memory resources will be owned