1 /*-------------------------------------------------------------------------
4 * Simplistic testbed for shared memory and semaphore code.
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.
19 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
20 * Portions Copyright (c) 1994, Regents of the University of California
26 *-------------------------------------------------------------------------
32 #include "miscadmin.h"
33 #include "storage/ipc.h"
34 #include "storage/pg_sema.h"
35 #include "storage/pg_shmem.h"
38 /********* stuff needed to satisfy references in shmem/sema code *********/
41 volatile bool InterruptPending
= false;
42 volatile bool QueryCancelPending
= false;
43 volatile bool ProcDiePending
= false;
44 volatile bool ImmediateInterruptOK
= false;
45 volatile uint32 InterruptHoldoffCount
= 0;
46 volatile uint32 CritSectionCount
= 0;
48 bool IsUnderPostmaster
= false;
49 bool assert_enabled
= true;
57 #define MAX_ON_EXITS 20
61 pg_on_exit_callback function
;
63 } on_proc_exit_list
[MAX_ON_EXITS
], on_shmem_exit_list
[MAX_ON_EXITS
];
65 static int on_proc_exit_index
,
72 while (--on_proc_exit_index
>= 0)
73 (*on_proc_exit_list
[on_proc_exit_index
].function
) (code
,
74 on_proc_exit_list
[on_proc_exit_index
].arg
);
81 while (--on_shmem_exit_index
>= 0)
82 (*on_shmem_exit_list
[on_shmem_exit_index
].function
) (code
,
83 on_shmem_exit_list
[on_shmem_exit_index
].arg
);
84 on_shmem_exit_index
= 0;
88 on_shmem_exit(pg_on_exit_callback function
, Datum arg
)
90 if (on_shmem_exit_index
>= MAX_ON_EXITS
)
91 elog(FATAL
, "out of on_shmem_exit slots");
93 on_shmem_exit_list
[on_shmem_exit_index
].function
= function
;
94 on_shmem_exit_list
[on_shmem_exit_index
].arg
= arg
;
96 ++on_shmem_exit_index
;
102 on_shmem_exit_index
= 0;
103 on_proc_exit_index
= 0;
107 RecordSharedMemoryInLockFile(unsigned long id1
, unsigned long id2
)
112 ProcessInterrupts(void)
117 ExceptionalCondition(const char *conditionName
,
118 const char *errorType
,
119 const char *fileName
,
122 fprintf(stderr
, "TRAP: %s(\"%s\", File: \"%s\", Line: %d)\n",
123 errorType
, conditionName
,
124 fileName
, lineNumber
);
131 errcode_for_file_access(void)
137 errstart(int elevel
, const char *filename
, int lineno
,
138 const char *funcname
)
140 return (elevel
>= ERROR
);
144 errfinish(int dummy
,...)
150 elog_start(const char *filename
, int lineno
, const char *funcname
)
155 elog_finish(int elevel
, const char *fmt
,...)
157 fprintf(stderr
, "ERROR: %s\n", fmt
);
162 errcode(int sqlerrcode
)
164 return 0; /* return value does not matter */
168 errmsg(const char *fmt
,...)
170 fprintf(stderr
, "ERROR: %s\n", fmt
);
171 return 0; /* return value does not matter */
175 errmsg_internal(const char *fmt
,...)
177 fprintf(stderr
, "ERROR: %s\n", fmt
);
178 return 0; /* return value does not matter */
182 errdetail(const char *fmt
,...)
184 fprintf(stderr
, "DETAIL: %s\n", fmt
);
185 return 0; /* return value does not matter */
189 errdetail_log(const char *fmt
,...)
191 fprintf(stderr
, "DETAIL: %s\n", fmt
);
192 return 0; /* return value does not matter */
196 errhint(const char *fmt
,...)
198 fprintf(stderr
, "HINT: %s\n", fmt
);
199 return 0; /* return value does not matter */
203 /********* here's the actual test *********/
206 typedef struct MyStorage
208 PGShmemHeader header
;
215 main(int argc
, char **argv
)
220 printf("Creating shared memory ... ");
223 storage
= (MyStorage
*) PGSharedMemoryCreate(8192, false, 5433);
225 storage
->flag
= 1234;
229 printf("Creating semaphores ... ");
232 PGReserveSemaphores(2, 5433);
234 PGSemaphoreCreate(&storage
->sem
);
238 /* sema initial value is 1, so lock should work */
240 printf("Testing Lock ... ");
243 PGSemaphoreLock(&storage
->sem
, false);
247 /* now sema value is 0, so trylock should fail */
249 printf("Testing TryLock ... ");
252 if (PGSemaphoreTryLock(&storage
->sem
))
253 printf("unexpected result!\n");
257 /* unlocking twice and then locking twice should work... */
259 printf("Testing Multiple Lock ... ");
262 PGSemaphoreUnlock(&storage
->sem
);
263 PGSemaphoreUnlock(&storage
->sem
);
265 PGSemaphoreLock(&storage
->sem
, false);
266 PGSemaphoreLock(&storage
->sem
, false);
270 /* check Reset too */
272 printf("Testing Reset ... ");
275 PGSemaphoreUnlock(&storage
->sem
);
277 PGSemaphoreReset(&storage
->sem
);
279 if (PGSemaphoreTryLock(&storage
->sem
))
280 printf("unexpected result!\n");
284 /* Fork a child process and see if it can communicate */
286 printf("Forking child process ... ");
296 PGSemaphoreUnlock(&storage
->sem
);
302 printf("failed: %s\n", strerror(errno
));
306 printf("forked child pid %d OK\n", cpid
);
308 if (storage
->flag
!= 1234)
309 printf("Wrong value found in shared memory!\n");
311 printf("Waiting for child (should wait 3 sec here) ... ");
314 PGSemaphoreLock(&storage
->sem
, false);
318 if (storage
->flag
!= 1235)
319 printf("Wrong value found in shared memory!\n");
323 printf("Running shmem_exit processing ... ");
330 printf("Tests complete.\n");
334 return 0; /* not reached */