PostgreSQL Source Code  git master
pg_sema.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct PGSemaphoreDataPGSemaphore
 

Functions

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)
 

Typedef Documentation

◆ PGSemaphore

typedef struct PGSemaphoreData* PGSemaphore

Definition at line 34 of file pg_sema.h.

Function Documentation

◆ PGReserveSemaphores()

void PGReserveSemaphores ( int  maxSemas)

Definition at line 196 of file posix_sema.c.

197 {
198  struct stat statbuf;
199 
200  /*
201  * We use the data directory's inode number to seed the search for free
202  * semaphore keys. This minimizes the odds of collision with other
203  * postmasters, while maximizing the odds that we will detect and clean up
204  * semaphores left over from a crashed postmaster in our own directory.
205  */
206  if (stat(DataDir, &statbuf) < 0)
207  ereport(FATAL,
209  errmsg("could not stat data directory \"%s\": %m",
210  DataDir)));
211 
212 #ifdef USE_NAMED_POSIX_SEMAPHORES
213  mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));
214  if (mySemPointers == NULL)
215  elog(PANIC, "out of memory");
216 #else
217 
218  /*
219  * We must use ShmemAllocUnlocked(), since the spinlock protecting
220  * ShmemAlloc() won't be ready yet.
221  */
224 #endif
225 
226  numSems = 0;
227  maxSems = maxSemas;
228  nextSemKey = statbuf.st_ino;
229 
231 }
int errcode_for_file_access(void)
Definition: elog.c:876
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define FATAL
Definition: elog.h:41
#define PANIC
Definition: elog.h:42
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
char * DataDir
Definition: globals.c:70
#define malloc(a)
Definition: header.h:50
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:365
struct PGSemaphoreData * PGSemaphore
Definition: pg_sema.h:34
Size PGSemaphoreShmemSize(int maxSemas)
Definition: posix_sema.c:165
static int maxSems
Definition: posix_sema.c:67
static int nextSemKey
Definition: posix_sema.c:68
static int numSems
Definition: posix_sema.c:66
static PGSemaphore sharedSemas
Definition: posix_sema.c:64
static void ReleaseSemaphores(int status, Datum arg)
Definition: posix_sema.c:239
void * ShmemAllocUnlocked(Size size)
Definition: shmem.c:233
#define stat
Definition: win32_port.h:284

References DataDir, elog, ereport, errcode_for_file_access(), errmsg(), FATAL, malloc, maxSemaSets, maxSems, maxSharedSemas, mySemaSets, mySemSet, nextSemaKey, nextSemaNumber, nextSemKey, numSemaSets, numSems, numSharedSemas, on_shmem_exit(), PANIC, PGSemaphoreShmemSize(), ReleaseSemaphores(), SEMAS_PER_SET, sharedSemas, ShmemAllocUnlocked(), stat::st_ino, and stat.

Referenced by CreateSharedMemoryAndSemaphores().

◆ PGSemaphoreCreate()

PGSemaphore PGSemaphoreCreate ( void  )

Definition at line 261 of file posix_sema.c.

262 {
263  PGSemaphore sema;
264  sem_t *newsem;
265 
266  /* Can't do this in a backend, because static state is postmaster's */
268 
269  if (numSems >= maxSems)
270  elog(PANIC, "too many semaphores created");
271 
272 #ifdef USE_NAMED_POSIX_SEMAPHORES
273  newsem = PosixSemaphoreCreate();
274  /* Remember new sema for ReleaseSemaphores */
275  mySemPointers[numSems] = newsem;
276  sema = (PGSemaphore) newsem;
277 #else
278  sema = &sharedSemas[numSems];
279  newsem = PG_SEM_REF(sema);
280  PosixSemaphoreCreate(newsem);
281 #endif
282 
283  numSems++;
284 
285  return sema;
286 }
#define Assert(condition)
Definition: c.h:812
bool IsUnderPostmaster
Definition: globals.c:119
static void PosixSemaphoreCreate(sem_t *sem)
Definition: posix_sema.c:135
#define PG_SEM_REF(x)
Definition: posix_sema.c:57

References Assert, elog, ereport, errmsg(), IpcSemaphoreCreate(), IpcSemaphoreInitialize(), IsUnderPostmaster, maxSemaSets, maxSems, maxSharedSemas, mySemaSets, mySemSet, nextSemaNumber, numSemaSets, numSems, numSharedSemas, PANIC, PG_SEM_REF, PosixSemaphoreCreate(), SEMAS_PER_SET, PGSemaphoreData::semId, PGSemaphoreData::semNum, and sharedSemas.

