7 * altstack - run a function with a dedicated stack, and then release the memory
9 * C99 introduced variable length arrays to make the language easier to use
10 * and more efficient. Many regard VLA's with distrust due to fear of stack
11 * overflow. The same fear causes many to shy away from recursion.
13 * altstack seeks to liberate us from this fear. altstack creates a dedicated stack,
14 * limited to a specified maximum size, runs a given function using this stack, and
15 * afterwards releases the memory back to the system.
17 * altstack provides a way to obtain current stack usage and a way to fail gracefully.
19 * altstack is implemented for x86-64 only.
22 * // allocate a VLA on a dedicated stack and show memory usage
29 * #include <ccan/altstack/altstack.h>
31 * #define ok(x) ({ int __r = (x); if (__r == -1) err(1, #x); __r; })
33 * char maps[128], rss[128];
35 * static void stack_used(void) {
36 * fprintf(stderr, "stack used: %ld\n", altstack_used());
39 * static void *fn(void *arg)
51 * memset(p, 0, sizeof(p));
56 * return (void *) 0xaced;
59 * int main(int argc, char *argv[])
61 * long stk_max, vla_sz;
66 * stk_max = strtol(argv[1], 0, 0) * 1024 * 1024;
67 * vla_sz = strtol(argv[2], 0, 0) * 1024 * 1024;
68 * assert(stk_max > 0 && vla_sz > 0);
70 * snprintf(maps, sizeof(maps), "egrep '\\[stack' /proc/%d/maps", getpid());
71 * snprintf(rss, sizeof(rss), "egrep '^VmRSS' /proc/%d/status", getpid());
76 * ret = altstack(stk_max, fn, (void *) vla_sz, &out);
83 * fprintf(stderr, "altstack return: %d, fn return: %p\n", ret, out);
88 * // 7ffeb59a9000-7ffeb59ca000 rw-p 00000000 00:00 0 [stack]
90 * // 7f9cb6005000-7f9cf6004000 rw-p 00000000 00:00 0 [stack:25891]
93 * // stack used: 536870968
95 * // stack used: 536870968
97 * // 7ffeb59a9000-7ffeb59ca000 rw-p 00000000 00:00 0 [stack]
99 * // altstack return: 0, fn return: 0xaced
101 * // $ ./foo 512 1024
102 * // 7ffd62bd0000-7ffd62bf1000 rw-p 00000000 00:00 0 [stack]
104 * // 7f0d3bef6000-7f0d5bef5000 rw-p 00000000 00:00 0 [stack:25900]
107 * // 7ffd62bd0000-7ffd62bf1000 rw-p 00000000 00:00 0 [stack]
109 * // (altstack@103) SIGSEGV caught
110 * // altstack return: -1, fn return: (nil)
112 * Ccanlint: tests_pass_valgrind FAIL
114 * Author: Dan Good <dan@dancancode.com>
116 int main(int argc, char *argv[])
118 /* Expect exactly one argument */
122 if (strcmp(argv[1], "depends") == 0)
125 if (strcmp(argv[1], "ported") == 0) {
129 printf("Only x86-64 supported\n");