Переглянути джерело

Merge branch 'master' of ssh://git.sip-router.org/sip-router

Jason Penton 11 роки тому
батько
коміт
daf2b6ef13

+ 5 - 1
modules/app_perl/lib/perl/Kamailio/Constants.pm

@@ -165,7 +165,11 @@ BEGIN {
 #####################
 #####################
 # non-enum constants from dprint.h:
 # non-enum constants from dprint.h:
 # Logging levels
 # Logging levels
-	const( L_ALERT	=> -3);
+	const( L_NPRL	=> -6);
+	const( L_MIN	=> -5);
+	const( L_ALERT	=> -5);
+	const( L_BUG	=> -4);
+	const( L_CRIT2  => -3);
 	const( L_CRIT	=> -2);
 	const( L_CRIT	=> -2);
 	const( L_ERR	=> -1);
 	const( L_ERR	=> -1);
 	const( L_WARN	=> 0);
 	const( L_WARN	=> 0);

+ 6 - 2
modules/htable/README

@@ -672,7 +672,9 @@ sht_reset("ha$var(x)");
 
 
 4.5. sht_lock(htable=>key)
 4.5. sht_lock(htable=>key)
 
 
-   Lock the slot in htable corespoding to the key item.
+   Lock the slot in htable corespoding to the key item. Note that the
+   locking is re-entrant for the process, therefore the lock and unlock
+   should be done by the same process.
 
 
    This function can be used from ANY_ROUTE.
    This function can be used from ANY_ROUTE.
 
 
@@ -683,7 +685,9 @@ sht_lock("ha=>test");
 
 
 4.6. sht_unlock(htable=>key)
 4.6. sht_unlock(htable=>key)
 
 
-   Unlock the slot in htable corespoding to the key item.
+   Unlock the slot in htable corespoding to the key item. Note that the
+   locking is re-entrant for the process, therefore the lock and unlock
+   should be done by the same process.
 
 
    This function can be used from ANY_ROUTE.
    This function can be used from ANY_ROUTE.
 
 

+ 6 - 2
modules/htable/doc/htable_admin.xml

@@ -741,7 +741,9 @@ sht_reset("ha$var(x)");
 		<function moreinfo="none">sht_lock(htable=>key)</function>
 		<function moreinfo="none">sht_lock(htable=>key)</function>
 		</title>
 		</title>
 		<para>
 		<para>
-			Lock the slot in htable corespoding to the key item.
+			Lock the slot in htable corespoding to the key item. Note that
+			the locking is re-entrant for the process, therefore the lock
+			and unlock should be done by the same process.
 		</para>
 		</para>
 		<para>
 		<para>
 			This function can be used from ANY_ROUTE.
 			This function can be used from ANY_ROUTE.
@@ -760,7 +762,9 @@ sht_lock("ha=>test");
 		<function moreinfo="none">sht_unlock(htable=>key)</function>
 		<function moreinfo="none">sht_unlock(htable=>key)</function>
 		</title>
 		</title>
 		<para>
 		<para>
-			Unlock the slot in htable corespoding to the key item.
+			Unlock the slot in htable corespoding to the key item. Note that
+			the locking is re-entrant for the process, therefore the lock
+			and unlock should be done by the same process.
 		</para>
 		</para>
 		<para>
 		<para>
 			This function can be used from ANY_ROUTE.
 			This function can be used from ANY_ROUTE.

+ 75 - 44
modules/htable/ht_api.c

@@ -140,6 +140,37 @@ void keyvalue_destroy(keyvalue_t *res)
 	memset(res, 0, sizeof(keyvalue_t));
 	memset(res, 0, sizeof(keyvalue_t));
 }
 }
 
 
