1 /*-------------------------------------------------------------------------
4 * System V Semaphore Emulation
6 * Copyright (c) 1999, repas AEG Automation GmbH
8 * 2000-12-1 pmb@mac.com
9 * - changed from anonymous to named semaphores for darwin
10 * - this required changing sem_info from containig an array of sem_t to an array of sem_t*
13 * $Header: /cvsroot/pgsql/src/backend/port/darwin/Attic/sem.c,v 1.1 2000/12/11 00:49:54 tgl Exp $
15 *-------------------------------------------------------------------------
19 #include <semaphore.h>
21 #include <sys/types.h>
26 #include "storage/ipc.h"
27 #include "storage/proc.h"
28 #include "port/darwin/sem.h"
30 #define SEMMAX IPC_NMAXSEM
31 #define SETMAX ((MAXBACKENDS + SEMMAX - 1) / SEMMAX)
35 #define SHM_INFO_NAME "SysV_Sem_Info"
36 #define SEM_NAME "/pgsql-darwin"
40 int op[OPMAX]; /* array of pending operations */
41 int idx; /* index of first free array member */
51 sem_t* sem[SEMMAX];/* array of POSIX semaphores */
52 struct sem semV[SEMMAX]; /* array of System V semaphore
54 struct pending_ops pendingOps[SEMMAX]; /* array of pending
59 static struct sem_info *SemInfo = (struct sem_info *) - 1;
63 semctl(int semid, int semnum, int cmd, /* ... */ union semun arg)
67 sem_wait(SemInfo->sem);
69 if (semid < 0 || semid >= SETMAX ||
70 semnum < 0 || semnum >= SemInfo->set[semid].nsems)
72 sem_post(SemInfo->sem);
80 r = SemInfo->set[semid].semV[semnum].semncnt;
84 r = SemInfo->set[semid].semV[semnum].sempid;
88 r = SemInfo->set[semid].semV[semnum].semval;
92 for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++)
93 arg.array[semnum] = SemInfo->set[semid].semV[semnum].semval;
97 SemInfo->set[semid].semV[semnum].semval = arg.val;
101 for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++)
102 SemInfo->set[semid].semV[semnum].semval = arg.array[semnum];
106 r = SemInfo->set[semid].semV[semnum].semzcnt;
110 for (semnum = 0; semnum < SemInfo->set[semid].nsems; semnum++)
112 if (sem_close(SemInfo->set[semid].sem[semnum]) == -1)
115 SemInfo->set[semid].key = -1;
116 SemInfo->set[semid].nsems = 0;
120 sem_post(SemInfo->sem);
125 sem_post(SemInfo->sem);
131 semget(key_t key, int nsems, int semflg)
135 semnum /* , semnum1 */ ;
139 if (nsems < 0 || nsems > SEMMAX)
142 fprintf(stderr, "darwin semget aborting because nsems out of range. (%d)\n", nsems);
148 /* open and map shared memory */
149 if (SemInfo == (struct sem_info *) - 1)
152 fprintf(stderr, "darwin initializing shared mem for semaphore shim.\n");
154 /* test if the shared memory already exists */
155 fd = shm_open(SHM_INFO_NAME, O_RDWR | O_CREAT | O_EXCL, MODE);
156 if (fd == -1 && errno == EEXIST)
159 fd = shm_open(SHM_INFO_NAME, O_RDWR | O_CREAT, MODE);
163 /* The size may only be set once. Ignore errors. */
164 ftruncate(fd, sizeof(struct sem_info));
165 SemInfo = mmap(NULL, sizeof(struct sem_info),
166 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
167 if (SemInfo == MAP_FAILED)
171 /* create semaphore for locking */
172 sprintf(semname, "%s-map", SEM_NAME);
174 fprintf(stderr, "darwin creating sem %s to cover shared mem.\n", semname);
176 SemInfo->sem = sem_open(semname, O_CREAT, semflg & 0777, 1);
177 sem_wait(SemInfo->sem);
178 /* initilize shared memory */
179 memset(SemInfo->set, 0, sizeof(SemInfo->set));
180 for (semid = 0; semid < SETMAX; semid++)
181 SemInfo->set[semid].key = -1;
182 sem_post(SemInfo->sem);
186 sem_wait(SemInfo->sem);
188 if (key != IPC_PRIVATE)
190 /* search existing element */
192 while (semid < SETMAX && SemInfo->set[semid].key != key)
194 if (!(semflg & IPC_CREAT) && semid >= SETMAX)
196 sem_post(SemInfo->sem);
200 else if (semid < SETMAX)
202 if (semflg & IPC_CREAT && semflg & IPC_EXCL)
204 sem_post(SemInfo->sem);
210 if (nsems != 0 && SemInfo->set[semid].nsems < nsems)
213 fprintf(stderr, "darwin semget failed because if (nsems != 0 && SemInfo->set[semid].nsems < nsems) %d %d\n",
214 nsems, SemInfo->set[semid].nsems);
216 sem_post(SemInfo->sem);
220 sem_post(SemInfo->sem);
226 /* search first free element */
228 while (semid < SETMAX && SemInfo->set[semid].key != -1)
233 fprintf(stderr, "darwin semget failed because all keys were -1 up to SETMAX\n");
235 sem_post(SemInfo->sem);
240 for (semnum = 0; semnum < nsems; semnum++)
242 sprintf(semname, "%s-%d-%d", SEM_NAME, semid, semnum);
244 fprintf(stderr, "darwin creating sem %s to cover set %d num %dm.\n", semname, semid, semnum);
246 SemInfo->set[semid].sem[semnum] = sem_open(semname, O_CREAT, semflg & 0777, 0);
248 /* Currently sem_init always returns -1.
249 if( sem_init( &SemInfo->set[semid].sem[semnum], 1, 0 ) == -1 ) {
250 for( semnum1 = 0; semnum1 < semnum; semnum1++ ) {
251 sem_close( SemInfo->set[semid].sem[semnum1] );
253 sem_post( SemInfo->sem );
259 SemInfo->set[semid].key = key;
260 SemInfo->set[semid].nsems = nsems;
262 sem_post(SemInfo->sem);
268 semop(int semid, struct sembuf * sops, size_t nsops)
276 sem_wait(SemInfo->sem);
278 if (semid < 0 || semid >= SETMAX)
280 sem_post(SemInfo->sem);
284 for (i = 0; i < nsops; i++)
286 if ( /* sops[i].sem_num < 0 || */ sops[i].sem_num >= SemInfo->set[semid].nsems)
288 sem_post(SemInfo->sem);
294 for (i = 0; i < nsops; i++)
296 if (sops[i].sem_op < 0)
298 if (SemInfo->set[semid].semV[sops[i].sem_num].semval < -sops[i].sem_op)
300 if (sops[i].sem_flg & IPC_NOWAIT)
302 sem_post(SemInfo->sem);
306 SemInfo->set[semid].semV[sops[i].sem_num].semncnt++;
307 if (SemInfo->set[semid].pendingOps[sops[i].sem_num].idx >= OPMAX)
309 /* pending operations array overflow */
310 sem_post(SemInfo->sem);
314 SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx++] = sops[i].sem_op;
316 sem_post(SemInfo->sem); /* avoid deadlock */
317 r1 = sem_wait(SemInfo->set[semid].sem[sops[i].sem_num]);
318 sem_wait(SemInfo->sem);
323 /* remove pending operation */
324 SemInfo->set[semid].pendingOps[sops[i].sem_num].op[--SemInfo->set[semid].pendingOps[sops[i].sem_num].idx] = 0;
327 SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op;
328 SemInfo->set[semid].semV[sops[i].sem_num].semncnt--;
331 SemInfo->set[semid].semV[sops[i].sem_num].semval -= -sops[i].sem_op;
333 else if (sops[i].sem_op > 0)
335 SemInfo->set[semid].semV[sops[i].sem_num].semval += sops[i].sem_op;
337 while (op > 0 && SemInfo->set[semid].pendingOps[sops[i].sem_num].idx > 0)
338 { /* operations pending */
339 if (SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx - 1] + op >= 0)
341 /* unsuspend processes */
342 if (sem_post(SemInfo->set[semid].sem[sops[i].sem_num]))
347 /* adjust pending operations */
348 op += SemInfo->set[semid].pendingOps[sops[i].sem_num].op[--SemInfo->set[semid].pendingOps[sops[i].sem_num].idx];
349 SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx] = 0;
353 /* adjust pending operations */
354 SemInfo->set[semid].pendingOps[sops[i].sem_num].op[SemInfo->set[semid].pendingOps[sops[i].sem_num].idx - 1] += op;
360 /* sops[i].sem_op == 0 */
363 sem_post(SemInfo->sem);
367 SemInfo->set[semid].semV[sops[i].sem_num].sempid = getpid();
370 sem_post(SemInfo->sem);