PostgreSQL Source Code git master
Loading...
Searching...
No Matches
posix_sema.c File Reference
#include "postgres.h"
#include <fcntl.h>
#include <semaphore.h>
#include <signal.h>
#include <unistd.h>
#include <sys/stat.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)
 
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 59 of file posix_sema.c.

◆ PG_SEM_REF

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

Definition at line 57 of file posix_sema.c.

Typedef Documentation

◆ PGSemaphoreData

◆ SemTPadded

Function Documentation

◆ PGReserveSemaphores()

void PGReserveSemaphores ( int  maxSemas)

Definition at line 196 of file posix_sema.c.

197{
198 struct stat statbuf;
199 bool found;
200
201 /*
202 * We use the data directory's inode number to seed the search for free
203 * semaphore keys. This minimizes the odds of collision with other
204 * postmasters, while maximizing the odds that we will detect and clean up
205 * semaphores left over from a crashed postmaster in our own directory.
206 */
207 if (stat(DataDir, &statbuf) < 0)
210 errmsg("could not stat data directory \"%s\": %m",
211 DataDir)));
212
213#ifdef USE_NAMED_POSIX_SEMAPHORES
214 mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));
215 if (mySemPointers == NULL)
216 elog(PANIC, "out of memory");
217#else
218
220 ShmemInitStruct("Semaphores", PGSemaphoreShmemSize(maxSemas), &found);
221 Assert(!found);
222#endif
223
224 numSems = 0;
226 nextSemKey = statbuf.st_ino;
227
229}
#define Assert(condition)
Definition c.h:943
int errcode_for_file_access(void)
Definition elog.c:897
#define FATAL
Definition elog.h:41
#define PANIC
Definition elog.h:43
#define elog(elevel,...)
Definition elog.h:227
#define ereport(elevel,...)
Definition elog.h:151
char * DataDir
Definition globals.c:71
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
static char * errmsg
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:237
static int fb(int x)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:408
#define malloc(a)
#define stat
Definition win32_port.h:74

References Assert, DataDir, elog, ereport, errcode_for_file_access(), errmsg, FATAL, fb(), malloc, maxSems, nextSemKey, numSems, on_shmem_exit(), PANIC, PGSemaphoreShmemSize(), ReleaseSemaphores(), sharedSemas, ShmemInitStruct(), and stat.

Referenced by InitProcGlobal().

◆ PGSemaphoreCreate()

PGSemaphore PGSemaphoreCreate ( void  )

Definition at line 259 of file posix_sema.c.

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

References Assert, elog, fb(), IsUnderPostmaster, maxSems, numSems, PANIC, PG_SEM_REF, PosixSemaphoreCreate(), and sharedSemas.

Referenced by InitProcGlobal().

◆ PGSemaphoreLock()

void PGSemaphoreLock ( PGSemaphore  sema)

Definition at line 317 of file posix_sema.c.

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

References EINTR, elog, FATAL, fb(), and PG_SEM_REF.

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

◆ PGSemaphoreReset()

void PGSemaphoreReset ( PGSemaphore  sema)

Definition at line 292 of file posix_sema.c.

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

References EAGAIN, EINTR, elog, FATAL, fb(), and PG_SEM_REF.

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

References fb(), and mul_size().

Referenced by PGReserveSemaphores(), and ProcGlobalShmemSize().

◆ PGSemaphoreTryLock()

bool PGSemaphoreTryLock ( PGSemaphore  sema)

Definition at line 362 of file posix_sema.c.

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

References EAGAIN, EINTR, elog, FATAL, fb(), and PG_SEM_REF.

◆ PGSemaphoreUnlock()

void PGSemaphoreUnlock ( PGSemaphore  sema)

Definition at line 337 of file posix_sema.c.

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

References EINTR, elog, FATAL, fb(), and PG_SEM_REF.

Referenced by BufferLockAcquire(), BufferLockDequeueSelf(), BufferLockWakeup(), LWLockAcquire(), LWLockAcquireOrWait(), LWLockDequeueSelf(), LWLockUpdateVar(), LWLockWaitForVar(), LWLockWakeup(), ProcArrayGroupClearXid(), and TransactionGroupUpdateXidStatus().

◆ PosixSemaphoreCreate()

static void PosixSemaphoreCreate ( sem_t sem)
static

Definition at line 135 of file posix_sema.c.

136{
137 if (sem_init(sem, 1, 1) < 0)
138 elog(FATAL, "sem_init failed: %m");
139}
static JsonSemAction sem

References elog, FATAL, fb(), and sem.

Referenced by PGSemaphoreCreate().

◆ PosixSemaphoreKill()

static void PosixSemaphoreKill ( sem_t sem)
static

Definition at line 147 of file posix_sema.c.

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

References elog, fb(), LOG, and sem.

Referenced by ReleaseSemaphores().

◆ ReleaseSemaphores()

static void ReleaseSemaphores ( int  status,
Datum  arg 
)
static

Definition at line 237 of file posix_sema.c.

238{
239 int i;
240
241#ifdef USE_NAMED_POSIX_SEMAPHORES
242 for (i = 0; i < numSems; i++)
245#endif
246
247#ifdef USE_UNNAMED_POSIX_SEMAPHORES
248 for (i = 0; i < numSems; i++)
250#endif
251}
int i
Definition isn.c:77
static void PosixSemaphoreKill(sem_t *sem)
Definition posix_sema.c:147
#define free(a)

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

Referenced by PGReserveSemaphores().

Variable Documentation

◆ maxSems

int maxSems
static

Definition at line 67 of file posix_sema.c.

Referenced by PGReserveSemaphores(), and PGSemaphoreCreate().

◆ nextSemKey

int nextSemKey
static

Definition at line 68 of file posix_sema.c.

Referenced by PGReserveSemaphores().

◆ numSems

◆ sharedSemas

PGSemaphore sharedSemas
static

Definition at line 64 of file posix_sema.c.

Referenced by PGReserveSemaphores(), PGSemaphoreCreate(), and ReleaseSemaphores().