The fix is 2 fold. First, we need to prevent the client from blocking. Then, we need the client to correctly implement the hide absolute option so that working it can properly process upload requests.
Since we are having problems with semaphores blocking ALL threads. We could tell them not to block then write them as a busy wait construct with a small time interval between retries.
Investigating src/sema.c source code, the only blocking calls are semop(2) with -1 as operation parameters. Consequently, we will both add IPC_NOWAIT to flag parameters in all of those and rewrite them as busy wait constructs.
Nevertheless, this does not solve the contention problem. Semaphores are built for protection of a shared resource; thus, we should add a thread appropriate mutual exclusion mechanism. The most appropriate seems to be mutexes.
Also, whenever we busy wait, we will call
from pthread(3), increasing the chance that a concurrent thread releases the semaphore before our next try.See the example Example 1-1
Example 1-1. Replacing a blocking semaphore operation with a non-blocking busy wait one
Replace
void get_slice(int semid, SPD_SEMA semnum) 2 { while(1) 4 { struct sembuf local={0,-1,0}; /* slave sema */ 6 local.sem_num=semnum; 8 if(semop(semid,&local,1)==0) { 10 /* we have what we want */ return; 12 } } 14 }
with hopefully portable
#include <sys/param.h> 2 /* interval between busy wait tries measured in microseconds */ 4 #define MUTEX_BUSY_WAIT_TIME 5000 6 void get_slice(int semid, SPD_SEMA semnum) { 8 #if !(defined(BSD) && (BSD >= 199103)) struct sembuf local={0,-1,0}; /* slave sema */ 10 #else struct sembuf local={0,-1,0|IPC_NOWAIT}; /* slave sema */ 12 #endif local.sem_num=semnum; 14 (void) lp_mutex_lock_(semaphore_mutex); 16 while(1) { 18 switch (semop(semid,&local,1)) { case 0: (void) lp_mutex_unlock_(semaphore_mutex); 20 /* we have what we want */ return; 22 break; case -1: switch(errno) { 24 case EAGAIN: /* triggers busy wait */ case EINTR: /* interrupted by system call, try again */ 26 pthread_yield(); usleep(MUTEX_BUSY_WAIT_TIME); /* busy wait with a small time out */ 28 continue; break; 30 } } 32 } } 34
Copy my lp_mutex.c BSD licensed mutex handling routines to subdirectory src
Apply patch patch-configure.in against configure.in to enable detection of header file sys/param.h which is used to detect if current system is BSD based
Apply patch patch-src::Makefile.am against src/Makefile.am to connect lp_mutex.c to the build
Apply patch patch-src::sema.c against src/sema.c hopefully adding more portability to the semaphore code
First, we need to pass the correct upload requests to
routine that checks if the files exist. Then, we have to make sure that this checking routine understands the requests.We will move the hide absolute option handling routines before the check routine. Then, we will add a specific handling to the check routine.
Apply patch patch-src::dc_manage.c against src/dc_manage.c so that the checking routine receives a correct file request
Apply patch patch-src::mydb.c against src/mydb.c so that the checking routine understands the file requested
For questions about FreeBSD, read the <documentation>.
For questions about the FreeBSD ports
system, e-mail <ports@FreeBSD.org>.
For questions about this documentation, e-mail <lioux@FreeBSD.org>.