PostgreSQL Source Code  git master
sysv_sema.c File Reference
#include "postgres.h"
#include <signal.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/stat.h>
#include "miscadmin.h"
#include "storage/ipc.h"
#include "storage/pg_sema.h"
#include "storage/shmem.h"
Include dependency graph for sysv_sema.c:

Go to the source code of this file.

Data Structures

struct  PGSemaphoreData
 
union  semun
 

Macros

#define SEMAS_PER_SET   16
 
#define IPCProtection   (0600) /* access/modify by user only */
 
#define PGSemaMagic   537 /* must be less than SEMVMX */
 

Typedefs

typedef struct PGSemaphoreData PGSemaphoreData
 
typedef key_t IpcSemaphoreKey
 
typedef int IpcSemaphoreId
 

Functions

static IpcSemaphoreId InternalIpcSemaphoreCreate (IpcSemaphoreKey semKey, int numSems)
 
static void IpcSemaphoreInitialize (IpcSemaphoreId semId, int semNum, int value)
 
static void IpcSemaphoreKill (IpcSemaphoreId semId)
 
static int IpcSemaphoreGetValue (IpcSemaphoreId semId, int semNum)
 
static pid_t IpcSemaphoreGetLastPID (IpcSemaphoreId semId, int semNum)
 
static IpcSemaphoreId IpcSemaphoreCreate (int numSems)
 
static void ReleaseSemaphores (int status, Datum arg)
 
Size PGSemaphoreShmemSize (int maxSemas)
 
void PGReserveSemaphores (int maxSemas)
 
PGSemaphore PGSemaphoreCreate (void)
 
void PGSemaphoreReset (PGSemaphore sema)
 
void PGSemaphoreLock (PGSemaphore sema)
 
void PGSemaphoreUnlock (PGSemaphore sema)
 
bool PGSemaphoreTryLock (PGSemaphore sema)
 

Variables

static PGSemaphore sharedSemas
 
static int numSharedSemas
 
static int maxSharedSemas
 
static IpcSemaphoreIdmySemaSets
 
static int numSemaSets
 
static int maxSemaSets
 
static IpcSemaphoreKey nextSemaKey
 
static int nextSemaNumber
 

Macro Definition Documentation

◆ IPCProtection

#define IPCProtection   (0600) /* access/modify by user only */

Definition at line 60 of file sysv_sema.c.

Referenced by InternalIpcSemaphoreCreate().

◆ PGSemaMagic

#define PGSemaMagic   537 /* must be less than SEMVMX */

Definition at line 62 of file sysv_sema.c.

Referenced by IpcSemaphoreCreate().

◆ SEMAS_PER_SET

#define SEMAS_PER_SET   16

Definition at line 58 of file sysv_sema.c.

Referenced by PGReserveSemaphores(), and PGSemaphoreCreate().

Typedef Documentation

◆ IpcSemaphoreId

typedef int IpcSemaphoreId

Definition at line 50 of file sysv_sema.c.

◆ IpcSemaphoreKey

Definition at line 49 of file sysv_sema.c.

◆ PGSemaphoreData

Function Documentation

◆ InternalIpcSemaphoreCreate()

static IpcSemaphoreId InternalIpcSemaphoreCreate ( IpcSemaphoreKey  semKey,
int  numSems 
)
static

Definition at line 97 of file sysv_sema.c.

References EIDRM, ereport, errdetail(), errhint(), errmsg(), FATAL, IPC_CREAT, IPC_EXCL, IPCProtection, and PGSemaphoreData::semId.

Referenced by IpcSemaphoreCreate().

