Skip to content

Commit 17ea23d

Browse files
committed
Add a trivial testbed for pg_sema and pg_shmem code.
1 parent 2010a43 commit 17ea23d

File tree

2 files changed

+285
-3
lines changed

2 files changed

+285
-3
lines changed

src/backend/port/Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# be converted to Method 2.
1414
#
1515
# IDENTIFICATION
16-
# $Header: /cvsroot/pgsql/src/backend/port/Makefile,v 1.12 2002/05/05 00:03:28 tgl Exp $
16+
# $Header: /cvsroot/pgsql/src/backend/port/Makefile,v 1.13 2002/05/05 16:02:37 tgl Exp $
1717
#
1818
#-------------------------------------------------------------------------
1919

@@ -25,7 +25,7 @@ OBJS = dynloader.o pg_sema.o pg_shmem.o
2525

2626
OBJS += $(GETHOSTNAME) $(GETRUSAGE) $(INET_ATON) $(ISINF) $(MEMCMP) \
2727
$(MISSING_RANDOM) $(SNPRINTF) $(SRANDOM) $(STRCASECMP) $(STRERROR) \
28-
$(STRTOL) $(STRTOUL) $(SNPRINTF)
28+
$(STRTOL) $(STRTOUL)
2929

3030
OBJS += $(TAS)
3131

@@ -68,8 +68,12 @@ darwin.dir:
6868
tas.o: tas.s
6969
$(CC) $(CFLAGS) -c $<
7070

71+
# IPC test program
72+
ipc_test: ipc_test.o pg_sema.o pg_shmem.o $(MEMCMP) $(SNPRINTF) $(STRERROR)
73+
$(CC) $(CFLAGS) $(LDFLAGS) $(export_dynamic) $^ $(LIBS) -o $@
74+
7175
distclean clean:
72-
rm -f SUBSYS.o $(OBJS)
76+
rm -f SUBSYS.o $(OBJS) ipc_test ipc_test.o
7377
$(MAKE) -C beos clean
7478
$(MAKE) -C darwin clean
7579
$(MAKE) -C qnx4 clean

