X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Faltstack%2F_info;fp=ccan%2Faltstack%2F_info;h=1b03770553c034f09bfdcf273a94233b980dbb73;hb=e65a92188aa1ac4c27a86d427acdf09417595ade;hp=0000000000000000000000000000000000000000;hpb=9840dbd3e19eaee1ed82a445cd5e9f041a434f70;p=ccan diff --git a/ccan/altstack/_info b/ccan/altstack/_info new file mode 100644 index 00000000..1b037705 --- /dev/null +++ b/ccan/altstack/_info @@ -0,0 +1,125 @@ +#include "config.h" +#include +#include + +/** + * + * altstack - run a function with a dedicated stack, and then release the memory + * + * C99 introduced variable length arrays to make the language easier to use + * and more efficient. Many regard VLA's with distrust due to fear of stack + * overflow. The same fear causes many to shy away from recursion. + * + * altstack seeks to liberate us from this fear. altstack creates a dedicated stack, + * limited to a specified maximum size, runs a given function using this stack, and + * afterwards releases the memory back to the system. + * + * altstack provides a way to obtain current stack usage and a way to fail gracefully. + * + * altstack is implemented for x86-64 only. + * + * Example: + * // allocate a VLA on a dedicated stack and show memory usage + * #include + * #include + * #include + * #include + * #include + * #include + * #include + * + * #define ok(x) ({ int __r = (x); if (__r == -1) err(1, #x); __r; }) + * + * char maps[128], rss[128]; + * + * static void stack_used(void) { + * fprintf(stderr, "stack used: %ld\n", altstack_used()); + * } + * + * static void *fn(void *arg) + * { + * ok(system(maps)); + * + * stack_used(); + * ok(system(rss)); + * + * char p[(long) arg]; + * + * stack_used(); + * ok(system(rss)); + * + * memset(p, 0, sizeof(p)); + * + * stack_used(); + * ok(system(rss)); + * + * return (void *) 0xaced; + * } + * + * int main(int argc, char *argv[]) + * { + * long stk_max, vla_sz; + * int ret; + * void *out; + * + * assert(argc == 3); + * stk_max = strtol(argv[1], 0, 0) * 1024 * 1024; + * vla_sz = strtol(argv[2], 0, 0) * 1024 * 1024; + * assert(stk_max > 0 && vla_sz > 0); + * + * snprintf(maps, sizeof(maps), "egrep '\\[stack' /proc/%d/maps", getpid()); + * snprintf(rss, sizeof(rss), "egrep '^VmRSS' /proc/%d/status", getpid()); + * + * ok(system(maps)); + * ok(system(rss)); + * + * ret = altstack(stk_max, fn, (void *) vla_sz, &out); + * + * ok(system(maps)); + * ok(system(rss)); + * + * if (ret) + * altstack_perror(); + * fprintf(stderr, "altstack return: %d, fn return: %p\n", ret, out); + * + * return 0; + * } + * // $ ./foo 1024 512 + * // 7ffeb59a9000-7ffeb59ca000 rw-p 00000000 00:00 0 [stack] + * // VmRSS: 760 kB + * // 7f9cb6005000-7f9cf6004000 rw-p 00000000 00:00 0 [stack:25891] + * // stack used: 56 + * // VmRSS: 760 kB + * // stack used: 536870968 + * // VmRSS: 760 kB + * // stack used: 536870968 + * // VmRSS: 525500 kB + * // 7ffeb59a9000-7ffeb59ca000 rw-p 00000000 00:00 0 [stack] + * // VmRSS: 1332 kB + * // altstack return: 0, fn return: 0xaced + * // + * // $ ./foo 512 1024 + * // 7ffd62bd0000-7ffd62bf1000 rw-p 00000000 00:00 0 [stack] + * // VmRSS: 700 kB + * // 7f0d3bef6000-7f0d5bef5000 rw-p 00000000 00:00 0 [stack:25900] + * // stack used: 56 + * // VmRSS: 700 kB + * // 7ffd62bd0000-7ffd62bf1000 rw-p 00000000 00:00 0 [stack] + * // VmRSS: 1336 kB + * // (altstack@103) SIGSEGV caught + * // altstack return: -1, fn return: (nil) + * + * License: APACHE-2 + * Author: Dan Good + */ +int main(int argc, char *argv[]) +{ + /* Expect exactly one argument */ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) + return 0; + + return 1; +}