PostgreSQL Source Code  git master
wait_event.c File Reference
#include "postgres.h"
#include "port/pg_bitutils.h"
#include "storage/lmgr.h"
#include "storage/lwlock.h"
#include "storage/spin.h"
#include "utils/wait_event.h"
#include "pgstat_wait_event.c"
Include dependency graph for wait_event.c:

Go to the source code of this file.

Data Structures

struct  WaitEventExtensionEntryById
 
struct  WaitEventExtensionEntryByName
 
struct  WaitEventExtensionCounterData
 

Macros

#define WAIT_EVENT_CLASS_MASK   0xFF000000
 
#define WAIT_EVENT_ID_MASK   0x0000FFFF
 
#define WAIT_EVENT_EXTENSION_HASH_INIT_SIZE   16
 
#define WAIT_EVENT_EXTENSION_HASH_MAX_SIZE   128
 
#define NUM_BUILTIN_WAIT_EVENT_EXTENSION    (WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED - WAIT_EVENT_EXTENSION)
 
#define WAIT_EVENT_EXTENSION_INFO(eventId)   (PG_WAIT_EXTENSION | eventId)
 

Typedefs

typedef struct WaitEventExtensionEntryById WaitEventExtensionEntryById
 
typedef struct WaitEventExtensionEntryByName WaitEventExtensionEntryByName
 
typedef struct WaitEventExtensionCounterData WaitEventExtensionCounterData
 

Functions

static const char * pgstat_get_wait_activity (WaitEventActivity w)
 
static const char * pgstat_get_wait_bufferpin (WaitEventBufferPin w)
 
static const char * pgstat_get_wait_client (WaitEventClient w)
 
static const char * pgstat_get_wait_ipc (WaitEventIPC w)
 
static const char * pgstat_get_wait_timeout (WaitEventTimeout w)
 
static const char * pgstat_get_wait_io (WaitEventIO w)
 
static const char * GetWaitEventExtensionIdentifier (uint16 eventId)
 
Size WaitEventExtensionShmemSize (void)
 
void WaitEventExtensionShmemInit (void)
 
uint32 WaitEventExtensionNew (const char *wait_event_name)
 
char ** GetWaitEventExtensionNames (int *nwaitevents)
 
void pgstat_set_wait_event_storage (uint32 *wait_event_info)
 
void pgstat_reset_wait_event_storage (void)
 
const char * pgstat_get_wait_event_type (uint32 wait_event_info)
 
const char * pgstat_get_wait_event (uint32 wait_event_info)
 

Variables

static uint32 local_my_wait_event_info
 
uint32my_wait_event_info = &local_my_wait_event_info
 
static HTABWaitEventExtensionHashById
 
static HTABWaitEventExtensionHashByName
 
static WaitEventExtensionCounterDataWaitEventExtensionCounter
 

Macro Definition Documentation

◆ NUM_BUILTIN_WAIT_EVENT_EXTENSION

#define NUM_BUILTIN_WAIT_EVENT_EXTENSION    (WAIT_EVENT_EXTENSION_FIRST_USER_DEFINED - WAIT_EVENT_EXTENSION)

Definition at line 92 of file wait_event.c.

◆ WAIT_EVENT_CLASS_MASK

#define WAIT_EVENT_CLASS_MASK   0xFF000000

Definition at line 43 of file wait_event.c.

◆ WAIT_EVENT_EXTENSION_HASH_INIT_SIZE

#define WAIT_EVENT_EXTENSION_HASH_INIT_SIZE   16

Definition at line 64 of file wait_event.c.

◆ WAIT_EVENT_EXTENSION_HASH_MAX_SIZE

#define WAIT_EVENT_EXTENSION_HASH_MAX_SIZE   128

Definition at line 65 of file wait_event.c.

◆ WAIT_EVENT_EXTENSION_INFO

#define WAIT_EVENT_EXTENSION_INFO (   eventId)    (PG_WAIT_EXTENSION | eventId)

