]> git.ozlabs.org Git - ccan/blob - ccan/rszshm/_info
cc95400ce64f53bc0496b74bb2be4d2351197b33
[ccan] / ccan / rszshm / _info
1 #include "config.h"
2 #include <stdio.h>
3 #include <string.h>
4
5 /**
6  * rszshm - resizable pointer-safe shared memory
7  *
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.
11  *
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.
23  *
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
28  * return an error.
29  *
30  * Example:
31  *      // fork x times, grow and fill shared memory cooperatively
32  *      #include <assert.h>
33  *      #include <err.h>
34  *      #include <signal.h>
35  *      #include <stdio.h>
36  *      #include <unistd.h>
37  *      #include <ccan/rszshm/rszshm.h>
38  *
39  *      #define ok(x) ({ int n = (x); if (n == -1) err(1, "%s", #x); n; })
40  *
41  *      int main(int argc, char *argv[]) {
42  *              int pidcnt, stopval, n, i;
43  *              struct rszshm *r;
44  *              char *m;
45  *
46  *              assert(argc == 3);
47  *              pidcnt  = atoi(argv[1]);
48  *              stopval = atoi(argv[2]);
49  *              assert(pidcnt > 0 && stopval > 0);
50  *
51  *              if (!rszshm_mkm(r, 4096, NULL))
52  *                      err(1, "rszshm_mkm");
53  *
54  *              printf("%s\n", r->fname);
55  *
56  *              for (n = 0; n < pidcnt - 1; n++)
57  *                      if (ok(fork()) == 0)
58  *                              break;
59  *
60  *              m = (char *) r->dat + sizeof(int);
61  *              #define next() (__sync_fetch_and_add((int *) r->dat, 1))
62  *
63  *              for(i = next(); i < stopval; i = next()) {
64  *                      if (i >= r->cap - sizeof(int))
65  *                              ok(rszshm_grow(r));
66  *                      assert(m[i] == '\0');
67  *                      m[i] = 'A' + n;
68  *                      kill(0, 0); // busy work
69  *              }
70  *
71  *              rszshm_free(r);
72  *              return 0;
73  *      }
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
78  *
79  * Ccanlint: tests_pass_valgrind FAIL
80  * License: APACHE-2
81  * Author: Dan Good <dan@dancancode.com>
82  *
83  * Ccanlint:
84  *      // tests use optional macros containing statement expressions
85  *      tests_compile_without_features FAIL
86  */
87 int main(int argc, char *argv[])
88 {
89         /* Expect exactly one argument */
90         if (argc != 2)
91                 return 1;
92
93         if (strcmp(argv[1], "depends") == 0)
94                 return 0;
95
96         return 1;
97 }