+/**
+ * recursive/re-entrant lock of the slot in hash table
+ */
+void ht_slot_lock(ht_t *ht, int idx)
+{
+	int mypid;
+
+	mypid = my_pid();
+	if (likely(atomic_get(&ht->entries[idx].locker_pid) != mypid)) {
+		lock_get(&ht->entries[idx].lock);
+		atomic_set(&ht->entries[idx].locker_pid, mypid);
+	} else {
+		/* locked within the same process that executed us */
+		ht->entries[idx].rec_lock_level++;
+	}
+}
+
+/**
+ * recursive/re-entrant unlock of the slot in hash table
+ */
+void ht_slot_unlock(ht_t *ht, int idx)
+{
+	if (likely(ht->entries[idx].rec_lock_level == 0)) {
+		atomic_set(&ht->entries[idx].locker_pid, 0);
+		lock_release(&ht->entries[idx].lock);
+	} else  {
+		/* recursive locked => decrease lock count */
+		ht->entries[idx].rec_lock_level--;
+	}
+}
+
 ht_cell_t* ht_cell_new(str *name, int type, int_str *val, unsigned int cellid)
 ht_cell_t* ht_cell_new(str *name, int type, int_str *val, unsigned int cellid)
 {
 {
 	ht_cell_t *cell;
 	ht_cell_t *cell;
@@ -393,7 +424,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
 	if(ht->htexpire>0)
 	if(ht->htexpire>0)
 		now = time(NULL);
 		now = time(NULL);
 	prev = NULL;
 	prev = NULL;
-	if(mode) lock_get(&ht->entries[idx].lock);
+	if(mode) ht_slot_lock(ht, idx);
 	it = ht->entries[idx].first;
 	it = ht->entries[idx].first;
 	while(it!=NULL && it->cellid < hid)
 	while(it!=NULL && it->cellid < hid)
 	{
 	{
@@ -425,7 +456,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
 						if(cell == NULL)
 						if(cell == NULL)
 						{
 						{
 							LM_ERR("cannot create new cell\n");
 							LM_ERR("cannot create new cell\n");
-							if(mode) lock_release(&ht->entries[idx].lock);
+							if(mode) ht_slot_unlock(ht, idx);
 							return -1;
 							return -1;
 						}
 						}
 						cell->next = it->next;
 						cell->next = it->next;
@@ -446,7 +477,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
 					if(ht->updateexpire)
 					if(ht->updateexpire)
 						it->expire = now + ht->htexpire;
 						it->expire = now + ht->htexpire;
 				}
 				}
-				if(mode) lock_release(&ht->entries[idx].lock);
+				if(mode) ht_slot_unlock(ht, idx);
 				return 0;
 				return 0;
 			} else {
 			} else {
 				if(type&AVP_VAL_STR)
 				if(type&AVP_VAL_STR)
@@ -456,7 +487,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
 					if(cell == NULL)
 					if(cell == NULL)
 					{
 					{
 						LM_ERR("cannot create new cell.\n");
 						LM_ERR("cannot create new cell.\n");
-						if(mode) lock_release(&ht->entries[idx].lock);
+						if(mode) ht_slot_unlock(ht, idx);
 						return -1;
 						return -1;
 					}
 					}
 					cell->expire = now + ht->htexpire;
 					cell->expire = now + ht->htexpire;
@@ -475,7 +506,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
 					if(ht->updateexpire)
 					if(ht->updateexpire)
 						it->expire = now + ht->htexpire;
 						it->expire = now + ht->htexpire;
 				}
 				}
-				if(mode) lock_release(&ht->entries[idx].lock);
+				if(mode) ht_slot_unlock(ht, idx);
 				return 0;
 				return 0;
 			}
 			}
 		}
 		}
@@ -487,7 +518,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
 	if(cell == NULL)
 	if(cell == NULL)
 	{
 	{
 		LM_ERR("cannot create new cell.\n");
 		LM_ERR("cannot create new cell.\n");
-		if(mode) lock_release(&ht->entries[idx].lock);
+		if(mode) ht_slot_unlock(ht, idx);
 		return -1;
 		return -1;
 	}
 	}
 	cell->expire = now + ht->htexpire;
 	cell->expire = now + ht->htexpire;
@@ -507,7 +538,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
 		prev->next = cell;
 		prev->next = cell;
 	}
 	}
 	ht->entries[idx].esize++;
 	ht->entries[idx].esize++;
-	if(mode) lock_release(&ht->entries[idx].lock);
+	if(mode) ht_slot_unlock(ht, idx);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -528,7 +559,7 @@ int ht_del_cell(ht_t *ht, str *name)
 	if(ht->entries[idx].first==NULL)
 	if(ht->entries[idx].first==NULL)
 		return 0;
 		return 0;
 	
 	
-	lock_get(&ht->entries[idx].lock);
+	ht_slot_lock(ht, idx);
 	it = ht->entries[idx].first;
 	it = ht->entries[idx].first;
 	while(it!=NULL && it->cellid < hid)
 	while(it!=NULL && it->cellid < hid)
 		it = it->next;
 		it = it->next;
@@ -545,13 +576,13 @@ int ht_del_cell(ht_t *ht, str *name)
 			if(it->next)
 			if(it->next)
 				it->next->prev = it->prev;
 				it->next->prev = it->prev;
 			ht->entries[idx].esize--;
 			ht->entries[idx].esize--;
-			lock_release(&ht->entries[idx].lock);
+			ht_slot_unlock(ht, idx);
 			ht_cell_free(it);
 			ht_cell_free(it);
 			return 0;
 			return 0;
 		}
 		}
 		it = it->next;
 		it = it->next;
 	}
 	}
-	lock_release(&ht->entries[idx].lock);
+	ht_slot_unlock(ht, idx);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -575,7 +606,7 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 	if(ht->htexpire>0)
 	if(ht->htexpire>0)
 		now = time(NULL);
 		now = time(NULL);
 	prev = NULL;
 	prev = NULL;