98 {
99  int semId;
100 
101  semId = semget(semKey, numSems, IPC_CREAT | IPC_EXCL | IPCProtection);
102 
103  if (semId < 0)
104  {
105  int saved_errno = errno;
106 
107  /*
108  * Fail quietly if error indicates a collision with existing set. One
109  * would expect EEXIST, given that we said IPC_EXCL, but perhaps we
110  * could get a permission violation instead? Also, EIDRM might occur
111  * if an old set is slated for destruction but not gone yet.
112  */
113  if (saved_errno == EEXIST || saved_errno == EACCES
114 #ifdef EIDRM
115  || saved_errno == EIDRM
116 #endif
117  )
118  return -1;
119 
120  /*
121  * Else complain and abort
122  */
123  ereport(FATAL,
124  (errmsg("could not create semaphores: %m"),
125  errdetail("Failed system call was semget(%lu, %d, 0%o).",
126  (unsigned long) semKey, numSems,
128  (saved_errno == ENOSPC) ?
129  errhint("This error does *not* mean that you have run out of disk space. "
130  "It occurs when either the system limit for the maximum number of "
131  "semaphore sets (SEMMNI), or the system wide maximum number of "
132  "semaphores (SEMMNS), would be exceeded. You need to raise the "
133  "respective kernel parameter. Alternatively, reduce PostgreSQL's "
134  "consumption of semaphores by reducing its max_connections parameter.\n"
135  "The PostgreSQL documentation contains more information about "
136  "configuring your system for PostgreSQL.") : 0));
137  }
138 
139  return semId;
140 }
int errhint(const char *fmt,...)
Definition: elog.c:974
#define IPC_CREAT
Definition: win32_port.h:82
static int numSems
Definition: posix_sema.c:66
#define FATAL
Definition: elog.h:52
#define EIDRM
Definition: win32_port.h:90
int errdetail(const char *fmt,...)
Definition: elog.c:860
#define ereport(elevel, rest)
Definition: elog.h:141
#define IPC_EXCL
Definition: win32_port.h:83
#define IPCProtection
Definition: sysv_sema.c:60
int errmsg(const char *fmt,...)
Definition: elog.c:784

◆ IpcSemaphoreCreate()

static IpcSemaphoreId IpcSemaphoreCreate ( int  numSems)
static

Definition at line 212 of file sysv_sema.c.

References InternalIpcSemaphoreCreate(), IPC_RMID, IpcSemaphoreGetLastPID(), IpcSemaphoreGetValue(), IpcSemaphoreInitialize(), kill, nextSemaKey, numSems, PGSemaMagic, PGSemaphoreUnlock(), PGSemaphoreData::semId, and semun::val.

Referenced by PGSemaphoreCreate().

213 {
214  IpcSemaphoreId semId;
215  union semun semun;
216  PGSemaphoreData mysema;
217 
218  /* Loop till we find a free IPC key */
219  for (nextSemaKey++;; nextSemaKey++)
220  {
221  pid_t creatorPID;
222 
223  /* Try to create new semaphore set */
225  if (semId >= 0)
226  break; /* successful create */
227 
228  /* See if it looks to be leftover from a dead Postgres process */
229  semId = semget(nextSemaKey, numSems + 1, 0);
230  if (semId < 0)
231  continue; /* failed: must be some other app's */
233  continue; /* sema belongs to a non-Postgres app */
234 
235  /*
236  * If the creator PID is my own PID or does not belong to any extant
237  * process, it's safe to zap it.
238  */
239  creatorPID = IpcSemaphoreGetLastPID(semId, numSems);
240  if (creatorPID <= 0)
241  continue; /* oops, GETPID failed */
242  if (creatorPID != getpid())
243  {
244  if (kill(creatorPID, 0) == 0 || errno != ESRCH)
245  continue; /* sema belongs to a live process */
246  }
247 
248  /*
249  * The sema set appears to be from a dead Postgres process, or from a
250  * previous cycle of life in this same process. Zap it, if possible.
251  * This probably shouldn't fail, but if it does, assume the sema set
252  * belongs to someone else after all, and continue quietly.
253  */
254  semun.val = 0; /* unused, but keep compiler quiet */
255  if (semctl(semId, 0, IPC_RMID, semun) < 0)
256  continue;
257 
258  /*
259  * Now try again to create the sema set.
260  */
262  if (semId >= 0)
263  break; /* successful create */
264 
265  /*
266  * Can only get here if some other process managed to create the same
267  * sema key before we did. Let him have that one, loop around to try
268  * next key.
269  */
270  }
271 
272  /*
273  * OK, we created a new sema set. Mark it as created by this process. We
274  * do this by setting the spare semaphore to PGSemaMagic-1 and then
275  * incrementing it with semop(). That leaves it with value PGSemaMagic
276  * and sempid referencing this process.
277  */
279  mysema.semId = semId;
280  mysema.semNum = numSems;
281  PGSemaphoreUnlock(&mysema);
282 
283  return semId;
284 }
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: sysv_sema.c:452
static int numSems
Definition: posix_sema.c:66
#define kill(pid, sig)
Definition: win32_port.h:426
int IpcSemaphoreId
Definition: sysv_sema.c:50
static void IpcSemaphoreInitialize(IpcSemaphoreId semId, int semNum, int value)
Definition: sysv_sema.c:146
#define PGSemaMagic
Definition: sysv_sema.c:62
int val
Definition: sysv_sema.c:43
#define IPC_RMID
Definition: win32_port.h:81
static int IpcSemaphoreGetValue(IpcSemaphoreId semId, int semNum)
Definition: sysv_sema.c:181
static IpcSemaphoreId InternalIpcSemaphoreCreate(IpcSemaphoreKey semKey, int numSems)
Definition: sysv_sema.c:97
static IpcSemaphoreKey nextSemaKey
Definition: sysv_sema.c:71
static pid_t IpcSemaphoreGetLastPID(IpcSemaphoreId semId, int semNum)
Definition: sysv_sema.c:192

◆ IpcSemaphoreGetLastPID()

static pid_t IpcSemaphoreGetLastPID ( IpcSemaphoreId  semId,
int  semNum 
)
static

Definition at line 192 of file sysv_sema.c.

References GETPID, and semun::val.

Referenced by IpcSemaphoreCreate().

193 {
194  union semun dummy; /* for Solaris */
195 
196  dummy.val = 0; /* unused */
197 
198  return semctl(semId, semNum, GETPID, dummy);
199 }
#define GETPID
Definition: win32_port.h:97
int val
Definition: sysv_sema.c:43

◆ IpcSemaphoreGetValue()

static int IpcSemaphoreGetValue ( IpcSemaphoreId  semId,
int  semNum 
)
static

Definition at line 181 of file sysv_sema.c.

References GETVAL, and semun::val.

Referenced by IpcSemaphoreCreate().

182 {
183  union semun dummy; /* for Solaris */
184 
185  dummy.val = 0; /* unused */
186 
187  return semctl(semId, semNum, GETVAL, dummy);
188 }
#define GETVAL
Definition: win32_port.h:95
int val
Definition: sysv_sema.c:43

◆ IpcSemaphoreInitialize()

static void IpcSemaphoreInitialize ( IpcSemaphoreId  semId,
int  semNum,
int  value 
)
static

Definition at line 146 of file sysv_sema.c.

References ereport, errhint(), errmsg_internal(), FATAL, SETVAL, semun::val, and value.

Referenced by IpcSemaphoreCreate(), PGSemaphoreCreate(), and PGSemaphoreReset().

147 {
148  union semun semun;
149 
150  semun.val = value;
151  if (semctl(semId, semNum, SETVAL, semun) < 0)
152  {
153  int saved_errno = errno;
154 
155  ereport(FATAL,
156  (errmsg_internal("semctl(%d, %d, SETVAL, %d) failed: %m",
157  semId, semNum, value),
158  (saved_errno == ERANGE) ?
159  errhint("You possibly need to raise your kernel's SEMVMX value to be at least "
160  "%d. Look into the PostgreSQL documentation for details.",
161  value) : 0));
162  }
163 }
int errhint(const char *fmt,...)
Definition: elog.c:974
static struct @145 value
#define FATAL
Definition: elog.h:52
int val
Definition: sysv_sema.c:43
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg_internal(const char *fmt,...)
Definition: elog.c:814
#define SETVAL
Definition: win32_port.h:96

◆ IpcSemaphoreKill()

static void IpcSemaphoreKill ( IpcSemaphoreId  semId)
static

Definition at line 169 of file sysv_sema.c.

References elog, IPC_RMID, LOG, and semun::val.

Referenced by ReleaseSemaphores().

170 {
171  union semun semun;
172 
173  semun.val = 0; /* unused, but keep compiler quiet */
174 
175  if (semctl(semId, 0, IPC_RMID, semun) < 0)
176  elog(LOG, "semctl(%d, 0, IPC_RMID, ...) failed: %m", semId);
177 }
#define LOG
Definition: elog.h:26
int val
Definition: sysv_sema.c:43
#define IPC_RMID
Definition: win32_port.h:81
#define elog(elevel,...)
Definition: elog.h:226

◆ PGReserveSemaphores()

void PGReserveSemaphores ( int  maxSemas)

Definition at line 314 of file sysv_sema.c.

References DataDir, elog, ereport, errcode_for_file_access(), errmsg(), FATAL, malloc, maxSemaSets, maxSharedSemas, mySemaSets, nextSemaKey, nextSemaNumber, numSemaSets, numSharedSemas, on_shmem_exit(), PANIC, PGSemaphoreShmemSize(), ReleaseSemaphores(), SEMAS_PER_SET, ShmemAllocUnlocked(), and stat.

315 {
316  struct stat statbuf;
317 
318  /*
319  * We use the data directory's inode number to seed the search for free
320  * semaphore keys. This minimizes the odds of collision with other
321  * postmasters, while maximizing the odds that we will detect and clean up
322  * semaphores left over from a crashed postmaster in our own directory.
323  */
324  if (stat(DataDir, &statbuf) < 0)
325  ereport(FATAL,
327  errmsg("could not stat data directory \"%s\": %m",
328  DataDir)));
329 
330  /*
331  * We must use ShmemAllocUnlocked(), since the spinlock protecting
332  * ShmemAlloc() won't be ready yet. (This ordering is necessary when we
333  * are emulating spinlocks with semaphores.)
334  */
337  numSharedSemas = 0;
338  maxSharedSemas = maxSemas;
339 
340  maxSemaSets = (maxSemas + SEMAS_PER_SET - 1) / SEMAS_PER_SET;
342  malloc(maxSemaSets * sizeof(IpcSemaphoreId));
343  if (mySemaSets == NULL)
344  elog(PANIC, "out of memory");
345  numSemaSets = 0;
346  nextSemaKey = statbuf.st_ino;
347  nextSemaNumber = SEMAS_PER_SET; /* force sema set alloc on 1st call */
348 
350 }
static int maxSemaSets
Definition: sysv_sema.c:70
static void ReleaseSemaphores(int status, Datum arg)
Definition: sysv_sema.c:358
#define SEMAS_PER_SET
Definition: sysv_sema.c:58
static int maxSharedSemas
Definition: sysv_sema.c:67
static PGSemaphore sharedSemas
Definition: sysv_sema.c:65
#define PANIC
Definition: elog.h:53
int IpcSemaphoreId
Definition: sysv_sema.c:50
#define malloc(a)
Definition: header.h:50
static int nextSemaNumber
Definition: sysv_sema.c:72
#define FATAL
Definition: elog.h:52
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
int errcode_for_file_access(void)
Definition: elog.c:593
#define ereport(elevel, rest)
Definition: elog.h:141
#define stat(a, b)
Definition: win32_port.h:255
static int numSharedSemas
Definition: sysv_sema.c:66
void * ShmemAllocUnlocked(Size size)
Definition: shmem.c:227
static IpcSemaphoreId * mySemaSets
Definition: sysv_sema.c:68
int errmsg(const char *fmt,...)
Definition: elog.c:784
Size PGSemaphoreShmemSize(int maxSemas)
Definition: sysv_sema.c:291
struct PGSemaphoreData * PGSemaphore
Definition: pg_sema.h:34
#define elog(elevel,...)
Definition: elog.h:226
char * DataDir
Definition: globals.c:62
static IpcSemaphoreKey nextSemaKey
Definition: sysv_sema.c:71
static int numSemaSets
Definition: sysv_sema.c:69

