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

Go to the source code of this file.

Data Structures

struct  PGSemaphoreData
 

Macros

#define PG_SEM_REF(x)   (&(x)->pgsem)
 
#define IPCProtection   (0600) /* access/modify by user only */
 

Typedefs

typedef struct PGSemaphoreData PGSemaphoreData
 

Functions

static void ReleaseSemaphores (int status, Datum arg)
 
static void PosixSemaphoreCreate (sem_t *sem)
 
static void PosixSemaphoreKill (sem_t *sem)
 
Size PGSemaphoreShmemSize (int maxSemas)
 
void PGReserveSemaphores (int maxSemas, int port)
 
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 numSems
 
static int maxSems
 
static int nextSemKey
 

Macro Definition Documentation

◆ IPCProtection

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

Definition at line 52 of file posix_sema.c.

Referenced by dsm_impl_sysv(), and InternalIpcMemoryCreate().

◆ PG_SEM_REF

#define PG_SEM_REF (   x)    (&(x)->pgsem)

Typedef Documentation

◆ PGSemaphoreData

Function Documentation

◆ PGReserveSemaphores()

void PGReserveSemaphores ( int  maxSemas,
int  port 
)

Definition at line 193 of file posix_sema.c.

Referenced by CreateSharedMemoryAndSemaphores().

194 {
195 #ifdef USE_NAMED_POSIX_SEMAPHORES
196  mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));
197  if (mySemPointers == NULL)
198  elog(PANIC, "out of memory");
199 #else
200 
201  /*
202  * We must use ShmemAllocUnlocked(), since the spinlock protecting
203  * ShmemAlloc() won't be ready yet. (This ordering is necessary when we
204  * are emulating spinlocks with semaphores.)
205  */
208 #endif
209 
210  numSems = 0;
211  maxSems = maxSemas;
212  nextSemKey = port * 1000;
213 
215 }
static int numSems
Definition: posix_sema.c:59
#define PANIC
Definition: elog.h:53
#define malloc(a)
Definition: header.h:50
static PGSemaphore sharedSemas
Definition: posix_sema.c:57
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:348
static void ReleaseSemaphores(int status, Datum arg)
Definition: posix_sema.c:223
static int port
Definition: pg_regress.c:90
static int maxSems
Definition: posix_sema.c:60
static int nextSemKey
Definition: posix_sema.c:61
void * ShmemAllocUnlocked(Size size)
Definition: shmem.c:227
struct PGSemaphoreData * PGSemaphore
Definition: pg_sema.h:34
Size PGSemaphoreShmemSize(int maxSemas)
Definition: posix_sema.c:158
#define elog
Definition: elog.h:219

◆ PGSemaphoreCreate()

PGSemaphore PGSemaphoreCreate ( void  )

Definition at line 245 of file posix_sema.c.

Referenced by InitProcGlobal(), and SpinlockSemaInit().

246 {
247  PGSemaphore sema;
248  sem_t *newsem;
249 
250  /* Can't do this in a backend, because static state is postmaster's */
252 
253  if (numSems >= maxSems)
254  elog(PANIC, "too many semaphores created");
255 
256 #ifdef USE_NAMED_POSIX_SEMAPHORES
257  newsem = PosixSemaphoreCreate();
258  /* Remember new sema for ReleaseSemaphores */
259  mySemPointers[numSems] = newsem;
260  sema = (PGSemaphore) newsem;
261 #else
262  sema = &sharedSemas[numSems];
263  newsem = PG_SEM_REF(sema);
264  PosixSemaphoreCreate(newsem);
265 #endif
266 
267  numSems++;
268 
269  return sema;
270 }
static void PosixSemaphoreCreate(sem_t *sem)
Definition: posix_sema.c:128
static int numSems
Definition: posix_sema.c:59
#define PANIC
Definition: elog.h:53
static PGSemaphore sharedSemas
Definition: posix_sema.c:57
bool IsUnderPostmaster
Definition: globals.c:101
static int maxSems
Definition: posix_sema.c:60
#define Assert(condition)
Definition: c.h:670
struct PGSemaphoreData * PGSemaphore
Definition: pg_sema.h:34
#define PG_SEM_REF(x)
Definition: posix_sema.c:50
#define elog
Definition: elog.h:219

