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)
 
void PGSemaphoreShmemRequest (int maxSemas)
 
void PGSemaphoreInit (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

◆ PGSemaphoreCreate()

PGSemaphore PGSemaphoreCreate ( void  )

Definition at line 255 of file posix_sema.c.

256{
257 PGSemaphore sema;
258 sem_t *newsem;
259
260 /* Can't do this in a backend, because static state is postmaster's */
262
263 if (numSems >= maxSems)
264 elog(PANIC, "too many semaphores created");
265
266#ifdef USE_NAMED_POSIX_SEMAPHORES
268 /* Remember new sema for ReleaseSemaphores */
270 sema = (PGSemaphore) newsem;
271#else
272 sema = &sharedSemas[numSems];
273 newsem = PG_SEM_REF(sema);
275#endif
276
277 numSems++;
278
279 return sema;
280}
#define Assert(condition)
Definition c.h:943
#define PANIC
Definition elog.h:44
#define elog(elevel,...)
Definition elog.h:228
bool IsUnderPostmaster
Definition globals.c:122
struct PGSemaphoreData * PGSemaphore
Definition pg_sema.h:34
static int maxSems
Definition posix_sema.c:67
static int numSems
Definition posix_sema.c:66
static PGSemaphore sharedSemas
Definition posix_sema.c:64
static void PosixSemaphoreCreate(sem_t *sem)
Definition posix_sema.c:135
#define PG_SEM_REF(x)
Definition posix_sema.c:57
static int fb(int x)

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

Referenced by ProcGlobalShmemInit().

◆ PGSemaphoreInit()

void PGSemaphoreInit ( int  maxSemas)

Definition at line 198 of file posix_sema.c.

199{
200 struct stat statbuf;
201
202 /*
203 * We use the data directory's inode number to seed the search for free
204 * semaphore keys. This minimizes the odds of collision with other
205 * postmasters, while maximizing the odds that we will detect and clean up
206 * semaphores left over from a crashed postmaster in our own directory.
207 */
208 if (stat(DataDir, &statbuf) < 0)
211 errmsg("could not stat data directory \"%s\": %m",
212 DataDir)));
213
214#ifdef USE_NAMED_POSIX_SEMAPHORES
215 mySemPointers = (sem_t **) malloc(maxSemas * sizeof(sem_t *));
216 if (mySemPointers == NULL)
217 elog(PANIC, "out of memory");
218#endif
219
220 numSems = 0;
222 nextSemKey = statbuf.st_ino;
223
225}
int errcode_for_file_access(void)
Definition elog.c:898
#define FATAL
Definition elog.h:42
#define ereport(elevel,...)
Definition elog.h:152
char * DataDir
Definition globals.c:73
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
static char * errmsg
static int nextSemKey
Definition posix_sema.c:68
static void ReleaseSemaphores(int status, Datum arg)
Definition posix_sema.c:233
#define malloc(a)
#define stat
Definition win32_port.h:74

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

Referenced by ProcGlobalShmemInit().

◆ PGSemaphoreLock()

void PGSemaphoreLock ( PGSemaphore  sema)

Definition at line 313 of file posix_sema.c.

314{
315 int errStatus;
316
317 /* See notes in sysv_sema.c's implementation of PGSemaphoreLock. */
318 do
319 {
321 } while (errStatus < 0 && errno == EINTR);
322
323 if (errStatus < 0)
324 elog(FATAL, "sem_wait failed: %m");
325}
#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 288 of file posix_sema.c.

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

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

Referenced by InitAuxiliaryProcess(), and InitProcess().

◆ PGSemaphoreShmemRequest()

void PGSemaphoreShmemRequest ( 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#else
170 /* Need a PGSemaphoreData per semaphore */
171 ShmemRequestStruct(.name = "Semaphores",
172 .size = mul_size(maxSemas, sizeof(PGSemaphoreData)),
173 .ptr = (void **) &sharedSemas,
174 );
175#endif
176}
Size mul_size(Size s1, Size s2)
Definition shmem.c:1063
#define ShmemRequestStruct(...)
Definition shmem.h:176
const char * name

References fb(), mul_size(), name, sharedSemas, and ShmemRequestStruct.

Referenced by ProcGlobalShmemRequest().

◆ PGSemaphoreTryLock()

bool PGSemaphoreTryLock ( PGSemaphore  sema)

Definition at line 358 of file posix_sema.c.

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

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

◆ PGSemaphoreUnlock()

void PGSemaphoreUnlock ( PGSemaphore  sema)

Definition at line 333 of file posix_sema.c.

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

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

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

Referenced by ReleaseSemaphores().

◆ ReleaseSemaphores()

static void ReleaseSemaphores ( int  status,
Datum  arg 
)
static

Definition at line 233 of file posix_sema.c.

234{
235 int i;
236
237#ifdef USE_NAMED_POSIX_SEMAPHORES
238 for (i = 0; i < numSems; i++)
241#endif
242
243#ifdef USE_UNNAMED_POSIX_SEMAPHORES
244 for (i = 0; i < numSems; i++)
246#endif
247}
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 PGSemaphoreInit().

Variable Documentation

◆ maxSems

int maxSems
static

Definition at line 67 of file posix_sema.c.

Referenced by PGSemaphoreCreate(), and PGSemaphoreInit().

◆ nextSemKey

int nextSemKey
static

Definition at line 68 of file posix_sema.c.

Referenced by PGSemaphoreInit().

◆ numSems

◆ sharedSemas

PGSemaphore sharedSemas
static

Definition at line 64 of file posix_sema.c.

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