-	if(mode) lock_get(&ht->entries[idx].lock);
+	if(mode) ht_slot_lock(ht, idx);
 	it = ht->entries[idx].first;
 	it = ht->entries[idx].first;
 	while(it!=NULL && it->cellid < hid)
 	while(it!=NULL && it->cellid < hid)
 	{
 	{
@@ -606,7 +637,7 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 					if(it->next)
 					if(it->next)
 						it->next->prev = it->prev;
 						it->next->prev = it->prev;
 					ht->entries[idx].esize--;
 					ht->entries[idx].esize--;
-					lock_release(&ht->entries[idx].lock);
+					if(mode) ht_slot_unlock(ht, idx);
 					ht_cell_free(it);
 					ht_cell_free(it);
 					return NULL;
 					return NULL;
 				}
 				}
@@ -615,7 +646,7 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 			if(it->flags&AVP_VAL_STR)
 			if(it->flags&AVP_VAL_STR)
 			{
 			{
 				/* string value cannot be incremented */
 				/* string value cannot be incremented */
-				if(mode) lock_release(&ht->entries[idx].lock);
+				if(mode) ht_slot_unlock(ht, idx);
 				return NULL;
 				return NULL;
 			} else {
 			} else {
 				it->value.n += val;
 				it->value.n += val;
@@ -625,7 +656,7 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 					if(old->msize>=it->msize)
 					if(old->msize>=it->msize)
 					{
 					{
 						memcpy(old, it, it->msize);
 						memcpy(old, it, it->msize);
-						lock_release(&ht->entries[idx].lock);
+						if(mode) ht_slot_unlock(ht, idx);
 						return old;
 						return old;
 					}
 					}
 				}
 				}
@@ -633,7 +664,7 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 				if(cell!=NULL)
 				if(cell!=NULL)
 					memcpy(cell, it, it->msize);
 					memcpy(cell, it, it->msize);
 
 
-				if(mode) lock_release(&ht->entries[idx].lock);
+				if(mode) ht_slot_unlock(ht, idx);
 				return cell;
 				return cell;
 			}
 			}
 		}
 		}
@@ -648,7 +679,7 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 	if(it == NULL)
 	if(it == NULL)
 	{
 	{
 		LM_ERR("cannot create new cell.\n");
 		LM_ERR("cannot create new cell.\n");
-		if(mode) lock_release(&ht->entries[idx].lock);
+		if(mode) ht_slot_unlock(ht, idx);
 		return NULL;
 		return NULL;
 	}
 	}
 	it->expire = now + ht->htexpire;
 	it->expire = now + ht->htexpire;
@@ -673,7 +704,7 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 		if(old->msize>=it->msize)
 		if(old->msize>=it->msize)
 		{
 		{
 			memcpy(old, it, it->msize);
 			memcpy(old, it, it->msize);
-			lock_release(&ht->entries[idx].lock);
+			if(mode) ht_slot_unlock(ht, idx);
 			return old;
 			return old;
 		}
 		}
 	}
 	}
@@ -681,7 +712,7 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, int mode,
 	if(cell!=NULL)
 	if(cell!=NULL)
 		memcpy(cell, it, it->msize);
 		memcpy(cell, it, it->msize);
 
 
-	if(mode) lock_release(&ht->entries[idx].lock);
+	if(mode) ht_slot_unlock(ht, idx);
 	return cell;
 	return cell;
 }
 }
 
 
@@ -703,7 +734,7 @@ ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old)
 	if(ht->entries[idx].first==NULL)
 	if(ht->entries[idx].first==NULL)
 		return NULL;
 		return NULL;
 	
 	
-	lock_get(&ht->entries[idx].lock);
+	ht_slot_lock(ht, idx);
 	it = ht->entries[idx].first;
 	it = ht->entries[idx].first;
 	while(it!=NULL && it->cellid < hid)
 	while(it!=NULL && it->cellid < hid)
 		it = it->next;
 		it = it->next;
@@ -724,7 +755,7 @@ ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old)
 				if(it->next)
 				if(it->next)
 					it->next->prev = it->prev;
 					it->next->prev = it->prev;
 				ht->entries[idx].esize--;
 				ht->entries[idx].esize--;
-				lock_release(&ht->entries[idx].lock);
+				ht_slot_unlock(ht, idx);
 				ht_cell_free(it);
 				ht_cell_free(it);
 				return NULL;
 				return NULL;
 			}
 			}
