OSDN Git Service

> I have improved the System V semaphore emulation of the QNX4 port.
authorBruce Momjian <bruce@momjian.us>
Tue, 14 Mar 2000 18:12:06 +0000 (18:12 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 14 Mar 2000 18:12:06 +0000 (18:12 +0000)
Please
> apply the attached patch to
>
> backend/port/qnx4
>
> Andreas Kardos
>

src/backend/port/qnx4/sem.c
src/backend/port/qnx4/sem.h
src/backend/port/qnx4/tstsem.c

index de98180..4263294 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/sem.c,v 1.1 1999/12/16 16:52:52 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/sem.c,v 1.2 2000/03/14 18:12:06 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <sys/mman.h>
 #include "postgres.h"
 #include "storage/ipc.h"
+#include "storage/proc.h"
 #include <sys/sem.h>
 
 
-#define SETMAX    32
-#define SEMMAX    16
+#define SETMAX ((MAXBACKENDS + PROC_NSEMS_PER_SET - 1) / PROC_NSEMS_PER_SET)
+#define SEMMAX (PROC_NSEMS_PER_SET)
+#define OPMAX  8
 
-#define MODE    0777
+#define MODE    0700
 #define SHM_INFO_NAME   "SysV_Sem_Info"
 
 
+struct pending_ops {
+    int                op[OPMAX];              /* array of pending operations */
+    int                idx;                    /* index of first free array member */
+};
+
 struct sem_info {
   sem_t sem;
   struct {
-    key_t  key;
-    int    nsems;
-    sem_t  sem[SEMMAX];  /* array of semaphores */
-    pid_t  pid[SEMMAX];  /* array of PIDs */
+    key_t              key;
+    int                        nsems;
+    sem_t              sem[SEMMAX];            /* array of POSIX semaphores */
+    struct sem         semV[SEMMAX];           /* array of System V semaphore structures */
+    struct pending_ops pendingOps[SEMMAX];     /* array of pending operations */
   } set[SETMAX];
 };
 
@@ -46,7 +54,7 @@ static struct sem_info  *SemInfo = ( struct sem_info * )-1;
 
 int semctl( int semid, int semnum, int cmd, /*...*/union semun arg )
 {
-  int r;
+  int r = 0;
 
   sem_wait( &SemInfo->sem );
 
@@ -58,30 +66,38 @@ int semctl( int semid, int semnum, int cmd, /*...*/union semun arg )
   }
 
   switch( cmd )  {
+    case GETNCNT:
+      r = SemInfo->set[semid].semV[semnum].semncnt;
+      break;
+
     case GETPID:
-      r = SemInfo->set[semid].pid[semnum];
+      r = SemInfo->set[semid].semV[semnum].sempid;
       break;
 
     case GETVAL:
-      r = SemInfo->set[semid].sem[semnum].value;
+      r = SemInfo->set[semid].semV[semnum].semval;
       break;
 
     case GETALL:
       for( semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++ )  {
-        arg.array[semnum] = SemInfo->set[semid].sem[semnum].value;
+        arg.array[semnum] = SemInfo->set[semid].semV[semnum].semval;
       }
       break;
 
     case SETVAL:
-      SemInfo->set[semid].sem[semnum].value = arg.val;
+      SemInfo->set[semid].semV[semnum].semval = arg.val;
       break;
 
     case SETALL:
       for( semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++ )  {
-        SemInfo->set[semid].sem[semnum].value = arg.array[semnum];
+        SemInfo->set[semid].semV[semnum].semval = arg.array[semnum];
       }
       break;
 
+    case GETZCNT:
+      r = SemInfo->set[semid].semV[semnum].semzcnt;
+      break;
+
     case IPC_RMID:
       for( semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++ )  {
         if( sem_destroy( &SemInfo->set[semid].sem[semnum] ) == -1 )  {
@@ -121,12 +137,16 @@ int semget( key_t key, int nsems, int semflg )
       exist = 1;
       fd = shm_open( SHM_INFO_NAME, O_RDWR | O_CREAT, MODE );
     }
-    if( fd == -1 ) return fd;
+    if( fd == -1 ) {
+      return fd;
+    }
     /* The size may only be set once. Ignore errors. */
     ltrunc( fd, sizeof( struct sem_info ), SEEK_SET );
     SemInfo = mmap( NULL, sizeof( struct sem_info ),
                     PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
-    if( SemInfo == MAP_FAILED ) return -1;
+    if( SemInfo == MAP_FAILED )  {
+      return -1;
+    }
     if( !exist )  {
       /* create semaphore for locking */
       sem_init( &SemInfo->sem, 1, 1 );
@@ -196,12 +216,12 @@ int semget( key_t key, int nsems, int semflg )
 
   sem_post( &SemInfo->sem );
 
-  return 0;
+  return semid;
 }
 
 int semop( int semid, struct sembuf *sops, size_t nsops )
 {
-  int i, j, r = 0, r1, errno1 = 0;
+  int i, r = 0, r1, errno1 = 0, op;
 
   sem_wait( &SemInfo->sem );
 
@@ -220,38 +240,67 @@ int semop( int semid, struct sembuf *sops, size_t nsops )
 
   for( i = 0; i < nsops; i++ )  {
     if( sops[i].sem_op < 0 )  {
-      if( sops[i].sem_flg & IPC_NOWAIT )  {
-        for( j = 0; j < -sops[i].sem_op; j++ )  {
-          if( sem_trywait( &SemInfo->set[semid].sem[sops[i].sem_num] ) )  {
-            errno1 = errno;
-            r = -1;
-          }
+      if( SemInfo->set[semid].semV[sops[i].sem_num].semval < -sops[i].sem_op )  {
+        if( sops[i].sem_flg & IPC_NOWAIT )  {
+          sem_post( &SemInfo->sem );
+          errno = EAGAIN;
+          return -1;
         }
+        SemInfo->set[semid].semV[sops[i].sem_num].semncnt++;
+        if( SemInfo->set[semid].pendingOps[sops[i].sem_num].idx >= OPMAX )  {
+          /* pending operations array overflow */
+          sem_post( &SemInfo->sem );
+          errno = ERANGE;
+          return -1;
+        }
+        SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx++] = sops[i].sem_op;
+        /* suspend */
+        sem_post( &SemInfo->sem ); /* avoid deadlock */
+        r1 = sem_wait( &SemInfo->set[semid].sem[sops[i].sem_num] );
+        sem_wait( &SemInfo->sem );
+        if( r1 )  {
+          errno1 = errno;
+          r = r1;
+          /* remove pending operation */
+          SemInfo->set[semid].pendingOps[sops[i].sem_num].op[--SemInfo->set[semid].pendingOps[sops[i].sem_num].idx] = 0;
+        }
+        else  {
+          SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op;
+        }
+        SemInfo->set[semid].semV[sops[i].sem_num].semncnt--;
       }
       else  {
-        for( j = 0; j < -sops[i].sem_op; j++ )  {
-          sem_post( &SemInfo->sem ); /* avoid deadlock */
-          r1 = sem_wait( &SemInfo->set[semid].sem[sops[i].sem_num] );
-          sem_wait( &SemInfo->sem );
-          if( r1 )  {
-            errno1 = errno;
-            r = r1;
-          }
-        }
+        SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op;
       }
     }
     else if( sops[i].sem_op > 0 )  {
-      for( j = 0; j < sops[i].sem_op; j++ )  {
-        if( sem_post( &SemInfo->set[semid].sem[sops[i].sem_num] ) )  {
-          errno1 = errno;
-          r = -1;
+      SemInfo->set[semid].semV[sops[i].sem_num].semval += sops[i].sem_op;
+      op = sops[i].sem_op;
+      while( op > 0 && SemInfo->set[semid].pendingOps[sops[i].sem_num].idx > 0 )  {    /* operations pending */
+        if( SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx-1] + op >= 0 )  {
+          /* unsuspend processes */
+          if( sem_post( &SemInfo->set[semid].sem[sops[i].sem_num] ) )  {
+            errno1 = errno;
+            r = -1;
+          }
+          /* adjust pending operations */
+          op += SemInfo->set[semid].pendingOps[sops[i].sem_num].op[--SemInfo->set[semid].pendingOps[sops[i].sem_num].idx];
+          SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx] = 0;
+        }
+        else  {
+          /* adjust pending operations */
+          SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx-1] += op;
+          op = 0;
         }
       }
     }
     else /* sops[i].sem_op == 0 */  {
       /* not supported */
+      sem_post( &SemInfo->sem );
+      errno = ENOSYS;
+      return -1;
     }
-    SemInfo->set[semid].pid[sops[i].sem_num] = getpid( );
+    SemInfo->set[semid].semV[sops[i].sem_num].sempid = getpid( );
   }
 
   sem_post( &SemInfo->sem );
index 6f8f288..a42d7fd 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/sem.h,v 1.1 1999/12/16 16:52:52 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/sem.h,v 1.2 2000/03/14 18:12:06 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <sys/ipc.h>
 
-#ifdef __cplusplus
+#ifdef __cplusplus
 extern "C" {
 #endif
 
 /*
-*       Semctl Command Definitions.
+ *     Semctl Command Definitions.
  */
 
-#define GETNCNT 3      /* get semncnt */
-#define GETPID  4      /* get sempid */
-#define GETVAL  5      /* get semval */
-#define GETALL  6      /* get all semval's */
-#define GETZCNT 7      /* get semzcnt */
-#define SETVAL  8      /* set semval */
-#define SETALL  9      /* set all semval's */
+#define GETNCNT        3       /* get semncnt */
+#define GETPID       /* get sempid */
+#define GETVAL       /* get semval */
+#define GETALL       /* get all semval's */
+#define GETZCNT        7       /* get semzcnt */
+#define SETVAL       /* set semval */
+#define SETALL       /* set all semval's */
 
 /*
-* User semaphore template for semop system calls.
+ *     There is one semaphore structure for each semaphore in the system.
+ */
+
+struct sem {
+       ushort_t        semval;         /* semaphore text map address   */
+       pid_t           sempid;         /* pid of last operation        */
+       ushort_t        semncnt;        /* # awaiting semval > cval     */
+       ushort_t        semzcnt;        /* # awaiting semval = 0        */
+};
+
+/*
+ * User semaphore template for semop system calls.
  */
 
 struct sembuf {
-        ushort_t        sem_num;        /* semaphore # */
-        short           sem_op;         /* semaphore operation */
-        short           sem_flg;        /* operation flags */
+       ushort_t        sem_num;        /* semaphore #                  */
+       short           sem_op;         /* semaphore operation          */
+       short           sem_flg;        /* operation flags              */
 };
 
 extern int semctl( int semid, int semnum, int cmd, /*...*/union semun arg );
 extern int semget( key_t key, int nsems, int semflg );
 extern int semop( int semid, struct sembuf *sops, size_t nsops );
 
-#ifdef __cplusplus
+#ifdef __cplusplus
 }
 #endif
 
index fee5d86..a604d95 100644 (file)
@@ -7,12 +7,13 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/tstsem.c,v 1.1 1999/12/16 16:52:52 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/port/qnx4/Attic/tstsem.c,v 1.2 2000/03/14 18:12:06 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/sem.h>
 
 
-#define SEMMAX  1
-#define OPSMAX  1
+#define SEMMAX 16
+#define OPSMAX 1
 
+static int semid;
+
+static void sig_handler( int sig_no )
+{
+  union semun arg;
+  int i = semctl( semid, 0, GETNCNT, arg );
+  if( i == -1 ) perror( "semctl" );
+  else printf( "semval = %d\n", i );
+}
 
 int main( int argc, char **argv )
 {
@@ -34,7 +44,7 @@ int main( int argc, char **argv )
   int     nsems = SEMMAX;
   int     semflg = 0;
   int     unlink = 0;
-  int     semid, i;
+  int     i;
   struct sembuf sops[OPSMAX];
   u_short array[SEMMAX];
   union semun arg;
@@ -67,8 +77,11 @@ int main( int argc, char **argv )
     exit( semid );
   }
 
+  /* test signal interrupts */
+  signal( SIGTERM, sig_handler );
+
   do  {
-    printf( "(-)sem_op, (+)sem_op, (G)ETVAL, (S)ETVAL, GET(P)ID, GET(A)LL, SETA(L)L, e(x)it: " );
+    printf( "(-)sem_op, (+)sem_op, (G)ETVAL, (S)ETVAL, GET(P)ID, GET(A)LL, SETA(L)L, GET(N)CNT, GET(Z)CNT, e(x)it: " );
     scanf( "%s", s );
     switch( s[0] )  {
       case '-': 
@@ -122,6 +135,20 @@ int main( int argc, char **argv )
         }
         if( semctl( semid, 0, SETALL, arg ) == -1 )perror( "semctl" );
         break;
+
+      case 'N': 
+      case 'n': 
+        i = semctl( semid, 0, GETNCNT, arg );
+        if( i == -1 ) perror( "semctl" );
+        else printf( "semval = %d\n", i );
+        break;
+
+      case 'Z': 
+      case 'z': 
+        i = semctl( semid, 0, GETZCNT, arg );
+        if( i == -1 ) perror( "semctl" );
+        else printf( "semval = %d\n", i );
+        break;
     }
   }
   while( s[0] != 'x' );