From d6410c9207d16f55afce5b30b2c8c05b5432f757 Mon Sep 17 00:00:00 2001
From: Jong Hyuk Choi <jongchoi@openldap.org>
Date: Tue, 14 Dec 2004 03:51:09 +0000
Subject: [PATCH] zone invalidation/locking implementation

---
 servers/slapd/slap.h      |   4 +-
 servers/slapd/zn_malloc.c | 248 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 245 insertions(+), 7 deletions(-)

diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 3527503339..785f72cf59 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -2879,12 +2879,14 @@ struct zone_heap {
 	int zh_maxzones;
 	int zh_deltazones;
 	void **zh_zones;
+	ldap_pvt_thread_rdwr_t *zh_znlock;
 	Avlnode *zh_zonetree;
 	unsigned char ***zh_maps;
-	unsigned long *zh_seqno;
+	int *zh_seqno;
 	LDAP_LIST_HEAD( zh_freelist, zone_object ) *zh_free;
 	LDAP_LIST_HEAD( zh_so, zone_object ) zh_zopool;
 	ldap_pvt_thread_mutex_t zh_mutex;
+	ldap_pvt_thread_rdwr_t zh_lock;
 };
 #endif
 
diff --git a/servers/slapd/zn_malloc.c b/servers/slapd/zn_malloc.c
index 31c21dd84a..c2e8d20f96 100644
--- a/servers/slapd/zn_malloc.c
+++ b/servers/slapd/zn_malloc.c
@@ -62,26 +62,29 @@ slap_zn_mem_destroy(
 	} while (pad_shift >>= 1);
 
 	ldap_pvt_thread_mutex_lock( &zh->zh_mutex );
