summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbnicholes <bnicholes@13f79535-47bb-0310-9956-ffa450edef68>2002-06-26 22:01:02 +0000
committerbnicholes <bnicholes@13f79535-47bb-0310-9956-ffa450edef68>2002-06-26 22:01:02 +0000
commit333ee0ee85c6e648161cc755ffebf1215f640a36 (patch)
tree936b0ef4a887132f5099cc84617b0b06c16f3ffb
parent9b95ce3a0d8308a6d5e2b50f9bb9555fd16c12a1 (diff)
downloadlibapr-333ee0ee85c6e648161cc755ffebf1215f640a36.tar.gz
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. git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@63523 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--NWGNUmakefile6
-rw-r--r--file_io/netware/filestat.c81
-rw-r--r--include/arch/netware/apr_private.h4
-rw-r--r--misc/netware/aprlib.def1
-rw-r--r--misc/netware/libprews.c23
5 files changed, 34 insertions, 81 deletions
diff --git a/NWGNUmakefile b/NWGNUmakefile
index aeb2cd5f6..63bd95915 100644
--- a/NWGNUmakefile
+++ b/NWGNUmakefile
@@ -220,10 +220,8 @@ FILE_nlm_copyright =
FILES_nlm_Ximports = \
@libc.imp \
@ws2nlm.imp \
- @netware.imp \
- NXGetRandom \
- NXGetCtlInfo \
- NXSetCtlInfo \
+ @netware.imp \
+ CpuCurrentProcessor \
$(EOLIST)
#
diff --git a/file_io/netware/filestat.c b/file_io/netware/filestat.c
index 4b3c01558..8bffb5e02 100644
--- a/file_io/netware/filestat.c
+++ b/file_io/netware/filestat.c
@@ -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 @@ struct apr_stat_entry_t {
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 @@ int cstat (const char *path, struct stat *buf, char **casedName, apr_pool_t *poo
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 @@ int cstat (const char *path, struct stat *buf, char **casedName, apr_pool_t *poo
}
}
+ /* 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 @@ int cstat (const char *path, struct stat *buf, char **casedName, apr_pool_t *poo
}
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;
diff --git a/include/arch/netware/apr_private.h b/include/arch/netware/apr_private.h
index da6916313..29d396178 100644
--- a/include/arch/netware/apr_private.h
+++ b/include/arch/netware/apr_private.h
@@ -170,8 +170,8 @@ int unregister_NLM(void *NLMHandle);
/* 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
diff --git a/misc/netware/aprlib.def b/misc/netware/aprlib.def
index 0a2a01eb8..973612427 100644
--- a/misc/netware/aprlib.def
+++ b/misc/netware/aprlib.def
@@ -1,3 +1,4 @@
MODULE LIBC.NLM
MODULE WS2_32.NLM
+IMPORT CpuCurrentProcessor
EXPORT @aprlib.imp
diff --git a/misc/netware/libprews.c b/misc/netware/libprews.c
index fa17427fa..8213636b8 100644
--- a/misc/netware/libprews.c
+++ b/misc/netware/libprews.c
@@ -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 @@ void* getGlobalPool()
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;