◆ PGSemaphoreCreate()

PGSemaphore PGSemaphoreCreate ( void  )

Definition at line 373 of file sysv_sema.c.

References Assert, elog, IpcSemaphoreCreate(), IpcSemaphoreInitialize(), IsUnderPostmaster, maxSemaSets, maxSharedSemas, mySemaSets, nextSemaNumber, numSemaSets, numSharedSemas, PANIC, SEMAS_PER_SET, PGSemaphoreData::semId, and PGSemaphoreData::semNum.

374 {
375  PGSemaphore sema;
376 
377  /* Can't do this in a backend, because static state is postmaster's */
379 
381  {
382  /* Time to allocate another semaphore set */
383  if (numSemaSets >= maxSemaSets)
384  elog(PANIC, "too many semaphores created");
386  numSemaSets++;
387  nextSemaNumber = 0;
388  }
389  /* Use the next shared PGSemaphoreData */
391  elog(PANIC, "too many semaphores created");
392  sema = &sharedSemas[numSharedSemas++];
393  /* Assign the next free semaphore in the current set */
394  sema->semId = mySemaSets[numSemaSets - 1];
395  sema->semNum = nextSemaNumber++;
396  /* Initialize it to count 1 */
397  IpcSemaphoreInitialize(sema->semId, sema->semNum, 1);
398 
399  return sema;
400 }
static int maxSemaSets
Definition: sysv_sema.c:70
#define SEMAS_PER_SET
Definition: sysv_sema.c:58
static int maxSharedSemas
Definition: sysv_sema.c:67
static PGSemaphore sharedSemas
Definition: sysv_sema.c:65
#define PANIC
Definition: elog.h:53
static int nextSemaNumber
Definition: sysv_sema.c:72
static void IpcSemaphoreInitialize(IpcSemaphoreId semId, int semNum, int value)
Definition: sysv_sema.c:146
bool IsUnderPostmaster
Definition: globals.c:109
static int numSharedSemas
Definition: sysv_sema.c:66
static IpcSemaphoreId * mySemaSets
Definition: sysv_sema.c:68
#define Assert(condition)
Definition: c.h:732
#define elog(elevel,...)
Definition: elog.h:226
static IpcSemaphoreId IpcSemaphoreCreate(int numSems)
Definition: sysv_sema.c:212
static int numSemaSets
Definition: sysv_sema.c:69