Referenced by InitProcGlobal().

◆ PGSemaphoreLock()

void PGSemaphoreLock ( PGSemaphore  sema)

Definition at line 319 of file posix_sema.c.

320 {
321  int errStatus;
322 
323  /* See notes in sysv_sema.c's implementation of PGSemaphoreLock. */
324  do
325  {
326  errStatus = sem_wait(PG_SEM_REF(sema));
327  } while (errStatus < 0 && errno == EINTR);
328 
329  if (errStatus < 0)
330  elog(FATAL, "sem_wait failed: %m");
331 }
#define EINTR
Definition: win32_port.h:374

References CHECK_FOR_INTERRUPTS, EINTR, elog, ereport, errmsg(), FATAL, PG_SEM_REF, pgwin32_dispatch_queued_signals(), pgwin32_signal_event, PGSemaphoreData::semId, and PGSemaphoreData::semNum.

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

◆ PGSemaphoreReset()

void PGSemaphoreReset ( PGSemaphore  sema)

Definition at line 294 of file posix_sema.c.

295 {
296  /*
297  * There's no direct API for this in POSIX, so we have to ratchet the
298  * semaphore down to 0 with repeated trywait's.
299  */
300  for (;;)
301  {
302  if (sem_trywait(PG_SEM_REF(sema)) < 0)
303  {
304  if (errno == EAGAIN || errno == EDEADLK)
305  break; /* got it down to 0 */
306  if (errno == EINTR)
307  continue; /* can this happen? */
308  elog(FATAL, "sem_trywait failed: %m");
309  }
310  }
311 }
#define EAGAIN
Definition: win32_port.h:372

References EAGAIN, EINTR, elog, FATAL, IpcSemaphoreInitialize(), PG_SEM_REF, PGSemaphoreTryLock(), PGSemaphoreData::semId, and PGSemaphoreData::semNum.

Referenced by InitAuxiliaryProcess(), and InitProcess().

◆ PGSemaphoreShmemSize()

Size PGSemaphoreShmemSize ( int  maxSemas)

Definition at line 165 of file posix_sema.c.

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

References mul_size().

Referenced by CalculateShmemSize(), and PGReserveSemaphores().

◆ PGSemaphoreTryLock()

bool PGSemaphoreTryLock ( PGSemaphore  sema)

Definition at line 364 of file posix_sema.c.

365 {
366  int errStatus;
367 
368  /*
369  * Note: if errStatus is -1 and errno == EINTR then it means we returned
370  * from the operation prematurely because we were sent a signal. So we
371  * try and lock the semaphore again.
372  */
373  do
374  {
375  errStatus = sem_trywait(PG_SEM_REF(sema));
376  } while (errStatus < 0 && errno == EINTR);
377 
378  if (errStatus < 0)
379  {
380  if (errno == EAGAIN || errno == EDEADLK)
381  return false; /* failed to lock it */
382  /* Otherwise we got trouble */
383  elog(FATAL, "sem_trywait failed: %m");
384  }
385 
386  return true;
387 }

References EAGAIN, EINTR, elog, ereport, errmsg(), EWOULDBLOCK, FATAL, IPC_NOWAIT, PG_SEM_REF, PGSemaphoreData::semId, and PGSemaphoreData::semNum.

Referenced by PGSemaphoreReset().

◆ PGSemaphoreUnlock()

void PGSemaphoreUnlock ( PGSemaphore  sema)

Definition at line 339 of file posix_sema.c.

340 {
341  int errStatus;
342 
343  /*
344  * Note: if errStatus is -1 and errno == EINTR then it means we returned
345  * from the operation prematurely because we were sent a signal. So we
346  * try and unlock the semaphore again. Not clear this can really happen,
347  * but might as well cope.
348  */
349  do
350  {
351  errStatus = sem_post(PG_SEM_REF(sema));
352  } while (errStatus < 0 && errno == EINTR);
353 
354  if (errStatus < 0)
355  elog(FATAL, "sem_post failed: %m");
356 }

References EINTR, elog, ereport, errmsg(), FATAL, PG_SEM_REF, PGSemaphoreData::semId, and PGSemaphoreData::semNum.

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