]> git.ozlabs.org Git - ccan/blob - ccan/altstack/_info
a33af2cea802934cce4f5c6dd263ebde4fa382af
[ccan] / ccan / altstack / _info
1 #include "config.h"
2 #include <stdio.h>
3 #include <string.h>
4
5 /**
6  *
7  * altstack - run a function with a dedicated stack, and then release the memory
8  *
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.
12  *
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.
16  *
17  * altstack provides a way to obtain current stack usage and a way to fail gracefully.
18  *
19  * altstack is implemented for x86-64 only.
20  *
21  * Example:
22  *      // allocate a VLA on a dedicated stack and show memory usage
23  *      #include <assert.h>
24  *      #include <err.h>
25  *      #include <stdio.h>
26  *      #include <stdlib.h>
27  *      #include <string.h>
28  *      #include <unistd.h>
29  *      #include <ccan/altstack/altstack.h>
30  *
31  *      #define ok(x) ({ int __r = (x); if (__r == -1) err(1, #x); __r; })
32  *
33  *      char maps[128], rss[128];
34  *
35  *      static void stack_used(void) {
36  *              fprintf(stderr, "stack used: %ld\n", altstack_used());
37  *      }
38  *
39  *      static void *fn(void *arg)
40  *      {
41  *              ok(system(maps));
42  *
43  *              stack_used();
44  *              ok(system(rss));
45  *
46  *              char p[(long) arg];
47  *
48  *              stack_used();
49  *              ok(system(rss));
50  *
51  *              memset(p, 0, sizeof(p));
52  *
53  *              stack_used();
54  *              ok(system(rss));
55  *
56  *              return (void *) 0xaced;
57  *      }
58  *
59  *      int main(int argc, char *argv[])
60  *      {
61  *              long stk_max, vla_sz;
62  *              int ret;
63  *              void *out;
64  *
65  *              assert(argc == 3);
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);
69  *
70  *              snprintf(maps, sizeof(maps), "egrep '\\[stack' /proc/%d/maps", getpid());
71  *              snprintf(rss,  sizeof(rss),  "egrep '^VmRSS' /proc/%d/status", getpid());
72  *
73  *              ok(system(maps));
74  *              ok(system(rss));
75  *
76  *              ret = altstack(stk_max, fn, (void *) vla_sz, &out);
77  *
78  *              ok(system(maps));
79  *              ok(system(rss));
80  *
81  *              if (ret)
82  *                      altstack_perror();
83  *              fprintf(stderr, "altstack return: %d, fn return: %p\n", ret, out);
84  *
85  *              return 0;
86  *      }
87  *      // $ ./foo 1024 512
88  *      // 7ffeb59a9000-7ffeb59ca000 rw-p 00000000 00:00 0                          [stack]
89  *      // VmRSS:       760 kB
90  *      // 7f9cb6005000-7f9cf6004000 rw-p 00000000 00:00 0                          [stack:25891]
91  *      // stack used: 56
92  *      // VmRSS:       760 kB
93  *      // stack used: 536870968
94  *      // VmRSS:       760 kB
95  *      // stack used: 536870968
96  *      // VmRSS:    525500 kB
97  *      // 7ffeb59a9000-7ffeb59ca000 rw-p 00000000 00:00 0                          [stack]
98  *      // VmRSS:      1332 kB
99  *      // altstack return: 0, fn return: 0xaced
100  *      //
101  *      // $ ./foo 512 1024
102  *      // 7ffd62bd0000-7ffd62bf1000 rw-p 00000000 00:00 0                          [stack]
103  *      // VmRSS:       700 kB
104  *      // 7f0d3bef6000-7f0d5bef5000 rw-p 00000000 00:00 0                          [stack:25900]
105  *      // stack used: 56
106  *      // VmRSS:       700 kB
107  *      // 7ffd62bd0000-7ffd62bf1000 rw-p 00000000 00:00 0                          [stack]
108  *      // VmRSS:      1336 kB
109  *      // (altstack@103) SIGSEGV caught
110  *      // altstack return: -1, fn return: (nil)
111  *
112  * Ccanlint: tests_pass_valgrind FAIL
113  * License: APACHE-2
114  * Author: Dan Good <dan@dancancode.com>
115  */
116 int main(int argc, char *argv[])
117 {
118         /* Expect exactly one argument */
119         if (argc != 2)
120                 return 1;
121
122         if (strcmp(argv[1], "depends") == 0)
123                 return 0;
124
125         if (strcmp(argv[1], "ported") == 0) {
126 #ifdef __x86_64__
127                 printf("1\n");
128 #else
129                 printf("0\n");
130 #endif
131         }
132
133         return 1;
134 }