Definition at line 96 of file wait_event.c.

◆ WAIT_EVENT_ID_MASK

#define WAIT_EVENT_ID_MASK   0x0000FFFF

Definition at line 44 of file wait_event.c.

Typedef Documentation

◆ WaitEventExtensionCounterData

◆ WaitEventExtensionEntryById

◆ WaitEventExtensionEntryByName

Function Documentation

◆ GetWaitEventExtensionIdentifier()

static const char * GetWaitEventExtensionIdentifier ( uint16  eventId)
static

Definition at line 241 of file wait_event.c.

242 {
243  bool found;
245 
246  /* Built-in event? */
247  if (eventId < NUM_BUILTIN_WAIT_EVENT_EXTENSION)
248  return "Extension";
249 
250  /* It is a user-defined wait event, so lookup hash table. */
251  LWLockAcquire(WaitEventExtensionLock, LW_SHARED);
252  entry = (WaitEventExtensionEntryById *)
254  HASH_FIND, &found);
255  LWLockRelease(WaitEventExtensionLock);
256 
257  if (!entry)
258  elog(ERROR, "could not find custom wait event name for ID %u",
259  eventId);
260 
261  return entry->wait_event_name;
262 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
@ HASH_FIND
Definition: hsearch.h:113
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1170
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1783
@ LW_SHARED
Definition: lwlock.h:115
char wait_event_name[NAMEDATALEN]
Definition: wait_event.c:71
#define NUM_BUILTIN_WAIT_EVENT_EXTENSION
Definition: wait_event.c:92
static HTAB * WaitEventExtensionHashById
Definition: wait_event.c:61