@@ -733,19 +764,19 @@ ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old)
 				if(old->msize>=it->msize)
 				if(old->msize>=it->msize)
 				{
 				{
 					memcpy(old, it, it->msize);
 					memcpy(old, it, it->msize);
-					lock_release(&ht->entries[idx].lock);
+					ht_slot_unlock(ht, idx);
 					return old;
 					return old;
 				}
 				}
 			}
 			}
 			cell = (ht_cell_t*)pkg_malloc(it->msize);
 			cell = (ht_cell_t*)pkg_malloc(it->msize);
 			if(cell!=NULL)
 			if(cell!=NULL)
 				memcpy(cell, it, it->msize);
 				memcpy(cell, it, it->msize);
-			lock_release(&ht->entries[idx].lock);
+			ht_slot_unlock(ht, idx);
 			return cell;
 			return cell;
 		}
 		}
 		it = it->next;
 		it = it->next;
 	}
 	}
-	lock_release(&ht->entries[idx].lock);
+	ht_slot_unlock(ht, idx);
 	return NULL;
 	return NULL;
 }
 }
 
 
@@ -762,7 +793,7 @@ int ht_dbg(void)
 				ht->name.s, ht->htid, ht->htexpire);
 				ht->name.s, ht->htid, ht->htexpire);
 		for(i=0; i<ht->htsize; i++)
 		for(i=0; i<ht->htsize; i++)
 		{
 		{
-			lock_get(&ht->entries[i].lock);
+			ht_slot_lock(ht, i);
 			LM_ERR("htable[%d] -- <%d>\n", i, ht->entries[i].esize);
 			LM_ERR("htable[%d] -- <%d>\n", i, ht->entries[i].esize);
 			it = ht->entries[i].first;
 			it = ht->entries[i].first;
 			while(it)
 			while(it)
@@ -776,7 +807,7 @@ int ht_dbg(void)
 					LM_ERR("\tv-i:%d\n", it->value.n);
 					LM_ERR("\tv-i:%d\n", it->value.n);
 				it = it->next;
 				it = it->next;
 			}
 			}
-			lock_release(&ht->entries[i].lock);
+			ht_slot_unlock(ht, i);
 		}
 		}
 		ht = ht->next;
 		ht = ht->next;
 	}
 	}
@@ -945,7 +976,7 @@ void ht_timer(unsigned int ticks, void *param)
 			for(i=0; i<ht->htsize; i++)
 			for(i=0; i<ht->htsize; i++)
 			{
 			{
 				/* free entries */
 				/* free entries */
-				lock_get(&ht->entries[i].lock);
+				ht_slot_lock(ht, i);
 				it = ht->entries[i].first;
 				it = ht->entries[i].first;
 				while(it)
 				while(it)
 				{
 				{
@@ -965,7 +996,7 @@ void ht_timer(unsigned int ticks, void *param)
 					}
 					}
 					it = it0;
 					it = it0;
 				}
 				}
-				lock_release(&ht->entries[i].lock);
+				ht_slot_unlock(ht, i);
 			}
 			}
 		}
 		}
 		ht = ht->next;
 		ht = ht->next;
@@ -1040,7 +1071,7 @@ int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
 	LM_DBG("set auto-expire to %u (%d)\n", (unsigned int)now,
 	LM_DBG("set auto-expire to %u (%d)\n", (unsigned int)now,
 			val->n);
 			val->n);
 
 
-	lock_get(&ht->entries[idx].lock);
+	ht_slot_lock(ht, idx);
 	it = ht->entries[idx].first;
 	it = ht->entries[idx].first;
 	while(it!=NULL && it->cellid < hid)
 	while(it!=NULL && it->cellid < hid)
 		it = it->next;
 		it = it->next;
@@ -1051,12 +1082,12 @@ int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
 		{
 		{
 			/* update value */
 			/* update value */
 			it->expire = now;
 			it->expire = now;
-			lock_release(&ht->entries[idx].lock);
+			ht_slot_unlock(ht, idx);
 			return 0;
 			return 0;
 		}
 		}
 		it = it->next;
 		it = it->next;
 	}
 	}
-	lock_release(&ht->entries[idx].lock);
+	ht_slot_unlock(ht, idx);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1080,7 +1111,7 @@ int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val)
 	idx = ht_get_entry(hid, ht->htsize);
 	idx = ht_get_entry(hid, ht->htsize);
 
 
 	now = time(NULL);
 	now = time(NULL);
-	lock_get(&ht->entries[idx].lock);
+	ht_slot_lock(ht, idx);
 	it = ht->entries[idx].first;
 	it = ht->entries[idx].first;
 	while(it!=NULL && it->cellid < hid)
 	while(it!=NULL && it->cellid < hid)
 		it = it->next;
 		it = it->next;
@@ -1091,12 +1122,12 @@ int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val)
 		{
 		{
 			/* update value */
 			/* update value */
 			*val = (unsigned int)(it->expire - now);
 			*val = (unsigned int)(it->expire - now);
-			lock_release(&ht->entries[idx].lock);
+			ht_slot_unlock(ht, idx);
 			return 0;
 			return 0;
 		}
 		}
 		it = it->next;
 		it = it->next;
 	}
 	}