src/backend/port/ipc_test.c

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* ipc_test.c
4+
* Simplistic testbed for shared memory and semaphore code.
5+
*
6+
* This file allows for quick "smoke testing" of a PG semaphore or shared
7+
* memory implementation, with less overhead than compiling up a whole
8+
* installation. To use:
9+
* 1. Run configure, then edit src/include/pg_config.h to select the
10+
* USE_xxx_SEMAPHORES and USE_xxx_SHARED_MEMORY settings you want.
11+
* Also, adjust the pg_sema.c and pg_shmem.c symlinks in
12+
* src/backend/port/ if needed.
13+
* 2. In src/backend/port/, do "gmake ipc_test".
14+
* 3. Run ipc_test and see if it works.
15+
* 4. If it seems to work, try building the whole system and running
16+
* the parallel regression tests for a more complete test.
17+
*
18+
*
19+
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
20+
* Portions Copyright (c) 1994, Regents of the University of California
21+
*
22+
*
23+
* IDENTIFICATION
24+
* $Header: /cvsroot/pgsql/src/backend/port/ipc_test.c,v 1.1 2002/05/05 16:02:37 tgl Exp $
25+
*
26+
*-------------------------------------------------------------------------
27+
*/
28+
#include "postgres.h"
29+
30+
#include <unistd.h>
31+
32+
#include "miscadmin.h"
33+
#include "storage/ipc.h"
34+
#include "storage/pg_sema.h"
35+
#include "storage/pg_shmem.h"
36+
#include "utils/exc.h"
37+
38+
39+
/********* stuff needed to satisfy references in shmem/sema code *********/
40+
41+
42+
volatile bool InterruptPending = false;
43+
volatile bool QueryCancelPending = false;
44+
volatile bool ProcDiePending = false;
45+
volatile bool ImmediateInterruptOK = false;
46+
volatile uint32 InterruptHoldoffCount = 0;
47+
volatile uint32 CritSectionCount = 0;
48+
49+
bool IsUnderPostmaster = false;
50+
51+
int MaxBackends = DEF_MAXBACKENDS;
52+
int NBuffers = DEF_NBUFFERS;
53+
54+
#ifndef assert_enabled
55+
bool assert_enabled = true;
56+
#endif
57+
58+
Exception FailedAssertion = {"Failed Assertion"};
59+
60+
61+
#define MAX_ON_EXITS 20
62+
63+
static struct ONEXIT
64+
{
65+
void (*function) ();
66+
Datum arg;
67+
} on_proc_exit_list[MAX_ON_EXITS], on_shmem_exit_list[MAX_ON_EXITS];
68+
69+
static int on_proc_exit_index,
70+
on_shmem_exit_index;
71+
72+
void
73+
proc_exit(int code)
74+
{
75+
shmem_exit(code);
76+
while (--on_proc_exit_index >= 0)
77+
(*on_proc_exit_list[on_proc_exit_index].function) (code,
78+
on_proc_exit_list[on_proc_exit_index].arg);
79+
exit(code);
80+
}
81+
82+
void
83+
shmem_exit(int code)
84+
{
85+
while (--on_shmem_exit_index >= 0)
86+
(*on_shmem_exit_list[on_shmem_exit_index].function) (code,
87+
on_shmem_exit_list[on_shmem_exit_index].arg);
88+
on_shmem_exit_index = 0;
89+
}
90+
91+
void
92+
on_shmem_exit(void (*function) (), Datum arg)
93+
{
94+
if (on_shmem_exit_index >= MAX_ON_EXITS)
95+
elog(FATAL, "Out of on_shmem_exit slots");
96+
97+
on_shmem_exit_list[on_shmem_exit_index].function = function;
98+
on_shmem_exit_list[on_shmem_exit_index].arg = arg;
99+
100+
++on_shmem_exit_index;
101+
}
102+
103+
void
104+
on_exit_reset(void)
105+
{
106+
on_shmem_exit_index = 0;
107+
on_proc_exit_index = 0;
108+
}
109+
110+
void
111+
RecordSharedMemoryInLockFile(unsigned long id1, unsigned long id2)
112+
{
113+
}
114+
115+
void
116+
ProcessInterrupts(void)
117+
{
118+
}
119+
120+
int
121+
ExceptionalCondition(char *conditionName,
122+
Exception *exceptionP,
123+
char *detail,
124+
char *fileName,
125+
int lineNumber)
126+
{
127+
fprintf(stderr, "TRAP: %s(\"%s:%s\", File: \"%s\", Line: %d)\n",
128+
exceptionP->message, conditionName,
129+
(detail == NULL ? "" : detail),
130+
fileName, lineNumber);
131+
abort();
132+
return 0;
133+
}
134+
135+
void
136+
elog(int lev, const char *fmt,...)
137+
{
138+
if (lev >= ERROR)
139+
{
140+
fprintf(stderr, "elog(%s)\n", fmt);
141+
abort();
142+
}
143+
}
144+
145+
146+
/********* here's the actual test *********/
147+
148+
149+
typedef struct MyStorage
150+
{
151+
PGShmemHeader header;
152+
int flag;
153+
PGSemaphoreData sem;
154+
} MyStorage;
155+
156+
157+
int
158+
main(int argc, char **argv)
159+
{
160+
MyStorage *storage;
161+
int cpid;
162+
163+
printf("Creating shared memory ... ");
164+
fflush(stdout);
165+
166+
storage = (MyStorage *) PGSharedMemoryCreate(8192, false, 5433);
167+
168+
storage->flag = 1234;
169+
170+
printf("OK\n");
171+
172+
printf("Creating semaphores ... ");
173+
fflush(stdout);
174+
175+
PGReserveSemaphores(2, 5433);
176+
177+
PGSemaphoreCreate(&storage->sem);
178+
179+
printf("OK\n");
180+
181+
/* sema initial value is 1, so lock should work */
182+
183+
printf("Testing Lock ... ");
184+
fflush(stdout);
185+
186+
PGSemaphoreLock(&storage->sem, false);
187+
188+
printf("OK\n");
189+
190+
/* now sema value is 0, so trylock should fail */
191+
192+
printf("Testing TryLock ... ");
193+
fflush(stdout);
194+
195+
if (PGSemaphoreTryLock(&storage->sem))
196+
printf("unexpected result!\n");
197+
else
198+
printf("OK\n");
199+
200+
/* unlocking twice and then locking twice should work... */
201+
202+
printf("Testing Multiple Lock ... ");
203+
fflush(stdout);
204+
205+
PGSemaphoreUnlock(&storage->sem);
206+
PGSemaphoreUnlock(&storage->sem);
207+
208+
PGSemaphoreLock(&storage->sem, false);
209+
PGSemaphoreLock(&storage->sem, false);
210+
211+
printf("OK\n");
212+
213+
/* check Reset too */
214+
215+
printf("Testing Reset ... ");
216+
fflush(stdout);
217+
218+
PGSemaphoreUnlock(&storage->sem);
219+
220+
PGSemaphoreReset(&storage->sem);
221+
222+
if (PGSemaphoreTryLock(&storage->sem))
223+
printf("unexpected result!\n");
224+
else
225+
printf("OK\n");
226+
227+
/* Fork a child process and see if it can communicate */
228+
229+
printf("Forking child process ... ");
230+
fflush(stdout);
231+
232+
cpid = fork();
233+
if (cpid == 0)
234+
{
235+
/* In child */
236+
on_exit_reset();
237+
sleep(3);
238+
storage->flag++;
239+
PGSemaphoreUnlock(&storage->sem);
240+
proc_exit(0);
241+
}
242+
if (cpid < 0)
243+
{
244+
/* Fork failed */
245+
printf("failed: %s\n", strerror(errno));
246+
proc_exit(1);
247+
}
248+
249+
printf("forked child pid %d OK\n", cpid);
250+
251+
if (storage->flag != 1234)
252+
printf("Wrong value found in shared memory!\n");
253+
254+
printf("Waiting for child (should wait 3 sec here) ... ");
255+
fflush(stdout);
256+
257+
PGSemaphoreLock(&storage->sem, false);
258+
259+
printf("OK\n");
260+
261+
if (storage->flag != 1235)
262+
printf("Wrong value found in shared memory!\n");
263+
264+
/* Test shutdown */
265+
266+
printf("Running shmem_exit processing ... ");
267+
fflush(stdout);
268+
269+
shmem_exit(0);
270+
271+
printf("OK\n");
272+
273+
printf("Tests complete.\n");
274+
275+
proc_exit(0);
276+
277+
return 0; /* not reached */
278+
}

0 commit comments

Comments
 (0)