References elog, ERROR, HASH_FIND, hash_search(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NUM_BUILTIN_WAIT_EVENT_EXTENSION, WaitEventExtensionEntryById::wait_event_name, and WaitEventExtensionHashById.

Referenced by pgstat_get_wait_event().

◆ GetWaitEventExtensionNames()

char** GetWaitEventExtensionNames ( int *  nwaitevents)

Definition at line 271 of file wait_event.c.

272 {
273  char **waiteventnames;
275  HASH_SEQ_STATUS hash_seq;
276  int index;
277  int els;
278 
279  LWLockAcquire(WaitEventExtensionLock, LW_SHARED);
280 
281  /* Now we can safely count the number of entries */
283 
284  /* Allocate enough space for all entries */
285  waiteventnames = palloc(els * sizeof(char *));
286 
287  /* Now scan the hash table to copy the data */
289 
290  index = 0;
291  while ((hentry = (WaitEventExtensionEntryByName *) hash_seq_search(&hash_seq)) != NULL)
292  {
293  waiteventnames[index] = pstrdup(hentry->wait_event_name);
294  index++;
295  }
296 
297  LWLockRelease(WaitEventExtensionLock);
298 
299  Assert(index == els);
300 
301  *nwaitevents = index;
302  return waiteventnames;
303 }
#define Assert(condition)
Definition: c.h:858
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1341
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1395
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
char * pstrdup(const char *in)
Definition: mcxt.c:1695
void * palloc(Size size)
Definition: mcxt.c:1316
char wait_event_name[NAMEDATALEN]
Definition: wait_event.c:76
Definition: type.h:95
static HTAB * WaitEventExtensionHashByName
Definition: wait_event.c:62

References Assert, hash_get_num_entries(), hash_seq_init(), hash_seq_search(), LW_SHARED, LWLockAcquire(), LWLockRelease(), palloc(), pstrdup(), WaitEventExtensionEntryByName::wait_event_name, and WaitEventExtensionHashByName.

Referenced by pg_get_wait_events().

◆ pgstat_get_wait_activity()

static const char* pgstat_get_wait_activity ( WaitEventActivity  w)
static

Referenced by pgstat_get_wait_event().

◆ pgstat_get_wait_bufferpin()

static const char* pgstat_get_wait_bufferpin ( WaitEventBufferPin  w)
static

Referenced by pgstat_get_wait_event().

◆ pgstat_get_wait_client()

static const char* pgstat_get_wait_client ( WaitEventClient  w)
static

Referenced by pgstat_get_wait_event().

◆ pgstat_get_wait_event()

const char* pgstat_get_wait_event ( uint32  wait_event_info)

Definition at line 393 of file wait_event.c.

394 {
395  uint32 classId;
396  uint16 eventId;
397  const char *event_name;
398 
399  /* report process as not waiting. */
400  if (wait_event_info == 0)
401  return NULL;
402 
403  classId = wait_event_info & WAIT_EVENT_CLASS_MASK;
404  eventId = wait_event_info & WAIT_EVENT_ID_MASK;
405 
406  switch (classId)
407  {
408  case PG_WAIT_LWLOCK:
409  event_name = GetLWLockIdentifier(classId, eventId);
410  break;
411  case PG_WAIT_LOCK:
412  event_name = GetLockNameFromTagType(eventId);
413  break;
414  case PG_WAIT_EXTENSION:
415  event_name = GetWaitEventExtensionIdentifier(eventId);
416  break;
417  case PG_WAIT_BUFFERPIN:
418  {
419  WaitEventBufferPin w = (WaitEventBufferPin) wait_event_info;
420 
421  event_name = pgstat_get_wait_bufferpin(w);
422  break;
423  }
424  case PG_WAIT_ACTIVITY:
425  {
426  WaitEventActivity w = (WaitEventActivity) wait_event_info;
427 
428  event_name = pgstat_get_wait_activity(w);
429  break;
430  }
431  case PG_WAIT_CLIENT:
432  {
433  WaitEventClient w = (WaitEventClient) wait_event_info;
434 
435  event_name = pgstat_get_wait_client(w);
436  break;
437  }
438  case PG_WAIT_IPC:
439  {
440  WaitEventIPC w = (WaitEventIPC) wait_event_info;
441 
442  event_name = pgstat_get_wait_ipc(w);
443  break;
444  }
445  case PG_WAIT_TIMEOUT:
446  {
447  WaitEventTimeout w = (WaitEventTimeout) wait_event_info;
448 
449  event_name = pgstat_get_wait_timeout(w);
450  break;
451  }
452  case PG_WAIT_IO:
453  {
454  WaitEventIO w = (WaitEventIO) wait_event_info;
455 
456  event_name = pgstat_get_wait_io(w);
457  break;
458  }
459  default:
460  event_name = "unknown wait event";
461  break;
462  }
463 
464  return event_name;
465 }
unsigned short uint16
Definition: c.h:505
unsigned int uint32
Definition: c.h:506
const char * GetLockNameFromTagType(uint16 locktag_type)
Definition: lmgr.c:1340
const char * GetLWLockIdentifier(uint32 classId, uint16 eventId)
Definition: lwlock.c:769
static const char * pgstat_get_wait_ipc(WaitEventIPC w)
static const char * pgstat_get_wait_io(WaitEventIO w)
static const char * pgstat_get_wait_bufferpin(WaitEventBufferPin w)
static const char * pgstat_get_wait_timeout(WaitEventTimeout w)
static const char * pgstat_get_wait_client(WaitEventClient w)
#define WAIT_EVENT_ID_MASK
Definition: wait_event.c:44
#define WAIT_EVENT_CLASS_MASK
Definition: wait_event.c:43
static const char * GetWaitEventExtensionIdentifier(uint16 eventId)
Definition: wait_event.c:241
static const char * pgstat_get_wait_activity(WaitEventActivity w)
#define PG_WAIT_TIMEOUT
Definition: wait_event.h:25
#define PG_WAIT_LWLOCK
Definition: wait_event.h:18
#define PG_WAIT_BUFFERPIN
Definition: wait_event.h:20
#define PG_WAIT_IPC
Definition: wait_event.h:24
#define PG_WAIT_CLIENT
Definition: wait_event.h:22
#define PG_WAIT_EXTENSION
Definition: wait_event.h:23
#define PG_WAIT_ACTIVITY
Definition: wait_event.h:21
#define PG_WAIT_LOCK
Definition: wait_event.h:19
#define PG_WAIT_IO
Definition: wait_event.h:26

References GetLockNameFromTagType(), GetLWLockIdentifier(), GetWaitEventExtensionIdentifier(), PG_WAIT_ACTIVITY, PG_WAIT_BUFFERPIN, PG_WAIT_CLIENT, PG_WAIT_EXTENSION, PG_WAIT_IO, PG_WAIT_IPC, PG_WAIT_LOCK, PG_WAIT_LWLOCK, PG_WAIT_TIMEOUT, pgstat_get_wait_activity(), pgstat_get_wait_bufferpin(), pgstat_get_wait_client(), pgstat_get_wait_io(), pgstat_get_wait_ipc(), pgstat_get_wait_timeout(), WAIT_EVENT_CLASS_MASK, and WAIT_EVENT_ID_MASK.

Referenced by pg_stat_get_activity(), and pg_stat_get_backend_wait_event().

◆ pgstat_get_wait_event_type()

const char* pgstat_get_wait_event_type ( uint32  wait_event_info)

Definition at line 338 of file wait_event.c.

339 {
340  uint32 classId;
341  const char *event_type;
342 
343  /* report process as not waiting. */
344  if (wait_event_info == 0)
345  return NULL;
346 
347  classId = wait_event_info & WAIT_EVENT_CLASS_MASK;
348 
349  switch (classId)
350  {
351  case PG_WAIT_LWLOCK:
352  event_type = "LWLock";
353  break;
354  case PG_WAIT_LOCK:
355  event_type = "Lock";
356  break;
357  case PG_WAIT_BUFFERPIN:
358  event_type = "BufferPin";
359  break;
360  case PG_WAIT_ACTIVITY:
361  event_type = "Activity";
362  break;
363  case PG_WAIT_CLIENT:
364  event_type = "Client";
365  break;
366  case PG_WAIT_EXTENSION:
367  event_type = "Extension";
368  break;
369  case PG_WAIT_IPC:
370  event_type = "IPC";
371  break;
372  case PG_WAIT_TIMEOUT:
373  event_type = "Timeout";
374  break;
375  case PG_WAIT_IO:
376  event_type = "IO";
377  break;
378  default:
379  event_type = "???";
380  break;
381  }
382 
383  return event_type;
384 }

References PG_WAIT_ACTIVITY, PG_WAIT_BUFFERPIN, PG_WAIT_CLIENT, PG_WAIT_EXTENSION, PG_WAIT_IO, PG_WAIT_IPC, PG_WAIT_LOCK, PG_WAIT_LWLOCK, PG_WAIT_TIMEOUT, and WAIT_EVENT_CLASS_MASK.

Referenced by pg_stat_get_activity(), and pg_stat_get_backend_wait_event_type().

◆ pgstat_get_wait_io()

static const char* pgstat_get_wait_io ( WaitEventIO  w)
static

Referenced by pgstat_get_wait_event().

◆ pgstat_get_wait_ipc()

static const char* pgstat_get_wait_ipc ( WaitEventIPC  w)
static

Referenced by pgstat_get_wait_event().

◆ pgstat_get_wait_timeout()

static const char* pgstat_get_wait_timeout ( WaitEventTimeout  w)
static

Referenced by pgstat_get_wait_event().

◆ pgstat_reset_wait_event_storage()

void pgstat_reset_wait_event_storage ( void  )

Definition at line 326 of file wait_event.c.

327 {
329 }
static uint32 local_my_wait_event_info
Definition: wait_event.c:40
uint32 * my_wait_event_info
Definition: wait_event.c:41

References local_my_wait_event_info, and my_wait_event_info.

Referenced by AuxiliaryProcKill(), and ProcKill().

◆ pgstat_set_wait_event_storage()

void pgstat_set_wait_event_storage ( uint32 wait_event_info)

Definition at line 314 of file wait_event.c.

315 {
316  my_wait_event_info = wait_event_info;
317 }

References my_wait_event_info.

Referenced by InitAuxiliaryProcess(), and InitProcess().

◆ WaitEventExtensionNew()

uint32 WaitEventExtensionNew ( const char *  wait_event_name)

Definition at line 162 of file wait_event.c.

163 {
164  uint16 eventId;
165  bool found;
166  WaitEventExtensionEntryByName *entry_by_name;
167  WaitEventExtensionEntryById *entry_by_id;
168 
169  /* Check the limit of the length of the event name */
170  if (strlen(wait_event_name) >= NAMEDATALEN)
171  elog(ERROR,
172  "cannot use custom wait event string longer than %u characters",
173  NAMEDATALEN - 1);
174 
175  /*
176  * Check if the wait event info associated to the name is already defined,
177  * and return it if so.
178  */
179  LWLockAcquire(WaitEventExtensionLock, LW_SHARED);
180  entry_by_name = (WaitEventExtensionEntryByName *)
181  hash_search(WaitEventExtensionHashByName, wait_event_name,
182  HASH_FIND, &found);
183  LWLockRelease(WaitEventExtensionLock);
184  if (found)
185  return WAIT_EVENT_EXTENSION_INFO(entry_by_name->event_id);
186 
187  /*
188  * Allocate and register a new wait event. Recheck if the event name
189  * exists, as it could be possible that a concurrent process has inserted
190  * one with the same name since the LWLock acquired again here was
191  * previously released.
192  */
193  LWLockAcquire(WaitEventExtensionLock, LW_EXCLUSIVE);
194  entry_by_name = (WaitEventExtensionEntryByName *)
195  hash_search(WaitEventExtensionHashByName, wait_event_name,
196  HASH_FIND, &found);
197  if (found)
198  {
199  LWLockRelease(WaitEventExtensionLock);
200  return WAIT_EVENT_EXTENSION_INFO(entry_by_name->event_id);
201  }
202 
203  /* Allocate a new event Id */
205 
207  {
209  ereport(ERROR,
210  errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
211  errmsg("too many wait events for extensions"));
212  }
213 
214  eventId = WaitEventExtensionCounter->nextId++;
215 
217 
218  /* Register the new wait event */
219  entry_by_id = (WaitEventExtensionEntryById *)
221  HASH_ENTER, &found);
222  Assert(!found);
223  strlcpy(entry_by_id->wait_event_name, wait_event_name,
224  sizeof(entry_by_id->wait_event_name));
225 
226  entry_by_name = (WaitEventExtensionEntryByName *)
227  hash_search(WaitEventExtensionHashByName, wait_event_name,
228  HASH_ENTER, &found);
229  Assert(!found);
230  entry_by_name->event_id = eventId;
231 
232  LWLockRelease(WaitEventExtensionLock);
233 
234  return WAIT_EVENT_EXTENSION_INFO(eventId);
235 }
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereport(elevel,...)
Definition: elog.h:149
@ HASH_ENTER
Definition: hsearch.h:114
@ LW_EXCLUSIVE
Definition: lwlock.h:114
#define NAMEDATALEN
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
static WaitEventExtensionCounterData * WaitEventExtensionCounter
Definition: wait_event.c:89
#define WAIT_EVENT_EXTENSION_INFO(eventId)
Definition: wait_event.c:96
#define WAIT_EVENT_EXTENSION_HASH_MAX_SIZE
Definition: wait_event.c:65