-	lock_release(&ht->entries[idx].lock);
+	ht_slot_unlock(ht, idx);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1121,7 +1152,7 @@ int ht_rm_cell_re(str *sre, ht_t *ht, int mode)
 	for(i=0; i<ht->htsize; i++)
 	for(i=0; i<ht->htsize; i++)
 	{
 	{
 		/* free entries */
 		/* free entries */
-		lock_get(&ht->entries[i].lock);
+		ht_slot_lock(ht, i);
 		it = ht->entries[i].first;
 		it = ht->entries[i].first;
 		while(it)
 		while(it)
 		{
 		{
@@ -1149,7 +1180,7 @@ int ht_rm_cell_re(str *sre, ht_t *ht, int mode)
 			}
 			}
 			it = it0;
 			it = it0;
 		}
 		}
-		lock_release(&ht->entries[i].lock);
+		ht_slot_unlock(ht, i);
 	}
 	}
 	regfree(&re);
 	regfree(&re);
 	return 0;
 	return 0;
@@ -1167,7 +1198,7 @@ int ht_reset_content(ht_t *ht)
 	for(i=0; i<ht->htsize; i++)
 	for(i=0; i<ht->htsize; i++)
 	{
 	{
 		/* free entries */
 		/* free entries */
-		lock_get(&ht->entries[i].lock);
+		ht_slot_lock(ht, i);
 		it = ht->entries[i].first;
 		it = ht->entries[i].first;
 		while(it)
 		while(it)
 		{
 		{
@@ -1182,7 +1213,7 @@ int ht_reset_content(ht_t *ht)
 			ht_cell_free(it);
 			ht_cell_free(it);
 			it = it0;
 			it = it0;
 		}
 		}
-		lock_release(&ht->entries[i].lock);
+		ht_slot_unlock(ht, i);
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -1285,7 +1316,7 @@ int ht_count_cells_re(str *sre, ht_t *ht, int mode)
 	for(i=0; i<ht->htsize; i++)
 	for(i=0; i<ht->htsize; i++)
 	{
 	{
 		/* free entries */
 		/* free entries */
-		lock_get(&ht->entries[i].lock);
+		ht_slot_lock(ht, i);
 		it = ht->entries[i].first;
 		it = ht->entries[i].first;
 		while(it)
 		while(it)
 		{
 		{
@@ -1332,7 +1363,7 @@ int ht_count_cells_re(str *sre, ht_t *ht, int mode)
 			}
 			}
 			it = it0;
 			it = it0;
 		}
 		}
-		lock_release(&ht->entries[i].lock);
+		ht_slot_unlock(ht, i);
 	}
 	}
 	if(op==1)
 	if(op==1)
 		regfree(&re);
 		regfree(&re);
@@ -1388,7 +1419,7 @@ int ht_iterator_start(str *iname, str *hname)
 		{
 		{
 			if(_ht_iterators[k].slot>=0 && _ht_iterators[k].slot<_ht_iterators[k].ht->htsize)
 			if(_ht_iterators[k].slot>=0 && _ht_iterators[k].slot<_ht_iterators[k].ht->htsize)
 			{
 			{
-				lock_release(&_ht_iterators[k].ht->entries[_ht_iterators[k].slot].lock);
+				ht_slot_unlock(_ht_iterators[k].ht, _ht_iterators[k].slot);
 			}
 			}
 		}
 		}
 	} else {
 	} else {
@@ -1457,19 +1488,19 @@ int ht_iterator_next(str *iname)
 		}
 		}
 		/* next is not in the same slot - release and try next one */
 		/* next is not in the same slot - release and try next one */
 		_ht_iterators[k].it = NULL;
 		_ht_iterators[k].it = NULL;
-		lock_release(&_ht_iterators[k].ht->entries[_ht_iterators[k].slot].lock);
+		ht_slot_unlock(_ht_iterators[k].ht, _ht_iterators[k].slot);
 		_ht_iterators[k].slot++;
 		_ht_iterators[k].slot++;
 	}
 	}
 
 
 	for( ; _ht_iterators[k].slot<_ht_iterators[k].ht->htsize; _ht_iterators[k].slot++)
 	for( ; _ht_iterators[k].slot<_ht_iterators[k].ht->htsize; _ht_iterators[k].slot++)
 	{
 	{
-		lock_get(&_ht_iterators[k].ht->entries[_ht_iterators[k].slot].lock);
+		ht_slot_lock(_ht_iterators[k].ht, _ht_iterators[k].slot);
 		if(_ht_iterators[k].ht->entries[_ht_iterators[k].slot].first!=NULL)
 		if(_ht_iterators[k].ht->entries[_ht_iterators[k].slot].first!=NULL)
 		{
 		{
 			_ht_iterators[k].it = _ht_iterators[k].ht->entries[_ht_iterators[k].slot].first;
 			_ht_iterators[k].it = _ht_iterators[k].ht->entries[_ht_iterators[k].slot].first;
 			return 0;
 			return 0;
 		}
 		}
-		lock_release(&_ht_iterators[k].ht->entries[_ht_iterators[k].slot].lock);
+		ht_slot_unlock(_ht_iterators[k].ht, _ht_iterators[k].slot);
 	}
 	}
 	return -1;
 	return -1;
 }
 }
