Line data Source code
1 : /*--------------------------------------------------------------------------
2 : *
3 : * test_dsa.c
4 : * Test dynamic shared memory areas (DSAs)
5 : *
6 : * Copyright (c) 2022-2025, PostgreSQL Global Development Group
7 : *
8 : * IDENTIFICATION
9 : * src/test/modules/test_dsa/test_dsa.c
10 : *
11 : * -------------------------------------------------------------------------
12 : */
13 : #include "postgres.h"
14 :
15 : #include "fmgr.h"
16 : #include "storage/dsm_registry.h"
17 : #include "storage/lwlock.h"
18 : #include "utils/dsa.h"
19 : #include "utils/resowner.h"
20 :
21 2 : PG_MODULE_MAGIC;
22 :
23 : static void
24 2 : init_tranche(void *ptr)
25 : {
26 2 : int *tranche_id = (int *) ptr;
27 :
28 2 : *tranche_id = LWLockNewTrancheId("test_dsa");
29 2 : }
30 :
31 : /* Test basic DSA functionality */
32 4 : PG_FUNCTION_INFO_V1(test_dsa_basic);
33 : Datum
34 2 : test_dsa_basic(PG_FUNCTION_ARGS)
35 : {
36 : int *tranche_id;
37 : bool found;
38 : dsa_area *a;
39 : dsa_pointer p[100];
40 :
41 2 : tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
42 : init_tranche, &found);
43 :
44 2 : a = dsa_create(*tranche_id);
45 202 : for (int i = 0; i < 100; i++)
46 : {
47 200 : p[i] = dsa_allocate(a, 1000);
48 200 : snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
49 : }
50 :
51 202 : for (int i = 0; i < 100; i++)
52 : {
53 : char buf[100];
54 :
55 200 : snprintf(buf, 100, "foobar%d", i);
56 200 : if (strcmp(dsa_get_address(a, p[i]), buf) != 0)
57 0 : elog(ERROR, "no match");
58 : }
59 :
60 202 : for (int i = 0; i < 100; i++)
61 : {
62 200 : dsa_free(a, p[i]);
63 : }
64 :
65 2 : dsa_detach(a);
66 :
67 2 : PG_RETURN_VOID();
68 : }
69 :
70 : /* Test using DSA across different resource owners */
71 4 : PG_FUNCTION_INFO_V1(test_dsa_resowners);
72 : Datum
73 2 : test_dsa_resowners(PG_FUNCTION_ARGS)
74 : {
75 : int *tranche_id;
76 : bool found;
77 : dsa_area *a;
78 : dsa_pointer p[10000];
79 : ResourceOwner oldowner;
80 : ResourceOwner childowner;
81 :
82 2 : tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
83 : init_tranche, &found);
84 :
85 : /* Create DSA in parent resource owner */
86 2 : a = dsa_create(*tranche_id);
87 :
88 : /*
89 : * Switch to child resource owner, and do a bunch of allocations in the
90 : * DSA
91 : */
92 2 : oldowner = CurrentResourceOwner;
93 2 : childowner = ResourceOwnerCreate(oldowner, "test_dsa temp owner");
94 2 : CurrentResourceOwner = childowner;
95 :
96 20002 : for (int i = 0; i < 10000; i++)
97 : {
98 20000 : p[i] = dsa_allocate(a, 1000);
99 20000 : snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
100 : }
101 :
102 : /* Also test freeing, by freeing some of the allocations. */
103 1002 : for (int i = 0; i < 500; i++)
104 1000 : dsa_free(a, p[i]);
105 :
106 : /* Release the child resource owner */
107 2 : CurrentResourceOwner = oldowner;
108 2 : ResourceOwnerRelease(childowner,
109 : RESOURCE_RELEASE_BEFORE_LOCKS,
110 : true, false);
111 2 : ResourceOwnerRelease(childowner,
112 : RESOURCE_RELEASE_LOCKS,
113 : true, false);
114 2 : ResourceOwnerRelease(childowner,
115 : RESOURCE_RELEASE_AFTER_LOCKS,
116 : true, false);
117 2 : ResourceOwnerDelete(childowner);
118 :
119 2 : dsa_detach(a);
120 :
121 2 : PG_RETURN_VOID();
122 : }
|