6 * rszshm - resizable pointer-safe shared memory
8 * If two separate processes have shared mappings of the same file at the
9 * same address, then pointers to addresses within the region can be shared
10 * between the processes and safely dereferenced.
12 * Mapping to the same address in unrelated processes is nontrivial. One can
13 * request a specific address, but mmap will return another in case of an
14 * overlap. One can require a specific address, but mmap will unmap anything
15 * overlapped. On Linux boxes it can be seen that the used addresses clump
16 * at either end of the address range. rszshm tries to mmap in the middle
17 * of the address range, and checks if the requested address matches the
18 * returned address. If not, additional addresses are tried. Once mapped,
19 * the address is recorded to a header in the file. Another process reads the
20 * header and requests the saved address from mmap. If the returned address
21 * matches, work proceeds. While the defaults provide a propitious search,
22 * all the search parameters may be specified.
24 * To accommodate resizing, rszshm first maps a large, private, noreserve map.
25 * This serves to claim a span of addresses. The shared file mapping then
26 * overlays the beginning of the span. Later calls to extend the mapping
27 * overlay more of the span. Attempts to extend beyond the end of the span
31 * // fork x times, grow and fill shared memory cooperatively
37 * #include <ccan/rszshm/rszshm.h>
39 * #define ok(x) ({ int n = (x); if (n == -1) err(1, "%s", #x); n; })
41 * int main(int argc, char *argv[]) {
42 * int pidcnt, stopval, n, i;
47 * pidcnt = atoi(argv[1]);
48 * stopval = atoi(argv[2]);
49 * assert(pidcnt > 0 && stopval > 0);
51 * if (!rszshm_mkm(r, 4096, NULL))
52 * err(1, "rszshm_mkm");
54 * printf("%s\n", r->fname);
56 * for (n = 0; n < pidcnt - 1; n++)
57 * if (ok(fork()) == 0)
60 * m = (char *) r->dat + sizeof(int);
61 * #define next() (__sync_fetch_and_add((int *) r->dat, 1))
63 * for(i = next(); i < stopval; i = next()) {
64 * if (i >= r->cap - sizeof(int))
66 * assert(m[i] == '\0');
68 * kill(0, 0); // busy work
74 * // $ ./foo 8 $((4*1024*1024-28))
75 * // /dev/shm/rszshm_LAsEvt/0
76 * // $ tail -c +29 /dev/shm/rszshm_LAsEvt/0 | sed 's/./&\n/g' | sort | uniq -c | tr '\n' '\t'; echo
77 * // 515532 A 527251 B 512930 C 513062 D 544326 E 545876 F 512936 G 522363 H
79 * Ccanlint: tests_pass_valgrind FAIL
81 * Author: Dan Good <dan@dancancode.com>
84 * // tests use optional macros containing statement expressions
85 * tests_compile_without_features FAIL
87 int main(int argc, char *argv[])
89 /* Expect exactly one argument */
93 if (strcmp(argv[1], "depends") == 0)