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

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.

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, ShmemAllocUnlocked(), and stat.

Referenced by CreateSharedMemoryAndSemaphores().

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. (This ordering is necessary when we
221  * are emulating spinlocks with semaphores.)
222  */
225 #endif
226 
227  numSems = 0;
228  maxSems = maxSemas;
229  nextSemKey = statbuf.st_ino;
230 
232 }
static int numSems
Definition: posix_sema.c:66
#define PANIC
Definition: elog.h:53
#define malloc(a)
Definition: header.h:50
#define FATAL
Definition: elog.h:52
static PGSemaphore sharedSemas
Definition: posix_sema.c:64
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
static void ReleaseSemaphores(int status, Datum arg)
Definition: posix_sema.c:240
static int maxSems
Definition: posix_sema.c:67
static int nextSemKey
Definition: posix_sema.c:68
#define stat(a, b)
Definition: win32_port.h:264
void * ShmemAllocUnlocked(Size size)
Definition: shmem.c:227
int errmsg(const char *fmt,...)
Definition: elog.c:784
struct PGSemaphoreData * PGSemaphore
Definition: pg_sema.h:34
#define elog(elevel,...)
Definition: elog.h:226
Size PGSemaphoreShmemSize(int maxSemas)
Definition: posix_sema.c:165
char * DataDir
Definition: globals.c:62

◆ PGSemaphoreCreate()

PGSemaphore PGSemaphoreCreate ( void  )

Definition at line 262 of file posix_sema.c.

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 TRUE.

Referenced by InitProcGlobal(), and SpinlockSemaInit().

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

◆ PGSemaphoreLock()

void PGSemaphoreLock ( PGSemaphore  sema)

Definition at line 320 of file posix_sema.c.

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

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

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

◆ PGSemaphoreReset()

void PGSemaphoreReset ( PGSemaphore  sema)

Definition at line 295 of file posix_sema.c.

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

Referenced by InitAuxiliaryProcess(), and InitProcess().

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

◆ PGSemaphoreShmemSize()

Size PGSemaphoreShmemSize ( int  maxSemas)

Definition at line 165 of file posix_sema.c.

References mul_size().

Referenced by CreateSharedMemoryAndSemaphores(), and PGReserveSemaphores().

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:492

◆ PGSemaphoreTryLock()

bool PGSemaphoreTryLock ( PGSemaphore  sema)

Definition at line 365 of file posix_sema.c.

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

Referenced by PGSemaphoreReset(), and tas_sema().

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

◆ PGSemaphoreUnlock()

void PGSemaphoreUnlock ( PGSemaphore  sema)

Definition at line 340 of file posix_sema.c.

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

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

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