◆ PGSemaphoreLock()

void PGSemaphoreLock ( PGSemaphore  sema)

Definition at line 419 of file sysv_sema.c.

References EINTR, elog, FATAL, PGSemaphoreData::semId, and PGSemaphoreData::semNum.

420 {
421  int errStatus;
422  struct sembuf sops;
423 
424  sops.sem_op = -1; /* decrement */
425  sops.sem_flg = 0;
426  sops.sem_num = sema->semNum;
427 
428  /*
429  * Note: if errStatus is -1 and errno == EINTR then it means we returned
430  * from the operation prematurely because we were sent a signal. So we
431  * try and lock the semaphore again.
432  *
433  * We used to check interrupts here, but that required servicing
434  * interrupts directly from signal handlers. Which is hard to do safely
435  * and portably.
436  */
437  do
438  {
439  errStatus = semop(sema->semId, &sops, 1);
440  } while (errStatus < 0 && errno == EINTR);
441 
442  if (errStatus < 0)
443  elog(FATAL, "semop(id=%d) failed: %m", sema->semId);
444 }
#define FATAL
Definition: elog.h:52
#define elog(elevel,...)
Definition: elog.h:226
#define EINTR
Definition: win32_port.h:323

◆ PGSemaphoreReset()

void PGSemaphoreReset ( PGSemaphore  sema)

