*
*
* 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];
};
int semctl( int semid, int semnum, int cmd, /*...*/union semun arg )
{
- int r;
+ int r = 0;
sem_wait( &SemInfo->sem );
}
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 ) {
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 );
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 );
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 );
*
*
* 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 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 */
/*
-* 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
*
*
* 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 )
{
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;
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 '-':
}
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' );