*** sem.c.orig	Sun Feb 11 08:50:01 2001
--- sem.c	Mon Dec 24 17:41:49 2001
***************
*** 44,49 ****
--- 44,50 ----
  #include <unistd.h>
  #include <syslog.h>
  #include <sys/ipctrace.h>
+ #include <signal.h>
  extern err_handlerP err_handler;
  
  static int newary (key_t, int, int);
***************
*** 63,68 ****
--- 64,70 ----
  static int		  GFdSem	    ;		/*PCPC*/
  
  static pid_t	GProcessId = 0;
+ static HANDLE	semh[SEMMNI][SEMOPM];
  
  static void	init_globals(void)
  {
***************
*** 74,79 ****
--- 76,82 ----
  		used_sems = used_semids = max_semid = 0;
  		sem_seq = 0;
  		GProcessId = pid;
+ 		memset(semh, 0, sizeof(semh));
  	}
  }
  
***************
*** 179,193 ****
  static void FDestroySem(int Index, int Id)
  {
      HANDLE LHandle ;
-     char   LBuff[256] ;
- 
-     name_mangle(100*Id+Index, LBuff) ;
- 
-     LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff) ;
  
!     if( LHandle != NULL )
      {
  	CloseHandle ( LHandle ) ;
      }
  
      return ;
--- 182,192 ----
  static void FDestroySem(int Index, int Id)
  {
      HANDLE LHandle ;
  
!     if (LHandle = semh[Id][Index], LHandle != NULL )
      {
  	CloseHandle ( LHandle ) ;
+ 	semh[Id][Index] = NULL;
      }
  
      return ;
***************
*** 203,211 ****
  
      LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff) ;
      if( LHandle != NULL )
!     {
! 	CloseHandle ( LHandle ) ;
!     }
      LHandle = CreateSemaphore(NULL, 0, 1, LBuff) ;
  /*     LHandle = CreateSemaphore(NULL, 1, 1, LBuff) ; */
  
--- 202,208 ----
  
      LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff) ;
      if( LHandle != NULL )
! 	return LHandle;
      LHandle = CreateSemaphore(NULL, 0, 1, LBuff) ;
  /*     LHandle = CreateSemaphore(NULL, 1, 1, LBuff) ; */
  
***************
*** 291,296 ****
--- 288,295 ----
  debug_printf("newary : return -ENOMEM\n");
  		CYGWIN_IPCNT_RETURN_DECONNECT (-ENOMEM);
  	    }
+ 	    else
+ 		semh[id][LIndex] = LHandle;
  	}
  
  	/****************************************************************/