Definition at line 408 of file sysv_sema.c.

References IpcSemaphoreInitialize(), PGSemaphoreData::semId, and PGSemaphoreData::semNum.

409 {
410  IpcSemaphoreInitialize(sema->semId, sema->semNum, 0);
411 }
static void IpcSemaphoreInitialize(IpcSemaphoreId semId, int semNum, int value)
Definition: sysv_sema.c:146

◆ PGSemaphoreShmemSize()

Size PGSemaphoreShmemSize ( int  maxSemas)

Definition at line 291 of file sysv_sema.c.

References mul_size().

Referenced by PGReserveSemaphores().

292 {
293  return mul_size(maxSemas, sizeof(PGSemaphoreData));
294 }
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492

◆ PGSemaphoreTryLock()

bool PGSemaphoreTryLock ( PGSemaphore  sema)

Definition at line 482 of file sysv_sema.c.

References EAGAIN, EINTR, elog, EWOULDBLOCK, FATAL, IPC_NOWAIT, PGSemaphoreData::semId, and PGSemaphoreData::semNum.

483 {
484  int errStatus;
485  struct sembuf sops;
486 
487  sops.sem_op = -1; /* decrement */
488  sops.sem_flg = IPC_NOWAIT; /* but don't block */
489  sops.sem_num = sema->semNum;
490 
491  /*
492  * Note: if errStatus is -1 and errno == EINTR then it means we returned
493  * from the operation prematurely because we were sent a signal. So we
494  * try and lock the semaphore again.
495  */
496  do
497  {
498  errStatus = semop(sema->semId, &sops, 1);
499  } while (errStatus < 0 && errno == EINTR);
500 
501  if (errStatus < 0)
502  {
503  /* Expect EAGAIN or EWOULDBLOCK (platform-dependent) */
504 #ifdef EAGAIN
505  if (errno == EAGAIN)
506  return false; /* failed to lock it */
507 #endif
508 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
509  if (errno == EWOULDBLOCK)
510  return false; /* failed to lock it */
511 #endif
512  /* Otherwise we got trouble */
513  elog(FATAL, "semop(id=%d) failed: %m", sema->semId);
514  }
515 
516  return true;
517 }
#define EAGAIN
Definition: win32_port.h:321
#define FATAL
Definition: elog.h:52
#define IPC_NOWAIT
Definition: win32_port.h:85
#define elog(elevel,...)
Definition: elog.h:226
#define EWOULDBLOCK
Definition: win32_port.h:329
#define EINTR
Definition: win32_port.h:323

