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

union  SemTPadded
 
struct  PGSemaphoreData
 

Macros

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

Typedefs

typedef union SemTPadded SemTPadded
 
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 58 of file posix_sema.c.

Referenced by dsm_impl_sysv(), and InternalIpcMemoryCreate().

◆ PG_SEM_REF

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

Typedef Documentation

◆ PGSemaphoreData

◆ SemTPadded

Function Documentation

◆ PGReserveSemaphores()

void PGReserveSemaphores ( int  maxSemas,
int  port 
)

Definition at line 199 of file posix_sema.c.

Referenced by CreateSharedMemoryAndSemaphores().

200 {
201 #ifdef USE_NAMED_POSIX_SEMAPHORES
202  mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));
203  if (mySemPointers == NULL)
204  elog(PANIC, "out of memory");
205 #else
206 
207  /*
208  * We must use ShmemAllocUnlocked(), since the spinlock protecting
209  * ShmemAlloc() won't be ready yet. (This ordering is necessary when we
210  * are emulating spinlocks with semaphores.)
211  */
214 #endif
215 
216  numSems = 0;
217  maxSems = maxSemas;
218  nextSemKey = port * 1000;
219 
221 }
static int numSems
Definition: posix_sema.c:65
#define PANIC
Definition: elog.h:53
#define malloc(a)
Definition: header.h:50
static PGSemaphore sharedSemas
Definition: posix_sema.c:63
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
static void ReleaseSemaphores(int status, Datum arg)
Definition: posix_sema.c:229
static int port
Definition: pg_regress.c:90
static int maxSems
Definition: posix_sema.c:66
static int nextSemKey
Definition: posix_sema.c:67
void * ShmemAllocUnlocked(Size size)
Definition: shmem.c:227
struct PGSemaphoreData * PGSemaphore
Definition: pg_sema.h:34
#define elog(elevel,...)
Definition: elog.h:226
Size PGSemaphoreShmemSize(int maxSemas)
Definition: posix_sema.c:164

◆ PGSemaphoreCreate()

PGSemaphore PGSemaphoreCreate ( void  )

Definition at line 251 of file posix_sema.c.

Referenced by InitProcGlobal(), and SpinlockSemaInit().

252 {
253  PGSemaphore sema;
254  sem_t *newsem;
255 
256  /* Can't do this in a backend, because static state is postmaster's */
258 
259  if (numSems >= maxSems)
260  elog(PANIC, "too many semaphores created");
261 
262 #ifdef USE_NAMED_POSIX_SEMAPHORES
263  newsem = PosixSemaphoreCreate();
264  /* Remember new sema for ReleaseSemaphores */
265  mySemPointers[numSems] = newsem;
266  sema = (PGSemaphore) newsem;
267 #else
268  sema = &sharedSemas[numSems];
269  newsem = PG_SEM_REF(sema);
270  PosixSemaphoreCreate(newsem);
271 #endif
272 
273  numSems++;
274 
275  return sema;
276 }
static void PosixSemaphoreCreate(sem_t *sem)
Definition: posix_sema.c:134
static int numSems
Definition: posix_sema.c:65
#define PANIC
Definition: elog.h:53
static PGSemaphore sharedSemas
Definition: posix_sema.c:63
bool IsUnderPostmaster
Definition: globals.c:109
static int maxSems
Definition: posix_sema.c:66
#define Assert(condition)
Definition: c.h:732
struct PGSemaphoreData * PGSemaphore
Definition: pg_sema.h:34
#define elog(elevel,...)
Definition: elog.h:226
#define PG_SEM_REF(x)
Definition: posix_sema.c:56

◆ PGSemaphoreLock()

void PGSemaphoreLock ( PGSemaphore  sema)

Definition at line 309 of file posix_sema.c.

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

310 {
311  int errStatus;
312 
313  /* See notes in sysv_sema.c's implementation of PGSemaphoreLock. */
314  do
315  {
316  errStatus = sem_wait(PG_SEM_REF(sema));
317  } while (errStatus < 0 && errno == EINTR);
318 
319  if (errStatus < 0)
320  elog(FATAL, "sem_wait failed: %m");
321 }
#define FATAL
Definition: elog.h:52
#define elog(elevel,...)
Definition: elog.h:226
#define PG_SEM_REF(x)
Definition: posix_sema.c:56
#define EINTR
Definition: win32_port.h:334

