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)
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
220#endif
221
222 numSems = 0;
223 maxSems = maxSemas;
224 nextSemKey = statbuf.st_ino;
225
227}
int errcode_for_file_access(void)
Definition: elog.c:886
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define FATAL
Definition: elog.h:41
#define PANIC
Definition: elog.h:42
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
char * DataDir
Definition: globals.c:71
#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:235
void * ShmemAlloc(Size size)
Definition: shmem.c:154
#define stat
Definition: win32_port.h:274

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, ShmemAlloc(), stat::st_ino, and stat.

Referenced by InitProcGlobal().

◆ PGSemaphoreCreate()

PGSemaphore PGSemaphoreCreate ( void  )

Definition at line 257 of file posix_sema.c.

258{
259 PGSemaphore sema;
260 sem_t *newsem;
261
262 /* Can't do this in a backend, because static state is postmaster's */
264
265 if (numSems >= maxSems)
266 elog(PANIC, "too many semaphores created");
267
268#ifdef USE_NAMED_POSIX_SEMAPHORES
269 newsem = PosixSemaphoreCreate();
270 /* Remember new sema for ReleaseSemaphores */
271 mySemPointers[numSems] = newsem;
272 sema = (PGSemaphore) newsem;
273#else
274 sema = &sharedSemas[numSems];
275 newsem = PG_SEM_REF(sema);
276 PosixSemaphoreCreate(newsem);
277#endif
278
279 numSems++;
280
281 return sema;
282}
bool IsUnderPostmaster
Definition: globals.c:120
Assert(PointerIsAligned(start, uint64))
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 315 of file posix_sema.c.

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

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 290 of file posix_sema.c.

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

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

References mul_size().

Referenced by PGReserveSemaphores(), and ProcGlobalShmemSize().

◆ PGSemaphoreTryLock()

bool PGSemaphoreTryLock ( PGSemaphore  sema)

Definition at line 360 of file posix_sema.c.

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

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 335 of file posix_sema.c.

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

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().