@@ -1489,7 +1520,7 @@ int ht_iterator_end(str *iname)
 				{
 				{
 					if(_ht_iterators[i].slot>=0 && _ht_iterators[i].slot<_ht_iterators[i].ht->htsize)
 					if(_ht_iterators[i].slot>=0 && _ht_iterators[i].slot<_ht_iterators[i].ht->htsize)
 					{
 					{
-						lock_release(&_ht_iterators[i].ht->entries[_ht_iterators[i].slot].lock);
+						ht_slot_unlock(_ht_iterators[i].ht, _ht_iterators[i].slot);
 					}
 					}
 				}
 				}
 				memset(&_ht_iterators[i], 0, sizeof(ht_iterator_t));
 				memset(&_ht_iterators[i], 0, sizeof(ht_iterator_t));

+ 8 - 3
modules/htable/ht_api.h

@@ -28,6 +28,7 @@
 #include "../../usr_avp.h"
 #include "../../usr_avp.h"
 #include "../../locking.h"
 #include "../../locking.h"
 #include "../../pvar.h"
 #include "../../pvar.h"
+#include "../../atomic_ops.h"
 
 
 #define ht_compute_hash(_s)        core_case_hash(_s,0,0)
 #define ht_compute_hash(_s)        core_case_hash(_s,0,0)
 #define ht_get_entry(_h,_size)    (_h)&((_size)-1)
 #define ht_get_entry(_h,_size)    (_h)&((_size)-1)
@@ -46,9 +47,11 @@ typedef struct _ht_cell
 
 
 typedef struct _ht_entry
 typedef struct _ht_entry
 {
 {
-	unsigned int esize;
-	ht_cell_t *first;
-	gen_lock_t lock;	
+	unsigned int esize;  /* number of items in the slot */
+	ht_cell_t *first;    /* first item in the slot */
+	gen_lock_t lock;     /* mutex to access items in the slot */
+	atomic_t locker_pid; /* pid of the process that holds the lock */
+	int rec_lock_level;  /* recursive lock count */
 } ht_entry_t;
 } ht_entry_t;
 
 
 typedef struct _ht
 typedef struct _ht
@@ -111,4 +114,6 @@ int ht_iterator_next(str *iname);
 int ht_iterator_end(str *iname);
 int ht_iterator_end(str *iname);
 ht_cell_t* ht_iterator_get_current(str *iname);
 ht_cell_t* ht_iterator_get_current(str *iname);
 
 
+void ht_slot_lock(ht_t *ht, int idx);
+void ht_slot_unlock(ht_t *ht, int idx);
 #endif
 #endif

+ 2 - 1
modules/htable/ht_db.c

@@ -435,7 +435,7 @@ int ht_db_save_table(ht_t *ht, str *dbtable)
 
 
 	for(i=0; i<ht->htsize; i++)
 	for(i=0; i<ht->htsize; i++)
 	{
 	{
-		lock_get(&ht->entries[i].lock);
+		ht_slot_lock(ht, i);
 		it = ht->entries[i].first;
 		it = ht->entries[i].first;
 		while(it)
 		while(it)
 		{
 		{
@@ -495,6 +495,7 @@ int ht_db_save_table(ht_t *ht, str *dbtable)
 			}
 			}
 			it = it->next;
 			it = it->next;
 		}
 		}
+		ht_slot_unlock(ht, i);
 	}
 	}
 	return 0;
 	return 0;
 }
 }

+ 19 - 19
modules/htable/htable.c

@@ -63,8 +63,8 @@ static void destroy(void);
 static int fixup_ht_key(void** param, int param_no);
 static int fixup_ht_key(void** param, int param_no);
 static int ht_rm_name_re(struct sip_msg* msg, char* key, char* foo);
 static int ht_rm_name_re(struct sip_msg* msg, char* key, char* foo);
 static int ht_rm_value_re(struct sip_msg* msg, char* key, char* foo);
 static int ht_rm_value_re(struct sip_msg* msg, char* key, char* foo);
