From 3b5e58ba6e82fcc4a8acc03286a0f370312f3ee8 Mon Sep 17 00:00:00 2001 From: Bill Stoddard Date: Wed, 13 Mar 2002 03:59:21 +0000 Subject: [PATCH] Enable mod_mem_cache to use apr_atomic operators in managing cache_object reference counting. Enabled by default via the USE_ATOMICS preproc directive. This compiles cleanly and serves pages on Windows. Not compiled or tested on any other OS. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93889 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 11 +++++ modules/experimental/mod_mem_cache.c | 72 ++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 9c3a784980..84300e29ea 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,15 @@ Changes with Apache 2.0.34-dev + *) Use apr_atomic operations in managing the mod_mem_cache + cache_objects for SMP scalability. (see USE_ATOMICS + preprocessor directive in mod_file_cache) + [Bill Stoddard] + + *) Add filehandle caching to mod_mem_cache. (see CACHE_FD + preprocessor directive in mod_file_cache) + [Bill Stoddard] + + *) Implement prototype mod_disk_cache for use with mod_cache. + [Bill Stoddard] *) Add a missing manualdir entry in the Debian config.layout. [Thom May ] diff --git a/modules/experimental/mod_mem_cache.c b/modules/experimental/mod_mem_cache.c index 3c29a4d161..5922121278 100644 --- a/modules/experimental/mod_mem_cache.c +++ b/modules/experimental/mod_mem_cache.c @@ -57,11 +57,18 @@ */ #define CORE_PRIVATE +/* CACHE_FD will eventually be exposed as a configuration directive */ #define CACHE_FD 0 #include "mod_cache.h" #include "ap_mpm.h" #include "apr_thread_mutex.h" +/* USE_ATOMICS should be replaced with the appropriate APR feature macro */ +#define USE_ATOMICS +#ifdef USE_ATOMICS +#include "apr_atomic.h" +#endif + #if !APR_HAS_THREADS #error This module does not currently compile unless you have a thread-capable APR. Sorry! #endif @@ -191,6 +198,13 @@ static apr_status_t decrement_refcount(void *arg) { cache_object_t *obj = (cache_object_t *) arg; +#ifdef USE_ATOMICS + if (!apr_atomic_dec(&obj->refcount)) { + if (obj->cleanup) { + cleanup_cache_object(obj); + } + } +#else if (sconf->lock) { apr_thread_mutex_lock(sconf->lock); } @@ -204,6 +218,7 @@ static apr_status_t decrement_refcount(void *arg) if (sconf->lock) { apr_thread_mutex_unlock(sconf->lock); } +#endif return APR_SUCCESS; } static apr_status_t cleanup_cache_mem(void *sconfv) @@ -223,8 +238,14 @@ static apr_status_t cleanup_cache_mem(void *sconfv) for (hi = apr_hash_first(NULL, co->cacheht); hi; hi=apr_hash_next(hi)) { apr_hash_this(hi, NULL, NULL, (void **)&obj); if (obj) { +#ifdef USE_ATOMICS + apr_atomic_inc(&obj->refcount); + obj->cleanup = 1; + if (!apr_atomic_dec(&obj->refcount)) { +#else obj->cleanup = 1; if (!obj->refcount) { +#endif cleanup_cache_object(obj); } } @@ -422,6 +443,7 @@ static int remove_entity(cache_handle_t *h) { cache_object_t *obj = h->cache_obj; + /* Remove the cache object from the cache */ if (sconf->lock) { apr_thread_mutex_lock(sconf->lock); } @@ -432,16 +454,36 @@ static int remove_entity(cache_handle_t *h) apr_hash_set(sconf->cacheht, obj->key, strlen(obj->key), NULL); sconf->object_cnt--; sconf->cache_size -= mobj->m_len; - obj->cleanup = 1; - if (!obj->refcount) { - cleanup_cache_object(obj); - } - h->cache_obj = NULL; } + else { + /* If the object was removed from the cache prior to this function being + * called, then obj == NULL. Reinit obj with the object being cleaned up. + * Note: This code assumes that there is at most only one object in the + * cache per key. + */ + obj = h->cache_obj; + } + + /* Cleanup the cache object + * Set obj->cleanup to ensure decrement_refcount cleans up the obj if it + * is still being referenced by another thread + */ + obj->cleanup = 1; +#ifndef USE_ATOMICS + obj->refcount--; + if (!obj->refcount) { + cleanup_cache_object(obj); + } +#endif if (sconf->lock) { apr_thread_mutex_unlock(sconf->lock); } - +#ifdef USE_ATOMICS + if (!apr_atomic_dec(&obj->refcount)) { + cleanup_cache_object(obj); + } +#endif + h->cache_obj = NULL; return OK; } static apr_status_t serialize_table(cache_header_tbl_t **obj, @@ -527,19 +569,29 @@ static int remove_url(const char *type, const char *key) apr_hash_set(sconf->cacheht, key, APR_HASH_KEY_STRING, NULL); sconf->object_cnt--; sconf->cache_size -= mobj->m_len; + /* Set cleanup to ensure decrement_refcount cleans up the obj if it + * is still being referenced by another thread + */ obj->cleanup = 1; +#ifdef USE_ATOMICS + /* Refcount increment MUST be made under protection of the lock */ + obj->refcount++; +#else if (!obj->refcount) { cleanup_cache_object(obj); } +#endif } if (sconf->lock) { apr_thread_mutex_unlock(sconf->lock); } - - if (!obj) { - return DECLINED; +#ifdef USE_ATOMICS + if (obj) { + if (!apr_atomic_dec(&obj->refcount)) { + cleanup_cache_object(obj); + } } - +#endif return OK; } -- 2.40.0