***************
*** 354,363 ****
  }
  
  static int do_semop (struct semid_ds * sma, struct sembuf * sops, int nsops,
! 		     int id)
  {
  	int i, LRet;
- 	char LStrSem[100] ;
  	HANDLE LHandle ;
  	long LVal ;
  
--- 353,361 ----
  }
  
  static int do_semop (struct semid_ds * sma, struct sembuf * sops, int nsops,
! 		     int id, const sigset_t *cursig)
  {
  	int i, LRet;
  	HANDLE LHandle ;
  	long LVal ;
  
***************
*** 365,420 ****
  
  	for (i = 0; i < nsops; i++) {
  		struct sembuf * sop = &sops[i];
  
  		/********************************************************/
  		/* PCPC							*/
  		/********************************************************/
!  		name_mangle(100*id+sop->sem_num, LStrSem) ;
! 		LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LStrSem);
! 		if( sop->sem_op >= 0 )
  		{
- 		    if (sem_connect() == 0)
- 		    {
  debug_printf("do_semop : return -EACCES\n");
  			CYGWIN_IPCNT_RETURN (-EACCES) ;
! 		    }
!     	    shareadrsem->current_nb[id].current_nb[sop->sem_num] +=
! 				sop->sem_op ;
  		    sem_deconnect() ;
  		    ReleaseSemaphore(LHandle, 1 , &LVal) ;
  		} else {
  		    if( sop->sem_flg == IPC_NOWAIT )
  		    {
! 			if( sop->sem_op + shareadrsem->current_nb[id].current_nb[sop->sem_num] <0 )
  			{
  debug_printf("do_semop : return -EAGAIN\n");
! 			    CYGWIN_IPCNT_RETURN (-EAGAIN) ;
! 			}
! 			if (sem_connect() == 0)
! 			{
! debug_printf("do_semop : return -EACCES\n");
! 			    CYGWIN_IPCNT_RETURN (-EACCES) ;
  			}
- 	    		shareadrsem->current_nb[id].current_nb[sop->sem_num] += sop->sem_op;
- 			sem_deconnect() ;
  		    } else {
! 		    while(sop->sem_op + shareadrsem->current_nb[id].current_nb[sop->sem_num] <0)
  			{
! 			  LRet = WaitForSingleObject(LHandle, 100) ;
! 			  usleep(100);
! 			  if(errno==EINTR) {
! 				CYGWIN_IPCNT_RETURN(-EINTR);
  			  }                       
! 			}
!  
! 			if (sem_connect() == 0)
! 			{
  debug_printf("do_semop : return -EACCES\n");
! 			    CYGWIN_IPCNT_RETURN (-EACCES) ;
  			}
- 			    shareadrsem->current_nb[id].current_nb[sop->sem_num] += sop->sem_op ;
- 			    sem_deconnect() ;
  		    }
  		}
  		/********************************************************/
  		/* FIN PCPC						*/
--- 363,429 ----
  
  	for (i = 0; i < nsops; i++) {
  		struct sembuf * sop = &sops[i];
+ 		int	sem_num = sop->sem_num, sem_op = sop->sem_op;
  
  		/********************************************************/
  		/* PCPC							*/
  		/********************************************************/
! 		if (LHandle = semh[id][sem_num], LHandle == NULL)
! 		{
! 			char LBuff[64];
!     			name_mangle(100 * id + sem_num, LBuff) ;
! 			if (LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff), LHandle == NULL)
! 				CYGWIN_IPCNT_RETURN (-EINVAL);
! 			semh[id][sem_num] = LHandle;
! 		}
! 		if (sem_connect() == 0)
  		{
  debug_printf("do_semop : return -EACCES\n");
  			CYGWIN_IPCNT_RETURN (-EACCES) ;
! 		}
! 		if (sem_op >= 0)
! 		{
! 		    shareadrsem->current_nb[id].current_nb[sem_num] +=
! 				sem_op ;
  		    sem_deconnect() ;
  		    ReleaseSemaphore(LHandle, 1 , &LVal) ;
  		} else {
  		    if( sop->sem_flg == IPC_NOWAIT )
  		    {
! 			if (sem_op + shareadrsem->current_nb[id].current_nb[sem_num] < 0)
  			{
  debug_printf("do_semop : return -EAGAIN\n");
! 			    CYGWIN_IPCNT_RETURN_DECONNECT (-EAGAIN) ;
  			}
  		    } else {
! 		    sigset_t	fulsig;
! 		    while (sem_op + shareadrsem->current_nb[id].current_nb[sem_num] < 0)
  			{
! 			  sem_deconnect() ;
! 			  do
! 			  {
! 			  	LRet = WaitForSingleObject(LHandle, 100);
! 				/*
! 				 * Fire suspended signals.
! 				 * This is the only place where signals could
! 				 * fire in do_semop(). 
! 				 */
! 				sigprocmask(SIG_SETMASK, cursig, &fulsig);
! 				/*
! 				 * block signals again.
! 				 */
! 				sigprocmask(SIG_SETMASK, &fulsig, NULL);
  			  }                       
! 			  while (sem_op + shareadrsem->current_nb[id].current_nb[sem_num] < 0);
! 			  if (sem_connect() == 0)
! 			  {
  debug_printf("do_semop : return -EACCES\n");
! 			    	CYGWIN_IPCNT_RETURN (-EACCES) ;
! 			  }
  			}
  		    }
+ 		    shareadrsem->current_nb[id].current_nb[sem_num] += sem_op ;
+ 		    sem_deconnect() ;
  		}
  		/********************************************************/
  		/* FIN PCPC						*/
***************
*** 460,466 ****
  	struct ipc_perm *ipcp;
  	unsigned int nsems;
  	ushort *array = NULL;
- 	char LBuff[100] ;
  	HANDLE LHandle ;
  	long LPrevious ;
  
--- 469,474 ----
***************
*** 588,603 ****
  		CYGWIN_IPCNT_RETURN_DECONNECT (shareadrsem->current_nb[id].current_nb[semnum]);
  
  	case SETVAL:
! 		name_mangle(100*id+semnum, (char *)LBuff) ;
! 
! 		LHandle =
! 		OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff) ;
! 		if( LHandle != NULL )
! 		{
! 		    if( arg.val > shareadrsem->current_nb[id].current_nb[semnum] )
! 				ReleaseSemaphore(LHandle,1,&LPrevious) ;
!             shareadrsem->current_nb[id].current_nb[semnum] = arg.val ;
! 		}
  debug_printf("semctl : SETVAL : return 0\n");
  		CYGWIN_IPCNT_RETURN_DECONNECT (0);
  		break;