◆ PGSemaphoreLock()

void PGSemaphoreLock ( PGSemaphore  sema)

Definition at line 303 of file posix_sema.c.

Referenced by LWLockAcquire(), LWLockAcquireOrWait(), LWLockDequeueSelf(), LWLockWaitForVar(), ProcArrayGroupClearXid(), and TransactionGroupUpdateXidStatus().

304 {
305  int errStatus;
306 
307  /* See notes in sysv_sema.c's implementation of PGSemaphoreLock. */
308  do
309  {
310  errStatus = sem_wait(PG_SEM_REF(sema));
311  } while (errStatus < 0 && errno == EINTR);
312 
313  if (errStatus < 0)
314  elog(FATAL, "sem_wait failed: %m");
315 }
#define FATAL
Definition: elog.h:52
#define PG_SEM_REF(x)
Definition: posix_sema.c:50
#define elog
Definition: elog.h:219
#define EINTR
Definition: win32_port.h:334

◆ PGSemaphoreReset()

void PGSemaphoreReset ( PGSemaphore  sema)

Definition at line 278 of file posix_sema.c.

Referenced by InitAuxiliaryProcess(), and InitProcess().

279 {
280  /*
281  * There's no direct API for this in POSIX, so we have to ratchet the
282  * semaphore down to 0 with repeated trywait's.
283  */
284  for (;;)
285  {
286  if (sem_trywait(PG_SEM_REF(sema)) < 0)
287  {
288  if (errno == EAGAIN || errno == EDEADLK)
289  break; /* got it down to 0 */
290  if (errno == EINTR)
291  continue; /* can this happen? */
292  elog(FATAL, "sem_trywait failed: %m");
293  }
294  }
295 }
#define EAGAIN
Definition: win32_port.h:332
#define FATAL
Definition: elog.h:52
#define PG_SEM_REF(x)
Definition: posix_sema.c:50
#define elog
Definition: elog.h:219
#define EINTR
Definition: win32_port.h:334

◆ PGSemaphoreShmemSize()

Size PGSemaphoreShmemSize ( int  maxSemas)

Definition at line 158 of file posix_sema.c.

Referenced by CreateSharedMemoryAndSemaphores(), and PGReserveSemaphores().

159 {
160 #ifdef USE_NAMED_POSIX_SEMAPHORES
161  /* No shared memory needed in this case */
162  return 0;
163 #else
164  /* Need a PGSemaphoreData per semaphore */
165  return mul_size(maxSemas, sizeof(PGSemaphoreData));
166 #endif
167 }
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492

◆ PGSemaphoreTryLock()

bool PGSemaphoreTryLock ( PGSemaphore  sema)

Definition at line 348 of file posix_sema.c.

Referenced by tas_sema().

349 {
350  int errStatus;
351 
352  /*
353  * Note: if errStatus is -1 and errno == EINTR then it means we returned
354  * from the operation prematurely because we were sent a signal. So we
355  * try and lock the semaphore again.
356  */
357  do
358  {
359  errStatus = sem_trywait(PG_SEM_REF(sema));
360  } while (errStatus < 0 && errno == EINTR);
361 
362  if (errStatus < 0)
363  {
364  if (errno == EAGAIN || errno == EDEADLK)
365  return false; /* failed to lock it */
366  /* Otherwise we got trouble */
367  elog(FATAL, "sem_trywait failed: %m");
368  }
369 
370  return true;
371 }
#define EAGAIN
Definition: win32_port.h:332
#define FATAL
Definition: elog.h:52
#define PG_SEM_REF(x)
Definition: posix_sema.c:50
#define elog
Definition: elog.h:219
#define EINTR
Definition: win32_port.h:334

