--- src/sema.c.orig	Sun Jul 21 21:13:59 2002
+++ src/sema.c	Mon Jul 22 19:30:15 2002
@@ -22,6 +22,10 @@
 #  include <config.h>
 #endif
 
+#ifdef HAVE_SYS_PARAM_H
+#  include <sys/param.h>
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -57,6 +61,11 @@
 #include "uaddr.h"
 #include "status.h"
 
+/* interval between busy wait tries measured in microseconds */
+#define MUTEX_BUSY_WAIT_TIME	5000
+
+pthread_mutex_t		*semaphore_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 /***********************************************************************/
 /* the following functions manage the bandwidth upload limit           */
 /* The system is build on 2 semaphores and 1 file                      */
@@ -100,6 +109,8 @@
 
 	int semid;
 
+	lp_mutex_init_(&semaphore_mutex, NULL);
+
 	fd=open(keyfile,O_CREAT|O_WRONLY|O_EXCL,0600);		/* create the file if not exists */
 	if(fd==-1)
 	{
@@ -131,7 +142,11 @@
 			{
 				close(fd);
 				/* a key exist */
+#if !(defined(BSD) && (BSD >= 199103))
 				semid=semget(key,0,IPC_ALLOC);
+#else
+				semid=semget(key,0,IPC_STAT);
+#endif
 				if(semid==-1)
 					goto create_new_sema;
 				printf("current sema found.\n");
@@ -293,8 +308,13 @@
 void check_sema_master(int semid)
 {
 	struct sembuf sb={0,-1,IPC_NOWAIT|SEM_UNDO};			/* master sema */
+	int result;
+
+	(void) lp_mutex_lock_(semaphore_mutex);
+	result = semop(semid,&sb,1);
+	(void) lp_mutex_unlock_(semaphore_mutex);
 
-	if(semop(semid,&sb,1)==0)
+	if (result==0)
 	{
 		/* to get slice, the function checks if the clock thread still runs */
 		create_sema_master(semid);
@@ -308,15 +328,29 @@
 /*******************************************/
 void get_slice(int semid, SPD_SEMA semnum)
 {
+#if !(defined(BSD) && (BSD >= 199103))
+	struct sembuf local={0,-1,0};					/* slave sema */
+#else
+	struct sembuf local={0,-1,0|IPC_NOWAIT};			/* slave sema */
+#endif
+	local.sem_num=semnum;
+
+	(void) lp_mutex_lock_(semaphore_mutex);
 	while(1)
 	{
-		struct sembuf local={0,-1,0};		/* slave sema */
-
-		local.sem_num=semnum;
-		if(semop(semid,&local,1)==0)
-		{
-			/* we have what we want */
-			return;
+		switch (semop(semid,&local,1)) {
+			case 0:	(void) lp_mutex_unlock_(semaphore_mutex);
+						/* we have what we want */
+						return;
+						break;
+			case -1:	switch(errno) {
+						case EAGAIN:			/* triggers busy wait */
+						case EINTR:			/* interrupted by system call, try again */
+									pthread_yield();
+									usleep(MUTEX_BUSY_WAIT_TIME);	/* busy wait with a small time out */
+									continue;
+									break;
+					}
 		}
 	}
 }
@@ -368,9 +402,26 @@
 /******************************/
 void lock_ul_slot_controler(int semid)
 {
+#if !(defined(BSD) && (BSD >= 199103))
 	struct sembuf get_ul_ctrl={UL_SLOT_SEMA,-1,SEM_UNDO};
+#else
+	struct sembuf get_ul_ctrl={UL_SLOT_SEMA,-1,SEM_UNDO|IPC_NOWAIT};
+#endif
+
+	(void) lp_mutex_lock_(semaphore_mutex);
+repeat:
 	/* lock the UL slot controler */
-	semop(semid,&get_ul_ctrl,1);
+	if (semop(semid,&get_ul_ctrl,1)==-1)
+		switch(errno)
+		{
+			case EAGAIN:			/* triggers busy wait */
+			case EINTR:			/* interrupted by system call, try again */
+						pthread_yield();
+						usleep(MUTEX_BUSY_WAIT_TIME);		/* busy wait with a small time out */
+						goto repeat;
+						break;
+		}
+	(void) lp_mutex_unlock_(semaphore_mutex);
 }
 
 /*********************************/
@@ -526,11 +577,28 @@
 			perror("free_one_ul_slot");
 		}
 #else
+#  if !(defined(BSD) && (BSD >= 199103))
 		struct sembuf free_one_ul_slot_op={UL_SLOT_BUSY_SEMA,-1,SEM_UNDO};
-		if(semop(semid,&free_one_ul_slot_op,1)==-1)
-		{
-			perror("free_one_ul_slot");
+#  else
+		struct sembuf free_one_ul_slot_op={UL_SLOT_BUSY_SEMA,-1,SEM_UNDO|IPC_NOWAIT};
+#  endif
+
+		(void) lp_mutex_lock_(semaphore_mutex);
+repeat:
+		if(semop(semid,&free_one_ul_slot_op,1)==-1) {
+			switch(errno) {
+				case EAGAIN:			/* triggers busy wait */
+				case EINTR:			/* interrupted by system call, try again */
+					pthread_yield();
+					usleep(MUTEX_BUSY_WAIT_TIME);          /* busy wait with a small time out */
+					goto repeat;
+					break;
+				default:
+					perror("free_one_ul_slot");
+					break;
+			}
 		}
+		(void) lp_mutex_unlock_(semaphore_mutex);
 #endif
 		nb_local_ul--;
 	}