-static int ht_slot_lock(struct sip_msg* msg, char* key, char* foo);
-static int ht_slot_unlock(struct sip_msg* msg, char* key, char* foo);
+static int w_ht_slot_lock(struct sip_msg* msg, char* key, char* foo);
+static int w_ht_slot_unlock(struct sip_msg* msg, char* key, char* foo);
 static int ht_reset(struct sip_msg* msg, char* htname, char* foo);
 static int ht_reset(struct sip_msg* msg, char* htname, char* foo);
 static int w_ht_iterator_start(struct sip_msg* msg, char* iname, char* hname);
 static int w_ht_iterator_start(struct sip_msg* msg, char* iname, char* hname);
 static int w_ht_iterator_next(struct sip_msg* msg, char* iname, char* foo);
 static int w_ht_iterator_next(struct sip_msg* msg, char* iname, char* foo);
@@ -114,9 +114,9 @@ static cmd_export_t cmds[]={
 		ANY_ROUTE},
 		ANY_ROUTE},
 	{"sht_rm_value_re", (cmd_function)ht_rm_value_re,  1, fixup_ht_key, 0,
 	{"sht_rm_value_re", (cmd_function)ht_rm_value_re,  1, fixup_ht_key, 0,
 		ANY_ROUTE},
 		ANY_ROUTE},
-	{"sht_lock",        (cmd_function)ht_slot_lock,    1, fixup_ht_key, 0,
+	{"sht_lock",        (cmd_function)w_ht_slot_lock,    1, fixup_ht_key, 0,
 		ANY_ROUTE},
 		ANY_ROUTE},
-	{"sht_unlock",      (cmd_function)ht_slot_unlock,  1, fixup_ht_key, 0,
+	{"sht_unlock",      (cmd_function)w_ht_slot_unlock,  1, fixup_ht_key, 0,
 		ANY_ROUTE},
 		ANY_ROUTE},
 	{"sht_reset",		(cmd_function)ht_reset,		   1, fixup_spve_null, 0,
 	{"sht_reset",		(cmd_function)ht_reset,		   1, fixup_spve_null, 0,
 		ANY_ROUTE},
 		ANY_ROUTE},
@@ -446,7 +446,7 @@ static int w_ht_iterator_end(struct sip_msg* msg, char* iname, char* foo)
 /**
 /**
  * lock the slot for a given key in a hash table
  * lock the slot for a given key in a hash table
  */
  */
-static int ht_slot_lock(struct sip_msg* msg, char* key, char* foo)
+static int w_ht_slot_lock(struct sip_msg* msg, char* key, char* foo)
 {
 {
 	ht_pv_t *hpv;
 	ht_pv_t *hpv;
 	str skey;
 	str skey;
@@ -480,7 +480,7 @@ static int ht_slot_lock(struct sip_msg* msg, char* key, char* foo)
 			hpv->htname.len, hpv->htname.s,
 			hpv->htname.len, hpv->htname.s,
 			idx, skey.len, skey.s);
 			idx, skey.len, skey.s);
 
 
-	lock_get(&hpv->ht->entries[idx].lock);
+	ht_slot_lock(hpv->ht, idx);
 
 
 	return 1;
 	return 1;
 }
 }
@@ -488,7 +488,7 @@ static int ht_slot_lock(struct sip_msg* msg, char* key, char* foo)
 /**
 /**
  * unlock the slot for a given key in a hash table
  * unlock the slot for a given key in a hash table
  */
  */
-static int ht_slot_unlock(struct sip_msg* msg, char* key, char* foo)
+static int w_ht_slot_unlock(struct sip_msg* msg, char* key, char* foo)
 {
 {
 	ht_pv_t *hpv;
 	ht_pv_t *hpv;
 	str skey;
 	str skey;
@@ -522,7 +522,7 @@ static int ht_slot_unlock(struct sip_msg* msg, char* key, char* foo)
 			hpv->htname.len, hpv->htname.s,
 			hpv->htname.len, hpv->htname.s,
 			idx, skey.len, skey.s);
 			idx, skey.len, skey.s);
 
 
-	lock_release(&hpv->ht->entries[idx].lock);
+	ht_slot_unlock(hpv->ht, idx);
 
 
 	return 1;
 	return 1;
 }
 }
@@ -609,11 +609,11 @@ static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
 	/* replace old entries */
 	/* replace old entries */
 	for(i=0; i<nht.htsize; i++)
 	for(i=0; i<nht.htsize; i++)
 	{
 	{
-		lock_get(&ht->entries[i].lock);
+		ht_slot_lock(ht, i);
 		first = ht->entries[i].first;
 		first = ht->entries[i].first;
 		ht->entries[i].first = nht.entries[i].first;
 		ht->entries[i].first = nht.entries[i].first;
 		ht->entries[i].esize = nht.entries[i].esize;
 		ht->entries[i].esize = nht.entries[i].esize;
-		lock_release(&ht->entries[i].lock);
+		ht_slot_unlock(ht, i);
 		nht.entries[i].first = first;
 		nht.entries[i].first = first;
 	}
 	}
 	/* free old entries */
 	/* free old entries */