◆ PGSemaphoreUnlock()

void PGSemaphoreUnlock ( PGSemaphore  sema)

Definition at line 452 of file sysv_sema.c.

References EINTR, elog, FATAL, PGSemaphoreData::semId, and PGSemaphoreData::semNum.

Referenced by IpcSemaphoreCreate().

453 {
454  int errStatus;
455  struct sembuf sops;
456 
457  sops.sem_op = 1; /* increment */
458  sops.sem_flg = 0;
459  sops.sem_num = sema->semNum;
460 
461  /*
462  * Note: if errStatus is -1 and errno == EINTR then it means we returned
463  * from the operation prematurely because we were sent a signal. So we
464  * try and unlock the semaphore again. Not clear this can really happen,
465  * but might as well cope.
466  */
467  do
468  {
469  errStatus = semop(sema->semId, &sops, 1);
470  } while (errStatus < 0 && errno == EINTR);
471 
472  if (errStatus < 0)
473  elog(FATAL, "semop(id=%d) failed: %m", sema->semId);
474 }
#define FATAL
Definition: elog.h:52
#define elog(elevel,...)
Definition: elog.h:226
#define EINTR
Definition: win32_port.h:323

◆ ReleaseSemaphores()

static void ReleaseSemaphores ( int  status,
Datum  arg 
)
static

Definition at line 358 of file sysv_sema.c.

References free, i, IpcSemaphoreKill(), mySemaSets, and numSemaSets.

Referenced by PGReserveSemaphores().

359 {
360  int i;
361 
362  for (i = 0; i < numSemaSets; i++)
364  free(mySemaSets);
365 }
static void IpcSemaphoreKill(IpcSemaphoreId semId)
Definition: sysv_sema.c:169
static IpcSemaphoreId * mySemaSets
Definition: sysv_sema.c:68
#define free(a)
Definition: header.h:65
int i
static int numSemaSets
Definition: sysv_sema.c:69

Variable Documentation

◆ maxSemaSets

int maxSemaSets
static

Definition at line 70 of file sysv_sema.c.

Referenced by PGReserveSemaphores(), and PGSemaphoreCreate().

◆ maxSharedSemas

int maxSharedSemas
static

Definition at line 67 of file sysv_sema.c.

Referenced by PGReserveSemaphores(), and PGSemaphoreCreate().

◆ mySemaSets

IpcSemaphoreId* mySemaSets
static

Definition at line 68 of file sysv_sema.c.

Referenced by PGReserveSemaphores(), PGSemaphoreCreate(), and ReleaseSemaphores().

◆ nextSemaKey

IpcSemaphoreKey nextSemaKey
static

Definition at line 71 of file sysv_sema.c.

Referenced by IpcSemaphoreCreate(), and PGReserveSemaphores().

◆ nextSemaNumber

int nextSemaNumber
static

Definition at line 72 of file sysv_sema.c.

Referenced by PGReserveSemaphores(), and PGSemaphoreCreate().

◆ numSemaSets

int numSemaSets
static

Definition at line 69 of file sysv_sema.c.

Referenced by PGReserveSemaphores(), PGSemaphoreCreate(), and ReleaseSemaphores().

◆ numSharedSemas

int numSharedSemas
static

Definition at line 66 of file sysv_sema.c.

Referenced by PGReserveSemaphores(), and PGSemaphoreCreate().

◆ sharedSemas

PGSemaphore sharedSemas
static

Definition at line 65 of file sysv_sema.c.