summaryrefslogtreecommitdiff
path: root/src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c
blob: a4f7fb208650f03e559137278241c63172c47b59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*--------------------------------------------------------------------------
 *
 * test_lwlock_tranches.c
 *		Test code for LWLock tranches allocated by extensions.
 *
 * Copyright (c) 2025, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *		src/test/modules/test_lwlock_tranches/test_lwlock_tranches.c
 *
 * -------------------------------------------------------------------------
 */

#include "postgres.h"

#include "fmgr.h"
#include "miscadmin.h"
#include "storage/lwlock.h"
#include "utils/builtins.h"
#include "utils/wait_classes.h"

PG_MODULE_MAGIC;

#define STARTUP_TRANCHE_NAME "test_lwlock_tranches_startup"
#define DYNAMIC_TRANCHE_NAME "test_lwlock_tranches_dynamic"

#define NUM_STARTUP_TRANCHES (32)
#define NUM_DYNAMIC_TRANCHES (256 - NUM_STARTUP_TRANCHES)

#define GET_TRANCHE_NAME(a) GetLWLockIdentifier(PG_WAIT_LWLOCK, (a))

static shmem_request_hook_type prev_shmem_request_hook;
static void test_lwlock_tranches_shmem_request(void);

void
_PG_init(void)
{
	prev_shmem_request_hook = shmem_request_hook;
	shmem_request_hook = test_lwlock_tranches_shmem_request;
}

static void
test_lwlock_tranches_shmem_request(void)
{
	if (prev_shmem_request_hook)
		prev_shmem_request_hook();

	for (int i = 0; i < NUM_STARTUP_TRANCHES; i++)
		RequestNamedLWLockTranche(STARTUP_TRANCHE_NAME, 1);
}

/*
 * Checks that GetLWLockIdentifier() returns the expected value for tranches
 * registered via RequestNamedLWLockTranche() and LWLockNewTrancheId().
 */
PG_FUNCTION_INFO_V1(test_lwlock_tranches);
Datum
test_lwlock_tranches(PG_FUNCTION_ARGS)
{
	int			dynamic_tranches[NUM_DYNAMIC_TRANCHES];

	for (int i = 0; i < NUM_DYNAMIC_TRANCHES; i++)
		dynamic_tranches[i] = LWLockNewTrancheId(DYNAMIC_TRANCHE_NAME);

	for (int i = 0; i < NUM_STARTUP_TRANCHES; i++)
	{
		if (strcmp(GET_TRANCHE_NAME(LWTRANCHE_FIRST_USER_DEFINED + i),
				   STARTUP_TRANCHE_NAME) != 0)
			elog(ERROR, "incorrect startup lock tranche name");
	}

	for (int i = 0; i < NUM_DYNAMIC_TRANCHES; i++)
	{
		if (strcmp(GET_TRANCHE_NAME(dynamic_tranches[i]),
				   DYNAMIC_TRANCHE_NAME) != 0)
			elog(ERROR, "incorrect dynamic lock tranche name");
	}

	PG_RETURN_VOID();
}

/*
 * Wrapper for LWLockNewTrancheId().
 */
PG_FUNCTION_INFO_V1(test_lwlock_tranche_creation);
Datum
test_lwlock_tranche_creation(PG_FUNCTION_ARGS)
{
	char	   *tranche_name = PG_ARGISNULL(0) ? NULL : TextDatumGetCString(PG_GETARG_DATUM(0));

	(void) LWLockNewTrancheId(tranche_name);

	PG_RETURN_VOID();
}

/*
 * Wrapper for GetNamedLWLockTranche().
 */
PG_FUNCTION_INFO_V1(test_lwlock_tranche_lookup);
Datum
test_lwlock_tranche_lookup(PG_FUNCTION_ARGS)
{
	char	   *tranche_name = TextDatumGetCString(PG_GETARG_DATUM(0));

	(void) GetNamedLWLockTranche(tranche_name);

	PG_RETURN_VOID();
}

/*
 * Wrapper for LWLockInitialize().
 */
PG_FUNCTION_INFO_V1(test_lwlock_initialize);
Datum
test_lwlock_initialize(PG_FUNCTION_ARGS)
{
	int			tranche_id = PG_GETARG_INT32(0);
	LWLock		lock;

	LWLockInitialize(&lock, tranche_id);

	PG_RETURN_VOID();
}