--- 596,612 ----
  		CYGWIN_IPCNT_RETURN_DECONNECT (shareadrsem->current_nb[id].current_nb[semnum]);
  
  	case SETVAL:
! 		if (LHandle = semh[id][semnum], LHandle == NULL)
! 		{
! 			char LBuff[64];
!     			name_mangle(100 * id + semnum, LBuff) ;
! 			if (LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff), LHandle == NULL)
! 				CYGWIN_IPCNT_RETURN_DECONNECT (-EINVAL);
! 			semh[id][semnum] = LHandle;
! 		}
! 		if( arg.val > shareadrsem->current_nb[id].current_nb[semnum] )
! 			ReleaseSemaphore(LHandle,1,&LPrevious) ;
!                 shareadrsem->current_nb[id].current_nb[semnum] = arg.val ;
  debug_printf("semctl : SETVAL : return 0\n");
  		CYGWIN_IPCNT_RETURN_DECONNECT (0);
  		break;
***************
*** 612,627 ****
  		array = arg.array ;
  		for (i=0; i<semnum; i++)
  		{
! 		  name_mangle(100*id+i, LBuff) ;
! 
! 		    LHandle =
! 			OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff) ;
! 		    if( LHandle != NULL )
  		    {
! 			ReleaseSemaphore(LHandle, array[i], &LPrevious) ;
! 	        	shareadrsem->current_nb[id].current_nb[i] +=
! 			    array[i] ;
  		    }
  		}
  debug_printf("semctl : SETALL : return 0\n");
  		CYGWIN_IPCNT_RETURN_DECONNECT (0);
--- 621,637 ----
  		array = arg.array ;
  		for (i=0; i<semnum; i++)
  		{
! 		    if (LHandle = semh[id][i], LHandle == NULL)
  		    {
! 			char LBuff[64];
!     			name_mangle(100 * id + i, LBuff) ;
! 			if (LHandle = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, LBuff), LHandle == NULL)
! 				CYGWIN_IPCNT_RETURN_DECONNECT (-EINVAL);
! 			semh[id][i] = LHandle;
  		    }
+ 		    ReleaseSemaphore(LHandle, array[i], &LPrevious) ;
+ 	            shareadrsem->current_nb[id].current_nb[i] +=
+ 			    array[i] ;
  		}
  debug_printf("semctl : SETALL : return 0\n");
  		CYGWIN_IPCNT_RETURN_DECONNECT (0);
***************
*** 670,675 ****
--- 680,686 ----
  	unsigned int i;
  	struct semid_ds *sma;
  	struct sembuf sops[SEMOPM], *sop;
+ 	sigset_t	cursig, fulsig;
  
  debug_printf("semop : semid=%X tsops=%p nsops=%X\n",semid,tsops,nsops);
  	if (nsops < 1 || semid < 0)
***************
*** 690,702 ****
  
  	memcpy (sops, tsops, nsops * sizeof(struct sembuf));
  
- 	if (sem_connect() == 0)
- 	{
- debug_printf("semop : return -EACCES\n");
- 	 CYGWIN_IPCNT_RETURN (-EACCES) ;
- 	}
- 	sem_deconnect() ;
- 
  	id = (unsigned int) semid % SEMMNI;
  	if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
  	{
--- 701,706 ----
***************
*** 719,725 ****
  		}
  	}
  
! 	error = do_semop(sma, sops, nsops, id);
  debug_printf("semop : return %d\n",error);
  	return (error) ;
  }
--- 723,740 ----
  		}
  	}
  
! 	/*
! 	 * Block all maskable signals.
! 	 * Intermediate signal calls e.g. during win APIs
! 	 * are harmful.
! 	 */
! 	sigfillset(&fulsig);
! 	sigprocmask(SIG_SETMASK, &fulsig, &cursig);
! 	error = do_semop(sma, sops, nsops, id, &cursig);
  debug_printf("semop : return %d\n",error);
+ 	/*
+ 	 * Restore the previously saved signal mask.
+ 	 */
+ 	sigprocmask(SIG_SETMASK, &cursig, NULL);
  	return (error) ;
  }
