|
@@ -24,6 +24,11 @@
|
|
* along with this program; if not, write to the Free Software
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
*/
|
|
|
|
+/*
|
|
|
|
+ * History:
|
|
|
|
+ * --------
|
|
|
|
+ * 2003-03-17 converted to locking.h (andrei)
|
|
|
|
+ */
|
|
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
#include "defs.h"
|
|
@@ -35,26 +40,18 @@
|
|
#include "timer.h"
|
|
#include "timer.h"
|
|
#include "../../dprint.h"
|
|
#include "../../dprint.h"
|
|
|
|
|
|
-#ifdef FAST_LOCK
|
|
|
|
-#include "../../mem/shm_mem.h"
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
|
|
|
|
-#ifndef FAST_LOCK
|
|
|
|
|
|
+#ifndef GEN_LOCK_T_PREFERED
|
|
/* semaphore probing limits */
|
|
/* semaphore probing limits */
|
|
#define SEM_MIN 16
|
|
#define SEM_MIN 16
|
|
#define SEM_MAX 4096
|
|
#define SEM_MAX 4096
|
|
|
|
|
|
-/* we implement mutex here using System V semaphores; as number of
|
|
|
|
- sempahores is limited and number of synchronized elements
|
|
|
|
- high, we partition the sync'ed SER elements and share semaphores
|
|
|
|
- in each of the partitions; we try to use as many semaphores as OS
|
|
|
|
- gives us for finest granularity; perhaps later we will
|
|
|
|
- add some arch-dependent mutex code that will not have
|
|
|
|
- ipc's dimensioning limitations and will provide us with
|
|
|
|
- fast unlimited (=no sharing) mutexing
|
|
|
|
-
|
|
|
|
- UPDATE: we do have now arch-dependent locking (-DFAST_LOCK)
|
|
|
|
|
|
+/* we implement mutex here using lock sets; as the number of
|
|
|
|
+ sempahores may be limited (e.g. sysv) and number of synchronized
|
|
|
|
+ elements high, we partition the sync'ed SER elements and share
|
|
|
|
+ semaphores in each of the partitions; we try to use as many
|
|
|
|
+ semaphores as OS gives us for finest granularity.
|
|
|
|
|
|
we allocate the locks according to the following plans:
|
|
we allocate the locks according to the following plans:
|
|
|
|
|
|
@@ -71,82 +68,17 @@
|
|
|
|
|
|
*/
|
|
*/
|
|
|
|
|
|
-/* keep the semaphore here */
|
|
|
|
-static int
|
|
|
|
- entry_semaphore=0,
|
|
|
|
- timer_semaphore=0,
|
|
|
|
- reply_semaphore=0;
|
|
|
|
/* and the maximum number of semaphores in the entry_semaphore set */
|
|
/* and the maximum number of semaphores in the entry_semaphore set */
|
|
static int sem_nr;
|
|
static int sem_nr;
|
|
-/* timer group locks */
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-/* return -1 if semget failed, -2 if semctl failed */
|
|
|
|
-static int init_semaphore_set( int size )
|
|
|
|
-{
|
|
|
|
- int new_semaphore, i;
|
|
|
|
-
|
|
|
|
- new_semaphore=semget ( IPC_PRIVATE, size, IPC_CREAT | IPC_PERMISSIONS );
|
|
|
|
- if (new_semaphore==-1) {
|
|
|
|
- DBG("DEBUG: init_semaphore_set(%d): failure to allocate a"
|
|
|
|
- " semaphore: %s\n", size, strerror(errno));
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
- for (i=0; i<size; i++) {
|
|
|
|
-
|
|
|
|
- union semun {
|
|
|
|
- int val;
|
|
|
|
- struct semid_ds *buf;
|
|
|
|
- ushort *array;
|
|
|
|
- } argument;
|
|
|
|
-
|
|
|
|
- /* binary lock */
|
|
|
|
- argument.val = +1;
|
|
|
|
- if (semctl( new_semaphore, i , SETVAL , argument )==-1) {
|
|
|
|
- DBG("DEBUG: init_semaphore_set: failure to "
|
|
|
|
- "initialize a semaphore: %s\n", strerror(errno));
|
|
|
|
- /* bug cought -- courtesy of Bogdan; -Jiri */
|
|
|
|
- /* if (semctl( entry_semaphore, 0 , IPC_RMID , 0 )==-1) */
|
|
|
|
- if (semctl( new_semaphore, 0 , IPC_RMID , 0 )==-1)
|
|
|
|
- DBG("DEBUG: init_semaphore_set: failure to release"
|
|
|
|
- " a semaphore\n");
|
|
|
|
- return -2;
|
|
|
|
- }
|
|
|
|
- } /* for cycle */
|
|
|
|
- return new_semaphore;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+lock_set_t* timer_semaphore=0;
|
|
|
|
+lock_set_t* entry_semaphore=0;
|
|
|
|
+lock_set_t* reply_semaphore=0;
|
|
|
|
+#endif
|
|
|
|
|
|
-int change_semaphore( ser_lock_t* s , int val )
|
|
|
|
-{
|
|
|
|
- struct sembuf pbuf;
|
|
|
|
- int r;
|
|
|
|
-
|
|
|
|
- pbuf.sem_num = s->semaphore_index ;
|
|
|
|
- pbuf.sem_op =val;
|
|
|
|
- pbuf.sem_flg = 0;
|
|
|
|
-
|
|
|
|
-tryagain:
|
|
|
|
- r=semop( s->semaphore_set, &pbuf , 1 /* just 1 op */ );
|
|
|
|
-
|
|
|
|
- if (r==-1) {
|
|
|
|
- if (errno==EINTR) {
|
|
|
|
- DBG("signal received in a semaphore\n");
|
|
|
|
- goto tryagain;
|
|
|
|
- } else {
|
|
|
|
- LOG(L_CRIT, "ERROR: change_semaphore(%x, %p, 1) : %s\n",
|
|
|
|
- s->semaphore_set, &pbuf,
|
|
|
|
- strerror(errno));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return r;
|
|
|
|
-}
|
|
|
|
-#endif /* !FAST_LOCK*/
|
|
|
|
|
|
+/* timer group locks */
|
|
|
|
|
|
|
|
|
|
-static ser_lock_t* timer_group_lock; /* pointer to a TG_NR lock array,
|
|
|
|
|
|
+static ser_lock_t* timer_group_lock=0; /* pointer to a TG_NR lock array,
|
|
it's safer if we alloc this in shared mem
|
|
it's safer if we alloc this in shared mem
|
|
( required for fast lock ) */
|
|
( required for fast lock ) */
|
|
|
|
|
|
@@ -155,7 +87,7 @@ static ser_lock_t* timer_group_lock; /* pointer to a TG_NR lock array,
|
|
int lock_initialize()
|
|
int lock_initialize()
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
-#ifndef FAST_LOCK
|
|
|
|
|
|
+#ifndef GEN_LOCK_T_PREFERED
|
|
int probe_run;
|
|
int probe_run;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -167,11 +99,13 @@ int lock_initialize()
|
|
LOG(L_CRIT, "ERROR: lock_initialize: out of shm mem\n");
|
|
LOG(L_CRIT, "ERROR: lock_initialize: out of shm mem\n");
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
-#ifdef FAST_LOCK
|
|
|
|
- for(i=0;i<TG_NR;i++) init_lock(timer_group_lock[i]);
|
|
|
|
|
|
+#ifdef GEN_LOCK_T_PREFERED
|
|
|
|
+ for(i=0;i<TG_NR;i++) lock_init(&timer_group_lock[i]);
|
|
#else
|
|
#else
|
|
/* transaction timers */
|
|
/* transaction timers */
|
|
- if ((timer_semaphore= init_semaphore_set( TG_NR ) ) < 0) {
|
|
|
|
|
|
+ if (((timer_semaphore= lock_set_alloc( TG_NR ) ) == 0)||
|
|
|
|
+ (lock_set_init(timer_semaphore)==0)){
|
|
|
|
+ if (timer_semaphore) lock_set_destroy(timer_semaphore);
|
|
LOG(L_CRIT, "ERROR: lock_initialize: "
|
|
LOG(L_CRIT, "ERROR: lock_initialize: "
|
|
"transaction timer semaphore initialization failure: %s\n",
|
|
"transaction timer semaphore initialization failure: %s\n",
|
|
strerror(errno));
|
|
strerror(errno));
|
|
@@ -180,7 +114,7 @@ int lock_initialize()
|
|
|
|
|
|
for (i=0; i<TG_NR; i++) {
|
|
for (i=0; i<TG_NR; i++) {
|
|
timer_group_lock[i].semaphore_set = timer_semaphore;
|
|
timer_group_lock[i].semaphore_set = timer_semaphore;
|
|
- timer_group_lock[i].semaphore_index = timer_group[ i ];
|
|
|
|
|
|
+ timer_group_lock[i].semaphore_index = timer_group[ i ];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -189,44 +123,47 @@ int lock_initialize()
|
|
probe_run=0;
|
|
probe_run=0;
|
|
again:
|
|
again:
|
|
do {
|
|
do {
|
|
- if (entry_semaphore>0) /* clean-up previous attempt */
|
|
|
|
- semctl( entry_semaphore, 0 , IPC_RMID , 0 );
|
|
|
|
- if (reply_semaphore>0)
|
|
|
|
- semctl(reply_semaphore, 0 , IPC_RMID , 0 );
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ if (entry_semaphore!=0){ /* clean-up previous attempt */
|
|
|
|
+ lock_set_destroy(entry_semaphore);
|
|
|
|
+ lock_set_dealloc(entry_semaphore);
|
|
|
|
+ }
|
|
|
|
+ if (reply_semaphore!=0){
|
|
|
|
+ lock_set_destroy(reply_semaphore);
|
|
|
|
+ lock_set_dealloc(reply_semaphore);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (i==0){
|
|
if (i==0){
|
|
LOG(L_CRIT, "lock_initialize: could not allocate semaphore"
|
|
LOG(L_CRIT, "lock_initialize: could not allocate semaphore"
|
|
" sets\n");
|
|
" sets\n");
|
|
goto error;
|
|
goto error;
|
|
}
|
|
}
|
|
-
|
|
|
|
- entry_semaphore=init_semaphore_set( i );
|
|
|
|
- if (entry_semaphore==-1) {
|
|
|
|
|
|
+
|
|
|
|
+ if (((entry_semaphore=lock_set_alloc(i))==0)||
|
|
|
|
+ (lock_set_init(entry_semaphore)==0)) {
|
|
DBG("DEBUG: lock_initialize: entry semaphore "
|
|
DBG("DEBUG: lock_initialize: entry semaphore "
|
|
"initialization failure: %s\n", strerror( errno ) );
|
|
"initialization failure: %s\n", strerror( errno ) );
|
|
- /* Solaris: EINVAL, Linux: ENOSPC */
|
|
|
|
- if (errno==EINVAL || errno==ENOSPC ) {
|
|
|
|
- /* first time: step back and try again */
|
|
|
|
- if (probe_run==0) {
|
|
|
|
|
|
+ if (entry_semaphore){
|
|
|
|
+ lock_set_dealloc(entry_semaphore);
|
|
|
|
+ entry_semaphore=0;
|
|
|
|
+ }
|
|
|
|
+ /* first time: step back and try again */
|
|
|
|
+ if (probe_run==0) {
|
|
DBG("DEBUG: lock_initialize: first time "
|
|
DBG("DEBUG: lock_initialize: first time "
|
|
"semaphore allocation failure\n");
|
|
"semaphore allocation failure\n");
|
|
- i--;
|
|
|
|
- probe_run=1;
|
|
|
|
- continue;
|
|
|
|
|
|
+ i--;
|
|
|
|
+ probe_run=1;
|
|
|
|
+ continue;
|
|
/* failure after we stepped back; give up */
|
|
/* failure after we stepped back; give up */
|
|
- } else {
|
|
|
|
- DBG("DEBUG: lock_initialize: second time sempahore allocation failure\n");
|
|
|
|
|
|
+ } else {
|
|
|
|
+ DBG("DEBUG: lock_initialize: second time sempahore"
|
|
|
|
+ " allocation failure\n");
|
|
goto error;
|
|
goto error;
|
|
- }
|
|
|
|
- }
|
|
|
|
- /* some other error occured: give up */
|
|
|
|
- goto error;
|
|
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
+ }
|
|
/* allocation succeeded */
|
|
/* allocation succeeded */
|
|
if (probe_run==1) { /* if ok after we stepped back, we're done */
|
|
if (probe_run==1) { /* if ok after we stepped back, we're done */
|
|
break;
|
|
break;
|
|
- } else { /* if ok otherwiese, try again with larger set */
|
|
|
|
|
|
+ } else { /* if ok otherwise, try again with larger set */
|
|
if (i==SEM_MAX) break;
|
|
if (i==SEM_MAX) break;
|
|
else {
|
|
else {
|
|
i++;
|
|
i++;
|
|
@@ -234,25 +171,24 @@ again:
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while(1);
|
|
} while(1);
|
|
- sem_nr=i;
|
|
|
|
|
|
+ sem_nr=i;
|
|
|
|
|
|
- if ((reply_semaphore=init_semaphore_set( sem_nr ))<0){
|
|
|
|
- if (errno==EINVAL || errno==ENOSPC ) {
|
|
|
|
|
|
+ if (((reply_semaphore=lock_set_alloc(i))==0)||
|
|
|
|
+ (lock_set_init(reply_semaphore)==0)){
|
|
|
|
+ if (reply_semaphore){
|
|
|
|
+ lock_set_dealloc(reply_semaphore);
|
|
|
|
+ reply_semaphore=0;
|
|
|
|
+ }
|
|
DBG("DEBUG:lock_initialize: reply semaphore initialization"
|
|
DBG("DEBUG:lock_initialize: reply semaphore initialization"
|
|
" failure: %s\n", strerror(errno));
|
|
" failure: %s\n", strerror(errno));
|
|
probe_run=1;
|
|
probe_run=1;
|
|
i--;
|
|
i--;
|
|
goto again;
|
|
goto again;
|
|
- }else{
|
|
|
|
- LOG(L_CRIT, "ERROR:lock_initialize: reply semaphore initialization"
|
|
|
|
- " failure: %s\n", strerror(errno));
|
|
|
|
- goto error;
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* return success */
|
|
/* return success */
|
|
LOG(L_INFO, "INFO: semaphore arrays of size %d allocated\n", sem_nr );
|
|
LOG(L_INFO, "INFO: semaphore arrays of size %d allocated\n", sem_nr );
|
|
-#endif /* FAST_LOCK*/
|
|
|
|
|
|
+#endif /* GEN_LOCK_T_PREFERED*/
|
|
return 0;
|
|
return 0;
|
|
error:
|
|
error:
|
|
lock_cleanup();
|
|
lock_cleanup();
|
|
@@ -260,7 +196,7 @@ error:
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-#ifdef FAST_LOCK
|
|
|
|
|
|
+#ifdef GEN_LOCK_T_PREFERED
|
|
void lock_cleanup()
|
|
void lock_cleanup()
|
|
{
|
|
{
|
|
/* must check if someone uses them, for now just leave them allocated*/
|
|
/* must check if someone uses them, for now just leave them allocated*/
|
|
@@ -279,22 +215,23 @@ void lock_cleanup()
|
|
|
|
|
|
/* sibling double-check missing here; install a signal handler */
|
|
/* sibling double-check missing here; install a signal handler */
|
|
|
|
|
|
- if (entry_semaphore > 0 &&
|
|
|
|
- semctl( entry_semaphore, 0 , IPC_RMID , 0 )==-1)
|
|
|
|
- LOG(L_ERR, "ERROR: lock_cleanup, entry_semaphore cleanup failed\n");
|
|
|
|
- if (timer_semaphore > 0 &&
|
|
|
|
- semctl( timer_semaphore, 0 , IPC_RMID , 0 )==-1)
|
|
|
|
- LOG(L_ERR, "ERROR: lock_cleanup, timer_semaphore cleanup failed\n");
|
|
|
|
- if (reply_semaphore > 0 &&
|
|
|
|
- semctl( reply_semaphore, 0 , IPC_RMID , 0 )==-1)
|
|
|
|
- LOG(L_ERR, "ERROR: lock_cleanup, reply_semaphore cleanup failed\n");
|
|
|
|
-
|
|
|
|
|
|
+ if (entry_semaphore !=0){
|
|
|
|
+ lock_set_destroy(entry_semaphore);
|
|
|
|
+ lock_set_dealloc(entry_semaphore);
|
|
|
|
+ };
|
|
|
|
+ if (timer_semaphore !=0){
|
|
|
|
+ lock_set_destroy(timer_semaphore);
|
|
|
|
+ lock_set_dealloc(timer_semaphore);
|
|
|
|
+ };
|
|
|
|
+ if (reply_semaphore !=0) {
|
|
|
|
+ lock_set_destroy(reply_semaphore);
|
|
|
|
+ lock_set_dealloc(reply_semaphore);
|
|
|
|
+ };
|
|
entry_semaphore = timer_semaphore = reply_semaphore = 0;
|
|
entry_semaphore = timer_semaphore = reply_semaphore = 0;
|
|
-
|
|
|
|
if (timer_group_lock) shm_free(timer_group_lock);
|
|
if (timer_group_lock) shm_free(timer_group_lock);
|
|
|
|
|
|
}
|
|
}
|
|
-#endif /*FAST_LOCK*/
|
|
|
|
|
|
+#endif /*GEN_LOCK_T_PREFERED*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -302,20 +239,20 @@ void lock_cleanup()
|
|
|
|
|
|
int init_cell_lock( struct cell *cell )
|
|
int init_cell_lock( struct cell *cell )
|
|
{
|
|
{
|
|
-#ifdef FAST_LOCK
|
|
|
|
- init_lock(cell->reply_mutex);
|
|
|
|
|
|
+#ifdef GEN_LOCK_T_PREFERED
|
|
|
|
+ lock_init(&cell->reply_mutex);
|
|
return 0;
|
|
return 0;
|
|
#else
|
|
#else
|
|
cell->reply_mutex.semaphore_set=reply_semaphore;
|
|
cell->reply_mutex.semaphore_set=reply_semaphore;
|
|
cell->reply_mutex.semaphore_index = cell->hash_index % sem_nr;
|
|
cell->reply_mutex.semaphore_index = cell->hash_index % sem_nr;
|
|
-#endif /* FAST_LOCK */
|
|
|
|
|
|
+#endif /* GEN_LOCK_T_PREFERED */
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
int init_entry_lock( struct s_table* ht, struct entry *entry )
|
|
int init_entry_lock( struct s_table* ht, struct entry *entry )
|
|
{
|
|
{
|
|
-#ifdef FAST_LOCK
|
|
|
|
- init_lock(entry->mutex);
|
|
|
|
|
|
+#ifdef GEN_LOCK_T_PREFERED
|
|
|
|
+ lock_init(&entry->mutex);
|
|
#else
|
|
#else
|
|
/* just advice which of the available semaphores to use;
|
|
/* just advice which of the available semaphores to use;
|
|
specifically, all entries are partitioned into as
|
|
specifically, all entries are partitioned into as
|
|
@@ -332,7 +269,7 @@ int init_entry_lock( struct s_table* ht, struct entry *entry )
|
|
|
|
|
|
int release_cell_lock( struct cell *cell )
|
|
int release_cell_lock( struct cell *cell )
|
|
{
|
|
{
|
|
-#ifndef FAST_LOCK
|
|
|
|
|
|
+#ifndef GEN_LOCK_T_PREFERED
|
|
/* don't do anything here -- the init_*_lock procedures
|
|
/* don't do anything here -- the init_*_lock procedures
|
|
just advised on usage of shared semaphores but did not
|
|
just advised on usage of shared semaphores but did not
|
|
generate them
|
|
generate them
|