* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cache.c,v 1.45.2.1 2001/10/19 00:22:26 marka Exp $ */
+/* $Id: cache.c,v 1.45.2.2 2001/10/23 01:31:08 marka Exp $ */
#include <config.h>
* task/event serialization, or locked from the cache object.
*/
struct cache_cleaner {
+ isc_mutex_t lock;
+ /*
+ * Locks overmem_event, overmem. Note: never allocate memory
+ * while holding this lock - that could lead to deadlock since
+ * the lock is take by water() which is called from the memory
+ * allocator.
+ */
+
dns_cache_t *cache;
isc_task_t *task;
unsigned int cleaning_interval; /* The cleaning-interval from
if (cache->cleaner.iterator != NULL)
dns_dbiterator_destroy(&cache->cleaner.iterator);
+ DESTROYLOCK(&cache->cleaner.lock);
+
if (cache->filename) {
isc_mem_free(cache->mctx, cache->filename);
cache->filename = NULL;
{
isc_result_t result;
+ result = isc_mutex_init(&cleaner->lock);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_mutex_init() failed: %s",
+ dns_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto fail;
+ }
+
cleaner->increment = DNS_CACHE_CLEANERINCREMENT;
cleaner->state = cleaner_s_idle;
cleaner->cache = cache;
isc_timer_detach(&cleaner->cleaning_timer);
if (cleaner->task != NULL)
isc_task_detach(&cleaner->task);
-
+ DESTROYLOCK(&cleaner->lock);
+ fail:
return (result);
}
static void
overmem_cleaning_action(isc_task_t *task, isc_event_t *event) {
cache_cleaner_t *cleaner = event->ev_arg;
+ isc_boolean_t want_cleaning = ISC_FALSE;
UNUSED(task);
INSIST(event->ev_type == DNS_EVENT_CACHEOVERMEM);
INSIST(cleaner->overmem_event == NULL);
+ LOCK(&cleaner->lock);
+
if (cleaner->overmem) {
if (cleaner->state == cleaner_s_idle)
- begin_cleaning(cleaner);
+ want_cleaning = ISC_TRUE;
} else {
if (cleaner->state == cleaner_s_busy)
/*
}
cleaner->overmem_event = event;
+
+ UNLOCK(&cleaner->lock);
+
+ if (want_cleaning)
+ begin_cleaning(cleaner);
}
/*
REQUIRE(VALID_CACHE(cache));
+ LOCK(&cache->cleaner.lock);
+
dns_db_overmem(cache->db, overmem);
cache->cleaner.overmem = overmem;
if (cache->cleaner.overmem_event != NULL)
isc_task_send(cache->cleaner.task,
&cache->cleaner.overmem_event);
+
+ UNLOCK(&cache->cleaner.lock);
}
void