First test of Darwin port with POSIX semaphore code.

This commit is contained in:
Tom Lane 2002-05-05 01:03:26 +00:00
parent 3e48c66136
commit 8df5625966
4 changed files with 8 additions and 407 deletions

View File

@ -4,7 +4,7 @@
# Makefile for port/darwin
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/port/darwin/Makefile,v 1.2 2001/11/08 04:24:03 tgl Exp $
# $Header: /cvsroot/pgsql/src/backend/port/darwin/Makefile,v 1.3 2002/05/05 01:03:26 tgl Exp $
#
#-------------------------------------------------------------------------
@ -12,7 +12,7 @@ subdir = src/backend/port/darwin
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
OBJS = sem.o system.o
OBJS = system.o
all: SUBSYS.o

View File

@ -16,23 +16,11 @@ Radar Bug#s 2767956, 2683531, 2805147. One hopes we can retire this
kluge in the not too distant future.
As of PostgreSQL 7.2 and Mac OS X 10.1, one should expect warnings
As of PostgreSQL 7.3 and Mac OS X 10.1, one should expect warnings
like these while linking the backend:
/usr/bin/ld: warning unused multiple definitions of symbol _system
port/SUBSYS.o definition of _system in section (__TEXT,__text)
/usr/lib/libm.dylib(system.o) unused definition of _system
/usr/bin/ld: warning unused multiple definitions of symbol _semctl
port/SUBSYS.o definition of _semctl in section (__TEXT,__text)
/usr/lib/libm.dylib(semctl.o) unused definition of _semctl
/usr/bin/ld: warning unused multiple definitions of symbol _semget
port/SUBSYS.o definition of _semget in section (__TEXT,__text)
/usr/lib/libm.dylib(semget.o) unused definition of _semget
/usr/bin/ld: warning unused multiple definitions of symbol _semop
port/SUBSYS.o definition of _semop in section (__TEXT,__text)
/usr/lib/libm.dylib(semop.o) unused definition of _semop
The first of these shows us overriding system() per the above-described
hack. The rest show sem.c overriding the nonfunctional semaphore stubs
in libc. (Perhaps sem.c can also be retired someday, but semget support
is reportedly not high on Apple's to-do list.)
These are due to overriding system() per the above-described hack.

View File

@ -1,389 +0,0 @@
/*-------------------------------------------------------------------------
*
* sem.c
* System V Semaphore Emulation
*
* Copyright (c) 1999, repas AEG Automation GmbH
*
* 2000-12-1 pmb@mac.com
* - changed from anonymous to named semaphores for darwin
* - this required changing sem_info from containig an array of sem_t to an array of sem_t*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/port/darwin/Attic/sem.c,v 1.5 2001/10/25 05:49:40 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <errno.h>
#include <semaphore.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "miscadmin.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "port/darwin/sem.h"
#define SEMMAX IPC_NMAXSEM
#define OPMAX 8
#define MODE 0700
#define SHM_INFO_NAME "SysV_Sem_Info"
#define SEM_NAME "/pgsql-darwin"
struct pending_ops
{
int op[OPMAX]; /* array of pending operations */
int idx; /* index of first free array member */
};
struct sem_set_info
{
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 */
};
struct sem_info
{
sem_t *sem;
int nsets;
/* there are actually nsets of these: */
struct sem_set_info set[1]; /* VARIABLE LENGTH ARRAY */
};
static struct sem_info *SemInfo = (struct sem_info *) - 1;
int
semctl(int semid, int semnum, int cmd, /* ... */ union semun arg)
{
int r = 0;
sem_wait(SemInfo->sem);
if (semid < 0 || semid >= SemInfo->nsets ||
semnum < 0 || semnum >= SemInfo->set[semid].nsems)
{
sem_post(SemInfo->sem);
errno = EINVAL;
return -1;
}
switch (cmd)
{
case GETNCNT:
r = SemInfo->set[semid].semV[semnum].semncnt;
break;
case GETPID:
r = SemInfo->set[semid].semV[semnum].sempid;
break;
case GETVAL:
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].semV[semnum].semval;
break;
case SETVAL:
SemInfo->set[semid].semV[semnum].semval = arg.val;
break;
case SETALL:
for (semnum = 0; semnum < SemInfo->set[semid].nsems; 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_close(SemInfo->set[semid].sem[semnum]) == -1)
r = -1;
}
SemInfo->set[semid].key = -1;
SemInfo->set[semid].nsems = 0;
break;
default:
sem_post(SemInfo->sem);
errno = EINVAL;
return -1;
}
sem_post(SemInfo->sem);
return r;
}
int
semget(key_t key, int nsems, int semflg)
{
int fd,
semid,
semnum,
nsets;
int exist = 0;
Size sem_info_size;
char semname[64];
if (nsems < 0 || nsems > SEMMAX)
{
#ifdef DEBUG_IPC
fprintf(stderr, "darwin semget aborting because nsems out of range. (%d)\n", nsems);
#endif
errno = EINVAL;
return -1;
}
/* open and map shared memory */
if (SemInfo == (struct sem_info *) - 1)
{
#ifdef DEBUG_IPC
fprintf(stderr, "darwin initializing shared mem for semaphore shim.\n");
#endif
/* test if the shared memory already exists */
fd = shm_open(SHM_INFO_NAME, O_RDWR | O_CREAT | O_EXCL, MODE);
if (fd == -1 && errno == EEXIST)
{
/* exist = 1; */
shm_unlink(SHM_INFO_NAME);
fd = shm_open(SHM_INFO_NAME, O_RDWR | O_CREAT | O_EXCL, MODE);
}
if (fd == -1)
return fd;
shm_unlink(SHM_INFO_NAME);
/* The size may only be set once. Ignore errors. */
nsets = PROC_SEM_MAP_ENTRIES(MaxBackends);
sem_info_size = sizeof(struct sem_info) + (nsets - 1) * sizeof(struct sem_set_info);
ftruncate(fd, sem_info_size);
SemInfo = mmap(NULL, sem_info_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (SemInfo == MAP_FAILED)
return -1;
if (!exist)
{
/* initialize shared memory */
memset(SemInfo, 0, sem_info_size);
SemInfo->nsets = nsets;
for (semid = 0; semid < nsets; semid++)
SemInfo->set[semid].key = -1;
/* create semaphore for locking */
sprintf(semname, "%s-map", SEM_NAME);
#ifdef DEBUG_IPC
fprintf(stderr, "darwin creating sem %s to cover shared mem.\n", semname);
#endif
SemInfo->sem = sem_open(semname, O_CREAT, semflg & 0777, 1);
sem_unlink(semname);
}
}
sem_wait(SemInfo->sem);
nsets = SemInfo->nsets;
if (key != IPC_PRIVATE)
{
/* search existing element */
semid = 0;
while (semid < nsets && SemInfo->set[semid].key != key)
semid++;
if (!(semflg & IPC_CREAT) && semid >= nsets)
{
sem_post(SemInfo->sem);
errno = ENOENT;
return -1;
}
else if (semid < nsets)
{
if (semflg & IPC_CREAT && semflg & IPC_EXCL)
{
sem_post(SemInfo->sem);
errno = EEXIST;
return -1;
}
else
{
if (nsems != 0 && SemInfo->set[semid].nsems < nsems)
{
#ifdef DEBUG_IPC
fprintf(stderr, "darwin semget failed because if (nsems != 0 && SemInfo->set[semid].nsems < nsems) %d %d\n",
nsems, SemInfo->set[semid].nsems);
#endif
sem_post(SemInfo->sem);
errno = EINVAL;
return -1;
}
sem_post(SemInfo->sem);
return semid;
}
}
}
/* search first free element */
semid = 0;
while (semid < nsets && SemInfo->set[semid].key != -1)
semid++;
if (semid >= nsets)
{
#ifdef DEBUG_IPC
fprintf(stderr, "darwin semget failed because all keys were -1\n");
#endif
sem_post(SemInfo->sem);
errno = ENOSPC;
return -1;
}
for (semnum = 0; semnum < nsems; semnum++)
{
sprintf(semname, "%s-%d-%d", SEM_NAME, semid, semnum);
#ifdef DEBUG_IPC
fprintf(stderr, "darwin creating sem %s to cover set %d num %dm.\n", semname, semid, semnum);
#endif
SemInfo->set[semid].sem[semnum] = sem_open(semname, O_CREAT, semflg & 0777, 0);
sem_unlink(semname);
/* Currently sem_init always returns -1. */
#ifdef NOT_USED
if (sem_init(&SemInfo->set[semid].sem[semnum], 1, 0) == -1)
{
int semnum1;
for (semnum1 = 0; semnum1 < semnum; semnum1++)
sem_close(SemInfo->set[semid].sem[semnum1]);
sem_post(SemInfo->sem);
return -1;
}
#endif
}
SemInfo->set[semid].key = key;
SemInfo->set[semid].nsems = nsems;
sem_post(SemInfo->sem);
return semid;
}
int
semop(int semid, struct sembuf * sops, size_t nsops)
{
int i,
r = 0,
r1,
errno1 = 0,
op;
sem_wait(SemInfo->sem);
if (semid < 0 || semid >= SemInfo->nsets)
{
sem_post(SemInfo->sem);
errno = EINVAL;
return -1;
}
for (i = 0; i < nsops; i++)
{
if ( /* sops[i].sem_num < 0 || */ sops[i].sem_num >= SemInfo->set[semid].nsems)
{
sem_post(SemInfo->sem);
errno = EFBIG;
return -1;
}
}
for (i = 0; i < nsops; i++)
{
if (sops[i].sem_op < 0)
{
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
SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op;
}
else if (sops[i].sem_op > 0)
{
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].semV[sops[i].sem_num].sempid = getpid();
}
sem_post(SemInfo->sem);
errno = errno1;
return r;
}

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/port/posix_sema.c,v 1.1 2002/05/05 00:03:28 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/port/posix_sema.c,v 1.2 2002/05/05 01:03:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,6 +21,8 @@
#include <signal.h>
#include <unistd.h>
#include "miscadmin.h"
#include "storage/ipc.h"
#include "storage/pg_sema.h"
@ -70,7 +72,7 @@ PosixSemaphoreCreate(void)
mySem = sem_open(semname, O_CREAT | O_EXCL,
(mode_t) IPCProtection, (unsigned) 1);
if (mySem != SEM_FAILED)
if (mySem != (sem_t *) SEM_FAILED)
break;
/* Loop if error indicates a collision */