◆ PGSemaphoreUnlock()

void PGSemaphoreUnlock ( PGSemaphore  sema)

Definition at line 323 of file posix_sema.c.

Referenced by LWLockAcquire(), LWLockAcquireOrWait(), LWLockDequeueSelf(), LWLockUpdateVar(), LWLockWaitForVar(), LWLockWakeup(), ProcArrayGroupClearXid(), s_unlock_sema(), and TransactionGroupUpdateXidStatus().

324 {
325  int errStatus;
326 
327  /*
328  * Note: if errStatus is -1 and errno == EINTR then it means we returned
329  * from the operation prematurely because we were sent a signal. So we
330  * try and unlock the semaphore again. Not clear this can really happen,
331  * but might as well cope.
332  */
333  do
334  {
335  errStatus = sem_post(PG_SEM_REF(sema));
336  } while (errStatus < 0 && errno == EINTR);
337 
338  if (errStatus < 0)
339  elog(FATAL, "sem_post failed: %m");
340 }
#define FATAL
Definition: elog.h:52
#define PG_SEM_REF(x)
Definition: posix_sema.c:50
#define elog
Definition: elog.h:219
#define EINTR
Definition: win32_port.h:334

◆ PosixSemaphoreCreate()

static void PosixSemaphoreCreate ( sem_t *  sem)
static

Definition at line 128 of file posix_sema.c.

References elog, and FATAL.

Referenced by PGSemaphoreCreate().

129 {
130  if (sem_init(sem, 1, 1) < 0)
131  elog(FATAL, "sem_init failed: %m");
132 }
#define FATAL
Definition: elog.h:52
#define elog
Definition: elog.h:219

◆ PosixSemaphoreKill()

static void PosixSemaphoreKill ( sem_t *  sem)
static

Definition at line 140 of file posix_sema.c.

References elog, and LOG.

Referenced by ReleaseSemaphores().

141 {
142 #ifdef USE_NAMED_POSIX_SEMAPHORES
143  /* Got to use sem_close for named semaphores */
144  if (sem_close(sem) < 0)
145  elog(LOG, "sem_close failed: %m");
146 #else
147  /* Got to use sem_destroy for unnamed semaphores */
148  if (sem_destroy(sem) < 0)
149  elog(LOG, "sem_destroy failed: %m");
150 #endif
151 }
#define LOG
Definition: elog.h:26
#define elog
Definition: elog.h:219

◆ ReleaseSemaphores()

static void ReleaseSemaphores ( int  status,
Datum  arg 
)
static

Definition at line 223 of file posix_sema.c.

References free, i, numSems, PG_SEM_REF, and PosixSemaphoreKill().

Referenced by PGReserveSemaphores().

224 {
225  int i;
226 
227 #ifdef USE_NAMED_POSIX_SEMAPHORES
228  for (i = 0; i < numSems; i++)
229  PosixSemaphoreKill(mySemPointers[i]);
230  free(mySemPointers);
231 #endif
232 
233 #ifdef USE_UNNAMED_POSIX_SEMAPHORES
234  for (i = 0; i < numSems; i++)
236 #endif
237 }
static void PosixSemaphoreKill(sem_t *sem)
Definition: posix_sema.c:140
static int numSems
Definition: posix_sema.c:59
static PGSemaphore sharedSemas
Definition: posix_sema.c:57
#define free(a)
Definition: header.h:65
int i
#define PG_SEM_REF(x)
Definition: posix_sema.c:50

Variable Documentation

◆ maxSems

int maxSems
static

Definition at line 60 of file posix_sema.c.

Referenced by PGReserveSemaphores(), and PGSemaphoreCreate().

◆ nextSemKey

int nextSemKey
static

Definition at line 61 of file posix_sema.c.

Referenced by PGReserveSemaphores().

◆ numSems

int numSems
static

◆ sharedSemas

PGSemaphore sharedSemas
static

Definition at line 57 of file posix_sema.c.