Przeglądaj źródła

dialog: re-entrant mutex for dialogs hash table slots

- changed from a lock set usage to per slot lock field
Daniel-Constantin Mierla 10 lat temu
rodzic
commit
9c3ea838b3
2 zmienionych plików z 32 dodań i 38 usunięć
  1. 7 32
      modules/dialog/dlg_hash.c
  2. 25 6
      modules/dialog/dlg_hash.h

+ 7 - 32
modules/dialog/dlg_hash.c

@@ -42,9 +42,6 @@
 #include "dlg_req_within.h"
 #include "dlg_db_handler.h"
 
-#define MAX_LDG_LOCKS  2048
-#define MIN_LDG_LOCKS  2
-
 extern int dlg_ka_interval;
 
 /*! global dialog table */
@@ -223,7 +220,7 @@ int dlg_clean_run(ticks_t ti)
 	tm = (unsigned int)time(NULL);
 	for(i=0; i<d_table->size; i++)
 	{
-		lock_set_get(d_table->locks, d_table->entries[i].lock_idx);
+		dlg_lock(d_table, &d_table->entries[i]);
 		dlg = d_table->entries[i].first;
 		while (dlg) {
 			tdlg = dlg;
@@ -243,7 +240,7 @@ int dlg_clean_run(ticks_t ti)
 				tdlg->dflags |= DLG_FLAG_CHANGED;
 			}
 		}
-		lock_set_release(d_table->locks, d_table->entries[i].lock_idx);
+		dlg_unlock(d_table, &d_table->entries[i]);
 	}
 	return 0;
 }
@@ -288,30 +285,13 @@ int init_dlg_table(unsigned int size)
 	d_table->size = size;
 	d_table->entries = (struct dlg_entry*)(d_table+1);
 
-	n = (size<MAX_LDG_LOCKS)?size:MAX_LDG_LOCKS;
-	for(  ; n>=MIN_LDG_LOCKS ; n-- ) {
-		d_table->locks = lock_set_alloc(n);
-		if (d_table->locks==0)
-			continue;
-		if (lock_set_init(d_table->locks)==0) {
-			lock_set_dealloc(d_table->locks);
-			d_table->locks = 0;
-			continue;
-		}
-		d_table->locks_no = n;
-		break;
-	}
-
-	if (d_table->locks==0) {
-		LM_ERR("unable to allocted at least %d locks for the hash table\n",
-			MIN_LDG_LOCKS);
-		goto error1;
-	}
-
 	for( i=0 ; i<size; i++ ) {
 		memset( &(d_table->entries[i]), 0, sizeof(struct dlg_entry) );
+		if(lock_init(&d_table->entries[i].lock)<0) {
+			LM_ERR("failed to init lock for slot: %d\n", i);
+			goto error1;
+		}
 		d_table->entries[i].next_id = rand() % (3*size);
-		d_table->entries[i].lock_idx = i % d_table->locks_no;
 	}
 
 	return 0;
@@ -411,11 +391,6 @@ void destroy_dlg_table(void)
 	if (d_table==0)
 		return;
 
-	if (d_table->locks) {
-		lock_set_destroy(d_table->locks);
-		lock_set_dealloc(d_table->locks);
-	}
-
 	for( i=0 ; i<d_table->size; i++ ) {
 		dlg = d_table->entries[i].first;
 		while (dlg) {
@@ -423,7 +398,7 @@ void destroy_dlg_table(void)
 			dlg = dlg->next;
 			destroy_dlg(l_dlg);
 		}
-
+		lock_destroy(&d_table->entries[i].lock);
 	}
 
 	shm_free(d_table);

+ 25 - 6
modules/dialog/dlg_hash.h

@@ -33,6 +33,7 @@
 #include "../../locking.h"
 #include "../../lib/kmi/mi.h"
 #include "../../timer.h"
+#include "../../atomic_ops.h"
 #include "dlg_timer.h"
 #include "dlg_cb.h"
 
@@ -134,7 +135,9 @@ typedef struct dlg_entry
 	struct dlg_cell    *first;	/*!< dialog list */
 	struct dlg_cell    *last;	/*!< optimisation, end of the dialog list */
 	unsigned int       next_id;	/*!< next id */
-	unsigned int       lock_idx;	/*!< lock index */
+	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 */
 } dlg_entry_t;
 
 
@@ -143,8 +146,6 @@ typedef struct dlg_table
 {
 	unsigned int       size;	/*!< size of the dialog table */
 	struct dlg_entry   *entries;	/*!< dialog hash table */
-	unsigned int       locks_no;	/*!< number of locks */
-	gen_lock_set_t     *locks;	/*!< lock table */
 } dlg_table_t;
 
 
@@ -160,12 +161,22 @@ extern dlg_table_t *d_table;
 
 
 /*!
- * \brief Set a dialog lock
+ * \brief Set a dialog lock (re-entrant)
  * \param _table dialog table
  * \param _entry locked entry
  */
 #define dlg_lock(_table, _entry) \
-		lock_set_get( (_table)->locks, (_entry)->lock_idx);
+		do { \
+			int mypid; \
+			mypid = my_pid(); \
+			if (likely(atomic_get( &(_entry)->locker_pid) != mypid)) { \
+				lock_get( &(_entry)->lock); \
+				atomic_set( &(_entry)->locker_pid, mypid); \
+			} else { \
+				/* locked within the same process that executed us */ \
+				(_entry)->rec_lock_level++; \
+			} \
+		} while(0)
 
 
 /*!
@@ -174,7 +185,15 @@ extern dlg_table_t *d_table;
  * \param _entry locked entry
  */
 #define dlg_unlock(_table, _entry) \
-		lock_set_release( (_table)->locks, (_entry)->lock_idx);
+		do { \
+			if (likely((_entry)->rec_lock_level == 0)) { \
+				atomic_set( &(_entry)->locker_pid, 0); \
+				lock_release( &(_entry)->lock); \
+			} else  { \
+				/* recursive locked => decrease lock count */ \
+				(_entry)->rec_lock_level--; \
+			} \
+		} while(0)
 
 /*!
  * \brief Unlink a dialog from the list without locking