Skip to content

Commit

Permalink
dialog: re-entrant mutex for dialogs hash table slots
Browse files Browse the repository at this point in the history
- changed from a lock set usage to per slot lock field
  • Loading branch information
miconda committed Jun 16, 2015
1 parent bbcac5b commit 9c3ea83
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 38 deletions.
39 changes: 7 additions & 32 deletions modules/dialog/dlg_hash.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -411,19 +391,14 @@ 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) {
l_dlg = dlg;
dlg = dlg->next;
destroy_dlg(l_dlg);
}

lock_destroy(&d_table->entries[i].lock);
}

shm_free(d_table);
Expand Down
31 changes: 25 additions & 6 deletions modules/dialog/dlg_hash.h
Expand Up @@ -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"

Expand Down Expand Up @@ -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;


Expand All @@ -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;


Expand All @@ -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)


/*!
Expand All @@ -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
Expand Down

0 comments on commit 9c3ea83

Please sign in to comment.