References Assert, elog, ereport, errcode(), errmsg(), ERROR, WaitEventExtensionEntryByName::event_id, HASH_ENTER, HASH_FIND, hash_search(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), WaitEventExtensionCounterData::mutex, NAMEDATALEN, WaitEventExtensionCounterData::nextId, SpinLockAcquire, SpinLockRelease, strlcpy(), WAIT_EVENT_EXTENSION_HASH_MAX_SIZE, WAIT_EVENT_EXTENSION_INFO, WaitEventExtensionEntryById::wait_event_name, WaitEventExtensionCounter, WaitEventExtensionHashById, and WaitEventExtensionHashByName.

Referenced by connect_pg_server(), dblink_connect(), dblink_get_conn(), dblink_init(), GetConnection(), injection_wait(), pgfdw_get_cleanup_result(), test_shm_mq_pipelined(), wait_for_workers_to_become_ready(), and worker_spi_main().

◆ WaitEventExtensionShmemInit()

void WaitEventExtensionShmemInit ( void  )

Definition at line 120 of file wait_event.c.

121 {
122  bool found;
123  HASHCTL info;
124 
126  ShmemInitStruct("WaitEventExtensionCounterData",
127  sizeof(WaitEventExtensionCounterData), &found);
128 
129  if (!found)
130  {
131  /* initialize the allocation counter and its spinlock. */
134  }
135 
136  /* initialize or attach the hash tables to store custom wait events */
137  info.keysize = sizeof(uint16);
138  info.entrysize = sizeof(WaitEventExtensionEntryById);
139  WaitEventExtensionHashById = ShmemInitHash("WaitEventExtension hash by id",
142  &info,
144 
145  /* key is a NULL-terminated string */
146  info.keysize = sizeof(char[NAMEDATALEN]);
148  WaitEventExtensionHashByName = ShmemInitHash("WaitEventExtension hash by name",
151  &info,
153 }
#define HASH_STRINGS
Definition: hsearch.h:96
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:332
#define SpinLockInit(lock)
Definition: spin.h:60
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76
struct WaitEventExtensionEntryByName WaitEventExtensionEntryByName
#define WAIT_EVENT_EXTENSION_HASH_INIT_SIZE
Definition: wait_event.c:64
struct WaitEventExtensionEntryById WaitEventExtensionEntryById

References HASHCTL::entrysize, HASH_BLOBS, HASH_ELEM, HASH_STRINGS, HASHCTL::keysize, WaitEventExtensionCounterData::mutex, NAMEDATALEN, WaitEventExtensionCounterData::nextId, NUM_BUILTIN_WAIT_EVENT_EXTENSION, ShmemInitHash(), ShmemInitStruct(), SpinLockInit, WAIT_EVENT_EXTENSION_HASH_INIT_SIZE, WAIT_EVENT_EXTENSION_HASH_MAX_SIZE, WaitEventExtensionCounter, WaitEventExtensionHashById, and WaitEventExtensionHashByName.

Referenced by CreateOrAttachShmemStructs().

◆ WaitEventExtensionShmemSize()

Size WaitEventExtensionShmemSize ( void  )

Definition at line 104 of file wait_event.c.

105 {
106  Size sz;
107 
110  sizeof(WaitEventExtensionEntryById)));
113  return sz;
114 }
#define MAXALIGN(LEN)
Definition: c.h:811
size_t Size
Definition: c.h:605
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:783
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

References add_size(), hash_estimate_size(), MAXALIGN, and WAIT_EVENT_EXTENSION_HASH_MAX_SIZE.

Referenced by CalculateShmemSize().

Variable Documentation

◆ local_my_wait_event_info

uint32 local_my_wait_event_info
static

Definition at line 40 of file wait_event.c.

Referenced by pgstat_reset_wait_event_storage().

◆ my_wait_event_info

◆ WaitEventExtensionCounter

WaitEventExtensionCounterData* WaitEventExtensionCounter
static

Definition at line 89 of file wait_event.c.

Referenced by WaitEventExtensionNew(), and WaitEventExtensionShmemInit().

◆ WaitEventExtensionHashById

HTAB* WaitEventExtensionHashById
static

◆ WaitEventExtensionHashByName

HTAB* WaitEventExtensionHashByName
static