Commit 8df56259 authored by Tom Lane's avatar Tom Lane

First test of Darwin port with POSIX semaphore code.

parent 3e48c661
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for port/darwin # Makefile for port/darwin
# #
# IDENTIFICATION # 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 ...@@ -12,7 +12,7 @@ subdir = src/backend/port/darwin
top_builddir = ../../../.. top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = sem.o system.o OBJS = system.o
all: SUBSYS.o all: SUBSYS.o
......
...@@ -16,23 +16,11 @@ Radar Bug#s 2767956, 2683531, 2805147. One hopes we can retire this ...@@ -16,23 +16,11 @@ Radar Bug#s 2767956, 2683531, 2805147. One hopes we can retire this
kluge in the not too distant future. 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: like these while linking the backend:
/usr/bin/ld: warning unused multiple definitions of symbol _system /usr/bin/ld: warning unused multiple definitions of symbol _system
port/SUBSYS.o definition of _system in section (__TEXT,__text) port/SUBSYS.o definition of _system in section (__TEXT,__text)
/usr/lib/libm.dylib(system.o) unused definition of _system /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 These are due to overriding system() per the above-described hack.
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.)
/*-------------------------------------------------------------------------
*
* 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;
}
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 @@ ...@@ -21,6 +21,8 @@
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include "miscadmin.h"
#include "storage/ipc.h"
#include "storage/pg_sema.h" #include "storage/pg_sema.h"
...@@ -70,7 +72,7 @@ PosixSemaphoreCreate(void) ...@@ -70,7 +72,7 @@ PosixSemaphoreCreate(void)
mySem = sem_open(semname, O_CREAT | O_EXCL, mySem = sem_open(semname, O_CREAT | O_EXCL,
(mode_t) IPCProtection, (unsigned) 1); (mode_t) IPCProtection, (unsigned) 1);
if (mySem != SEM_FAILED) if (mySem != (sem_t *) SEM_FAILED)
break; break;
/* Loop if error indicates a collision */ /* Loop if error indicates a collision */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment