diff --git a/modules/dialog/dlg_hash.c b/modules/dialog/dlg_hash.c index 536fe323d13..e3d0005fd15 100644 --- a/modules/dialog/dlg_hash.c +++ b/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; isize; 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=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 ; ientries[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 ; isize; 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); diff --git a/modules/dialog/dlg_hash.h b/modules/dialog/dlg_hash.h index d79d994bc41..b09fe381e6c 100644 --- a/modules/dialog/dlg_hash.h +++ b/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