◆ PGSemaphoreReset()

void PGSemaphoreReset ( PGSemaphore  sema)

Definition at line 284 of file posix_sema.c.

Referenced by InitAuxiliaryProcess(), and InitProcess().

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

◆ PGSemaphoreShmemSize()

Size PGSemaphoreShmemSize ( int  maxSemas)

Definition at line 164 of file posix_sema.c.

Referenced by CreateSharedMemoryAndSemaphores(), and PGReserveSemaphores().

165 {
166 #ifdef USE_NAMED_POSIX_SEMAPHORES
167  /* No shared memory needed in this case */
168  return 0;
169 #else
170  /* Need a PGSemaphoreData per semaphore */
171  return mul_size(maxSemas, sizeof(PGSemaphoreData));
172 #endif
173 }
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492

◆ PGSemaphoreTryLock()

bool PGSemaphoreTryLock ( PGSemaphore  sema)

Definition at line 354 of file posix_sema.c.

Referenced by tas_sema().

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

◆ PGSemaphoreUnlock()

void PGSemaphoreUnlock ( PGSemaphore  sema)

Definition at line 329 of file posix_sema.c.

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

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

◆ PosixSemaphoreCreate()

static void PosixSemaphoreCreate ( sem_t *  sem)
static

Definition at line 134 of file posix_sema.c.

References elog, and FATAL.

Referenced by PGSemaphoreCreate().

135 {
136  if (sem_init(sem, 1, 1) < 0)
137  elog(FATAL, "sem_init failed: %m");
138 }
#define FATAL
Definition: elog.h:52
#define elog(elevel,...)
Definition: elog.h:226

◆ PosixSemaphoreKill()

static void PosixSemaphoreKill ( sem_t *  sem)
static

Definition at line 146 of file posix_sema.c.

References elog, and LOG.

Referenced by ReleaseSemaphores().

147 {
148 #ifdef USE_NAMED_POSIX_SEMAPHORES
149  /* Got to use sem_close for named semaphores */
150  if (sem_close(sem) < 0)
151  elog(LOG, "sem_close failed: %m");
152 #else
153  /* Got to use sem_destroy for unnamed semaphores */
154  if (sem_destroy(sem) < 0)
155  elog(LOG, "sem_destroy failed: %m");
156 #endif
157 }
#define LOG
Definition: elog.h:26
#define elog(elevel,...)
Definition: elog.h:226

◆ ReleaseSemaphores()

static void ReleaseSemaphores ( int  status,
Datum  arg 
)
static

Definition at line 229 of file posix_sema.c.

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

Referenced by PGReserveSemaphores().

230 {
231  int i;
232 
233 #ifdef USE_NAMED_POSIX_SEMAPHORES
234  for (i = 0; i < numSems; i++)
235  PosixSemaphoreKill(mySemPointers[i]);
236  free(mySemPointers);
237 #endif
238 
239 #ifdef USE_UNNAMED_POSIX_SEMAPHORES
240  for (i = 0; i < numSems; i++)
242 #endif
243 }
static void PosixSemaphoreKill(sem_t *sem)
Definition: posix_sema.c:146
static int numSems
Definition: posix_sema.c:65
static PGSemaphore sharedSemas
Definition: posix_sema.c:63
#define free(a)
Definition: header.h:65
int i
#define PG_SEM_REF(x)
Definition: posix_sema.c:56

Variable Documentation

◆ maxSems

int maxSems
static

Definition at line 66 of file posix_sema.c.

Referenced by PGReserveSemaphores(), and PGSemaphoreCreate().

◆ nextSemKey

int nextSemKey
static

Definition at line 67 of file posix_sema.c.

Referenced by PGReserveSemaphores().

◆ numSems

int numSems
static

◆ sharedSemas

PGSemaphore sharedSemas
static

Definition at line 63 of file posix_sema.c.