@@ -708,7 +708,7 @@ static struct mi_root* ht_mi_dump(struct mi_root* cmd_tree, void* param)
 
 
 	for(i=0; i<ht->htsize; i++)
 	for(i=0; i<ht->htsize; i++)
 	{
 	{
-		lock_get(&ht->entries[i].lock);
+		ht_slot_lock(ht, i);
 		it = ht->entries[i].first;
 		it = ht->entries[i].first;
 		if(it)
 		if(it)
 		{
 		{
@@ -732,7 +732,7 @@ static struct mi_root* ht_mi_dump(struct mi_root* cmd_tree, void* param)
 				it = it->next;
 				it = it->next;
 			}
 			}
 		}
 		}
-		lock_release(&ht->entries[i].lock);
+		ht_slot_unlock(ht, i);
 	}
 	}
 
 
 	return rpl_tree;
 	return rpl_tree;
@@ -963,7 +963,7 @@ static void  htable_rpc_dump(rpc_t* rpc, void* c)
 	}
 	}
 	for(i=0; i<ht->htsize; i++)
 	for(i=0; i<ht->htsize; i++)
 	{
 	{
-		lock_get(&ht->entries[i].lock);
+		ht_slot_lock(ht, i);
 		it = ht->entries[i].first;
 		it = ht->entries[i].first;
 		if(it)
 		if(it)
 		{
 		{
@@ -1009,13 +1009,13 @@ static void  htable_rpc_dump(rpc_t* rpc, void* c)
 				it = it->next;
 				it = it->next;
 			}
 			}
 		}
 		}
-		lock_release(&ht->entries[i].lock);
+		ht_slot_unlock(ht, i);
 	}
 	}
 
 
 	return;
 	return;
 
 
 error:
 error:
-	lock_release(&ht->entries[i].lock);
+	ht_slot_unlock(ht, i);
 }
 }
 
 
 static void  htable_rpc_list(rpc_t* rpc, void* c)
 static void  htable_rpc_list(rpc_t* rpc, void* c)
@@ -1093,13 +1093,13 @@ static void  htable_rpc_stats(rpc_t* rpc, void* c)
 		max = 0;
 		max = 0;
 		min = 4294967295U;
 		min = 4294967295U;
 		for(i=0; i<ht->htsize; i++) {
 		for(i=0; i<ht->htsize; i++) {
-			lock_get(&ht->entries[i].lock);
+			ht_slot_lock(ht, i);
 			if(ht->entries[i].esize<min)
 			if(ht->entries[i].esize<min)
 				min = ht->entries[i].esize;
 				min = ht->entries[i].esize;
 			if(ht->entries[i].esize>max)
 			if(ht->entries[i].esize>max)
 				max = ht->entries[i].esize;
 				max = ht->entries[i].esize;
 			all += ht->entries[i].esize;
 			all += ht->entries[i].esize;
-			lock_release(&ht->entries[i].lock);
+			ht_slot_unlock(ht, i);
 		}
 		}
 
 
 		if(rpc->struct_add(th, "Sddd",
 		if(rpc->struct_add(th, "Sddd",
@@ -1189,11 +1189,11 @@ static void htable_rpc_reload(rpc_t* rpc, void* c)
 	/* replace old entries */
 	/* replace old entries */
 	for(i=0; i<nht.htsize; i++)
 	for(i=0; i<nht.htsize; i++)
 	{
 	{
-		lock_get(&ht->entries[i].lock);
+		ht_slot_lock(ht, i);
 		first = ht->entries[i].first;
 		first = ht->entries[i].first;
 		ht->entries[i].first = nht.entries[i].first;
 		ht->entries[i].first = nht.entries[i].first;
 		ht->entries[i].esize = nht.entries[i].esize;
 		ht->entries[i].esize = nht.entries[i].esize;
-		lock_release(&ht->entries[i].lock);
+		ht_slot_unlock(ht, i);
 		nht.entries[i].first = first;
 		nht.entries[i].first = first;
 	}
 	}
 	/* free old entries */
 	/* free old entries */

+ 4 - 3
modules/tm/tm.c

@@ -2141,9 +2141,10 @@ int t_check_trans(struct sip_msg* msg)
 	int ret;
 	int ret;
 	
 	
 	/* already processing a T */
 	/* already processing a T */
-	if(get_route_type()==FAILURE_ROUTE
-			|| get_route_type()==BRANCH_ROUTE
-			|| get_route_type()==TM_ONREPLY_ROUTE) {
+	if(is_route_type(FAILURE_ROUTE)
+			|| is_route_type(BRANCH_ROUTE)
+			|| is_route_type(BRANCH_FAILURE_ROUTE)
+			|| is_route_type(TM_ONREPLY_ROUTE)) {
 		return 1;
 		return 1;
 	}
 	}