Line data Source code
1 : /*--------------------------------------------------------------------------
2 : *
3 : * test_lwlock_tranches.c
4 : * Test code for LWLock tranches allocated by extensions.
5 : *
6 : * Copyright (c) 2025-2026, PostgreSQL Global Development Group
7 : *
8 : * IDENTIFICATION
9 : * src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c
10 : *
11 : * -------------------------------------------------------------------------
12 : */
13 :
14 : #include "postgres.h"
15 :
16 : #include "fmgr.h"
17 : #include "miscadmin.h"
18 : #include "storage/lwlock.h"
19 : #include "utils/builtins.h"
20 : #include "utils/wait_classes.h"
21 :
22 1 : PG_MODULE_MAGIC;
23 :
24 : static shmem_request_hook_type prev_shmem_request_hook;
25 : static void test_lwlock_tranches_shmem_request(void);
26 :
27 : void
28 1 : _PG_init(void)
29 : {
30 1 : prev_shmem_request_hook = shmem_request_hook;
31 1 : shmem_request_hook = test_lwlock_tranches_shmem_request;
32 1 : }
33 :
34 : static void
35 1 : test_lwlock_tranches_shmem_request(void)
36 : {
37 1 : if (prev_shmem_request_hook)
38 0 : prev_shmem_request_hook();
39 :
40 : /*
41 : * Request some tranches with RequestNamedLWLockTranche() for
42 : * test_startup_lwlocks()
43 : */
44 1 : RequestNamedLWLockTranche("test_lwlock_tranches_startup", 1);
45 1 : RequestNamedLWLockTranche("test_lwlock_tranches_startup10", 10);
46 1 : }
47 :
48 : /*
49 : * Test locks requested with RequestNamedLWLockTranche
50 : */
51 2 : PG_FUNCTION_INFO_V1(test_startup_lwlocks);
52 : Datum
53 1 : test_startup_lwlocks(PG_FUNCTION_ARGS)
54 : {
55 : LWLockPadded *lwlock_startup;
56 : LWLockPadded *lwlock_startup10;
57 :
58 : /* Check that the locks can be used */
59 1 : lwlock_startup = GetNamedLWLockTranche("test_lwlock_tranches_startup");
60 1 : lwlock_startup10 = GetNamedLWLockTranche("test_lwlock_tranches_startup10");
61 :
62 1 : LWLockAcquire(&lwlock_startup->lock, LW_EXCLUSIVE);
63 11 : for (int i = 0; i < 10; i++)
64 10 : LWLockAcquire(&lwlock_startup10[i].lock, LW_EXCLUSIVE);
65 :
66 1 : LWLockRelease(&lwlock_startup->lock);
67 11 : for (int i = 0; i < 10; i++)
68 10 : LWLockRelease(&lwlock_startup10[i].lock);
69 :
70 : /*
71 : * Check that GetLWLockIdentifier() returns the expected value for
72 : * tranches
73 : */
74 1 : if (strcmp("test_lwlock_tranches_startup",
75 : GetLWLockIdentifier(PG_WAIT_LWLOCK, LWTRANCHE_FIRST_USER_DEFINED)) != 0)
76 0 : elog(ERROR, "incorrect startup lock tranche name");
77 1 : if (strcmp("test_lwlock_tranches_startup10",
78 : GetLWLockIdentifier(PG_WAIT_LWLOCK, LWTRANCHE_FIRST_USER_DEFINED + 1)) != 0)
79 0 : elog(ERROR, "incorrect startup lock tranche name");
80 :
81 1 : PG_RETURN_VOID();
82 : }
83 :
84 : /*
85 : * Wrapper for LWLockNewTrancheId().
86 : */
87 2 : PG_FUNCTION_INFO_V1(test_lwlock_tranche_create);
88 : Datum
89 257 : test_lwlock_tranche_create(PG_FUNCTION_ARGS)
90 : {
91 257 : char *tranche_name = PG_ARGISNULL(0) ? NULL : TextDatumGetCString(PG_GETARG_DATUM(0));
92 : int tranche_id;
93 :
94 257 : tranche_id = LWLockNewTrancheId(tranche_name);
95 :
96 254 : PG_RETURN_INT32(tranche_id);
97 : }
98 :
99 : /*
100 : * Wrapper for GetNamedLWLockTranche().
101 : */
102 2 : PG_FUNCTION_INFO_V1(test_lwlock_tranche_lookup);
103 : Datum
104 2 : test_lwlock_tranche_lookup(PG_FUNCTION_ARGS)
105 : {
106 2 : char *tranche_name = TextDatumGetCString(PG_GETARG_DATUM(0));
107 :
108 2 : (void) GetNamedLWLockTranche(tranche_name);
109 :
110 0 : PG_RETURN_VOID();
111 : }
112 :
113 2 : PG_FUNCTION_INFO_V1(test_lwlock_get_lwlock_identifier);
114 : Datum
115 4 : test_lwlock_get_lwlock_identifier(PG_FUNCTION_ARGS)
116 : {
117 4 : int eventId = PG_GETARG_INT32(0);
118 : const char *tranche_name;
119 :
120 4 : tranche_name = GetLWLockIdentifier(PG_WAIT_LWLOCK, eventId);
121 :
122 4 : if (tranche_name)
123 4 : PG_RETURN_TEXT_P(cstring_to_text(tranche_name));
124 : else
125 0 : PG_RETURN_NULL();
126 : }
127 :
128 : /*
129 : * Wrapper for LWLockInitialize().
130 : */
131 2 : PG_FUNCTION_INFO_V1(test_lwlock_initialize);
132 : Datum
133 1 : test_lwlock_initialize(PG_FUNCTION_ARGS)
134 : {
135 1 : int tranche_id = PG_GETARG_INT32(0);
136 : LWLock lock;
137 :
138 1 : LWLockInitialize(&lock, tranche_id);
139 :
140 0 : PG_RETURN_VOID();
141 : }
|