-	for (i = 0; i <= zh->zh_zoneorder - order_start; i++) {
+	for (i = 0; i < zh->zh_zoneorder - order_start + 1; i++) {
 		zo = LDAP_LIST_FIRST(&zh->zh_free[i]);
 		while (zo) {
 			struct zone_object *zo_tmp = zo;
 			zo = LDAP_LIST_NEXT(zo, zo_link);
+			LDAP_LIST_REMOVE(zo_tmp, zo_link);
 			LDAP_LIST_INSERT_HEAD(&zh->zh_zopool, zo_tmp, zo_link);
 		}
 	}
 	ch_free(zh->zh_free);
 
 	for (i = 0; i < zh->zh_numzones; i++) {
-		for (j = 0; j < zh->zh_zoneorder - order_start; j++) {
+		for (j = 0; j < zh->zh_zoneorder - order_start + 1; j++) {
 			ch_free(zh->zh_maps[i][j]);
 		}
 		ch_free(zh->zh_maps[i]);
 		munmap(zh->zh_zones[i], zh->zh_zonesize);
+		ldap_pvt_thread_rdwr_destroy(&zh->zh_znlock[i]);
 	}
 	ch_free(zh->zh_maps);
 	ch_free(zh->zh_zones);
 	ch_free(zh->zh_seqno);
+	ch_free(zh->zh_znlock);
 
 	avl_free(zh->zh_zonetree, slap_zo_release);
 
@@ -99,8 +102,9 @@ slap_zn_mem_destroy(
 		zo = LDAP_LIST_NEXT(zo, zo_link);
 		ch_free(zo_tmp);
 	}
-	ldap_pvt_thread_mutex_unlock( &zh->zh_mutex );
-	ldap_pvt_thread_mutex_destroy( &zh->zh_mutex );
+	ldap_pvt_thread_mutex_unlock(&zh->zh_mutex);
+	ldap_pvt_thread_rdwr_destroy(&zh->zh_lock);
+	ldap_pvt_thread_mutex_destroy(&zh->zh_mutex);
 	ch_free(zh);
 }
 
@@ -165,6 +169,8 @@ slap_zn_mem_create(
 	order = order_end - order_start + 1;
 
 	zh->zh_zones = (void **)ch_malloc(zh->zh_maxzones * sizeof(void*));
+	zh->zh_znlock = (ldap_pvt_thread_rdwr_t *)ch_malloc(
+						zh->zh_maxzones * sizeof(ldap_pvt_thread_rdwr_t *));
 	zh->zh_maps = (unsigned char ***)ch_malloc(
 					zh->zh_maxzones * sizeof(unsigned char**));
 
@@ -187,7 +193,7 @@ slap_zn_mem_create(
 			int shiftamt = order_start + 1 + j;
 			int nummaps = zh->zh_zonesize >> shiftamt;
 			assert(nummaps);
-			nummaps /= 8;
+			nummaps >>= 3;
 			if (!nummaps) nummaps = 1;
 			zh->zh_maps[i][j] = (unsigned char *)ch_malloc(nummaps);
 			memset(zh->zh_maps[i][j], 0, nummaps);
@@ -211,9 +217,11 @@ slap_zn_mem_create(
 		zo->zo_siz = zh->zh_zonesize;
 		zo->zo_idx = i;
 		avl_insert(&zh->zh_zonetree, zo, slap_zone_cmp, avl_dup_error);
+		ldap_pvt_thread_rdwr_init(&zh->zh_znlock[i]);
 	}
 
 	ldap_pvt_thread_mutex_init(&zh->zh_mutex);
+	ldap_pvt_thread_rdwr_init(&zh->zh_lock);
 
 	return zh;
 }
@@ -337,7 +345,7 @@ retry:
 				int shiftamt = order_start + 1 + j;
 				int nummaps = zh->zh_zonesize >> shiftamt;
 				assert(nummaps);
-				nummaps /= 8;
+				nummaps >>= 3;
 				if (!nummaps) nummaps = 1;
 				zh->zh_maps[i][j] = (unsigned char *)ch_malloc(nummaps);
 				memset(zh->zh_maps[i][j], 0, nummaps);
@@ -362,6 +370,7 @@ retry:
 			zo->zo_siz = zh->zh_zonesize;
 			zo->zo_idx = i;
 			avl_insert(&zh->zh_zonetree, zo, slap_zone_cmp, avl_dup_error);
+			ldap_pvt_thread_rdwr_init(&zh->zh_znlock[i]);
 		}
 		zh->zh_numzones += zh->zh_deltazones;
 		ldap_pvt_thread_mutex_unlock( &zh->zh_mutex );
@@ -520,6 +529,7 @@ slap_zn_free(void *ptr, void *ctx)
 						zo = LDAP_LIST_FIRST(&zh->zh_zopool);
 						LDAP_LIST_REMOVE(zo, zo_link);
 						zo->zo_ptr = tmpp;
+						zo->zo_idx = idx;
 						Debug(LDAP_DEBUG_NONE,
 							"slap_zn_free: merging 0x%x\n",
 							zo->zo_ptr, 0, 0);
@@ -541,6 +551,7 @@ slap_zn_free(void *ptr, void *ctx)
 						zo = LDAP_LIST_FIRST(&zh->zh_zopool);
 						LDAP_LIST_REMOVE(zo, zo_link);
 						zo->zo_ptr = tmpp;
+						zo->zo_idx = idx;
 						Debug(LDAP_DEBUG_NONE,
 							"slap_zn_free: merging 0x%x\n",
 							zo->zo_ptr, 0, 0);
@@ -580,6 +591,7 @@ slap_zn_free(void *ptr, void *ctx)
 						zo = LDAP_LIST_FIRST(&zh->zh_zopool);
 						LDAP_LIST_REMOVE(zo, zo_link);
 						zo->zo_ptr = tmpp;
+						zo->zo_idx = idx;
 						Debug(LDAP_DEBUG_NONE,
 							"slap_zn_free: merging 0x%x\n",
 							zo->zo_ptr, 0, 0);
@@ -601,6 +613,7 @@ slap_zn_free(void *ptr, void *ctx)
 						zo = LDAP_LIST_FIRST(&zh->zh_zopool);
 						LDAP_LIST_REMOVE(zo, zo_link);
 						zo->zo_ptr = tmpp;
+						zo->zo_idx = idx;
 						Debug(LDAP_DEBUG_NONE,
 							"slap_zn_free: merging 0x%x\n",
 							zo->zo_ptr, 0, 0);
@@ -656,4 +669,227 @@ slap_replenish_zopool(
 
 	return zo_block;
 }
+
+int
+slap_zn_invalidate(
+	void *ctx,
+	void *ptr
+)
+{
+	struct zone_heap* zh = ctx;
+	struct zone_object zoi, *zoo;
+	struct zone_heap *zone = NULL;
+	int seqno = *((ber_len_t*)ptr - 2);
+	int idx = -1, rc = 0;
+	int pad = 2*sizeof(int)-1, pad_shift;
+	int order_start = -1, i;
+	struct zone_object *zo;
+
+	pad_shift = pad - 1;
+	do {
+		order_start++;
+	} while (pad_shift >>= 1);
+
+	zoi.zo_ptr = ptr;
+	zoi.zo_idx = -1;
+
+	ldap_pvt_thread_mutex_lock( &zh->zh_mutex );
+	zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp);
+
+	if (zoo) {
+		idx = zoo->zo_idx;
+		assert(idx != -1);
+		madvise(zh->zh_zones[idx], zh->zh_zonesize, MADV_DONTNEED);
+		for (i = 0; i < zh->zh_zoneorder - order_start + 1; i++) {
+			int shiftamt = order_start + 1 + i;
+			int nummaps = zh->zh_zonesize >> shiftamt;
+			assert(nummaps);
+			nummaps >>= 3;
+			if (!nummaps) nummaps = 1;
+			memset(zh->zh_maps[idx][i], 0, nummaps);
+			zo = LDAP_LIST_FIRST(&zh->zh_free[i]);
+			while (zo) {
+				struct zone_object *zo_tmp = zo;
+				zo = LDAP_LIST_NEXT(zo, zo_link);
+				if (zo_tmp && zo_tmp->zo_idx == idx) {
+					LDAP_LIST_REMOVE(zo_tmp, zo_link);
+					LDAP_LIST_INSERT_HEAD(&zh->zh_zopool, zo_tmp, zo_link);
+				}
+			}
+		}
+		if (LDAP_LIST_EMPTY(&zh->zh_zopool)) {
+			slap_replenish_zopool(zh);
+		}
+		zo = LDAP_LIST_FIRST(&zh->zh_zopool);
+		LDAP_LIST_REMOVE(zo, zo_link);
+		zo->zo_ptr = zh->zh_zones[idx];
+		zo->zo_idx = idx;
+		LDAP_LIST_INSERT_HEAD(&zh->zh_free[zh->zh_zoneorder-order_start],
+								zo, zo_link);
+		zh->zh_seqno[idx]++;
+	} else {
+		Debug(LDAP_DEBUG_NONE, "zone not found for (ctx=0x%x, ptr=0x%x) !\n",
+				ctx, ptr, 0);
+	}
+
+	ldap_pvt_thread_mutex_unlock( &zh->zh_mutex );
+	Debug(LDAP_DEBUG_NONE, "zone %d invalidate\n", idx, 0, 0);
+	return rc;
+}
+
+int
+slap_zn_validate(
+	void *ctx,
+	void *ptr,
+	int seqno
+)
+{
+	struct zone_heap* zh = ctx;
+	struct zone_object zoi, *zoo;
+	struct zone_heap *zone = NULL;
+	int idx, rc = 0;
+
+	zoi.zo_ptr = ptr;
+	zoi.zo_idx = -1;
+
+	zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp);
+
+	if (zoo) {
+		idx = zoo->zo_idx;
+		assert(idx != -1);
+		assert(seqno <= zh->zh_seqno[idx]);
+		rc = (seqno == zh->zh_seqno[idx]);
+	}
+
+	return rc;
+}
+
+int slap_zh_rlock(
+	void *ctx
+)
+{
+	struct zone_heap* zh = ctx;
+	ldap_pvt_thread_rdwr_rlock(&zh->zh_lock);
+}
+
+int slap_zh_runlock(
+	void *ctx
+)
+{
+	struct zone_heap* zh = ctx;
+	ldap_pvt_thread_rdwr_runlock(&zh->zh_lock);
+}
+
+int slap_zh_wlock(
+	void *ctx
+)
+{
+	struct zone_heap* zh = ctx;
+	ldap_pvt_thread_rdwr_wlock(&zh->zh_lock);
+}
+
+int slap_zh_wunlock(
+	void *ctx
+)
+{
+	struct zone_heap* zh = ctx;
+	ldap_pvt_thread_rdwr_wunlock(&zh->zh_lock);
+}
+
+int slap_zn_rlock(
+	void *ctx,
+	void *ptr
+)
+{
+	struct zone_heap* zh = ctx;
+	struct zone_object zoi, *zoo;
+	struct zone_heap *zone = NULL;
+	int idx;
+
+	zoi.zo_ptr = ptr;
+	zoi.zo_idx = -1;
+
+	ldap_pvt_thread_mutex_lock( &zh->zh_mutex );
+	zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp);
+	ldap_pvt_thread_mutex_unlock( &zh->zh_mutex );
+
+	if (zoo) {
+		idx = zoo->zo_idx;
+		assert(idx != -1);
+		ldap_pvt_thread_rdwr_rlock(&zh->zh_znlock[idx]);
+	}
+}
+
+int slap_zn_runlock(
+	void *ctx,
+	void *ptr
+)
+{
+	struct zone_heap* zh = ctx;
+	struct zone_object zoi, *zoo;
+	struct zone_heap *zone = NULL;
+	int idx;
+
+	zoi.zo_ptr = ptr;
+	zoi.zo_idx = -1;
+
+	ldap_pvt_thread_mutex_lock( &zh->zh_mutex );
+	zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp);
+	ldap_pvt_thread_mutex_unlock( &zh->zh_mutex );
+
+	if (zoo) {
+		idx = zoo->zo_idx;
+		assert(idx != -1);
+		ldap_pvt_thread_rdwr_runlock(&zh->zh_znlock[idx]);
+	}
+}
+
+int slap_zn_wlock(
+	void *ctx,
+	void *ptr
+)
+{
+	struct zone_heap* zh = ctx;
+	struct zone_object zoi, *zoo;
+	struct zone_heap *zone = NULL;
+	int idx;
+
+	zoi.zo_ptr = ptr;
+	zoi.zo_idx = -1;
+
+	ldap_pvt_thread_mutex_lock( &zh->zh_mutex );
+	zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp);
+	ldap_pvt_thread_mutex_unlock( &zh->zh_mutex );
+
+	if (zoo) {
+		idx = zoo->zo_idx;
+		assert(idx != -1);
+		ldap_pvt_thread_rdwr_wlock(&zh->zh_znlock[idx]);
+	}
+}
+
+int slap_zn_wunlock(
+	void *ctx,
+	void *ptr
+)
+{
+	struct zone_heap* zh = ctx;
+	struct zone_object zoi, *zoo;
+	struct zone_heap *zone = NULL;
+	int idx;
+
+	zoi.zo_ptr = ptr;
+	zoi.zo_idx = -1;
+
+	ldap_pvt_thread_mutex_lock( &zh->zh_mutex );
+	zoo = avl_find(zh->zh_zonetree, &zoi, slap_zone_cmp);
+	ldap_pvt_thread_mutex_unlock( &zh->zh_mutex );
+
+	if (zoo) {
+		idx = zoo->zo_idx;
+		assert(idx != -1);
+		ldap_pvt_thread_rdwr_wunlock(&zh->zh_znlock[idx]);
+	}
+}
+
 #endif /* SLAP_ZONE_ALLOC */
-- 
GitLab