]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | /* |
2 | * Example memory allocator with machine parseable logging. | |
3 | * | |
4 | * Also sizes for reallocs and frees are logged so that the memory | |
5 | * behavior can be essentially replayed to accurately determine e.g. | |
6 | * optimal pool sizes for a pooled allocator. | |
7 | * | |
8 | * Allocation structure: | |
9 | * | |
10 | * [ alloc_hdr | user area ] | |
11 | * | |
12 | * ^ ^ | |
13 | * | `--- pointer returned to Duktape | |
14 | * `--- underlying malloc ptr | |
15 | */ | |
16 | ||
17 | #include "duktape.h" | |
18 | #include <stdio.h> | |
19 | #include <stdlib.h> | |
20 | #include <string.h> | |
21 | #include <stdint.h> | |
22 | ||
23 | #define ALLOC_LOG_FILE "/tmp/duk-alloc-log.txt" | |
24 | ||
25 | typedef struct { | |
26 | /* The double value in the union is there to ensure alignment is | |
27 | * good for IEEE doubles too. In many 32-bit environments 4 bytes | |
28 | * would be sufficiently aligned and the double value is unnecessary. | |
29 | */ | |
30 | union { | |
31 | size_t sz; | |
32 | double d; | |
33 | } u; | |
34 | } alloc_hdr; | |
35 | ||
36 | static FILE *log_file = NULL; | |
37 | ||
38 | static void write_log(const char *fmt, ...) { | |
39 | va_list ap; | |
40 | ||
41 | if (!log_file) { | |
42 | log_file = fopen(ALLOC_LOG_FILE, "wb"); | |
43 | if (!log_file) { | |
44 | return; | |
45 | } | |
46 | } | |
47 | ||
48 | va_start(ap, fmt); | |
49 | vfprintf(log_file, fmt, ap); | |
50 | va_end(ap); | |
51 | } | |
52 | ||
53 | void *duk_alloc_logging(void *udata, duk_size_t size) { | |
54 | alloc_hdr *hdr; | |
55 | void *ret; | |
56 | ||
57 | (void) udata; /* Suppress warning. */ | |
58 | ||
59 | if (size == 0) { | |
60 | write_log("A NULL %ld\n", (long) size); | |
61 | return NULL; | |
62 | } | |
63 | ||
64 | hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr)); | |
65 | if (!hdr) { | |
66 | write_log("A FAIL %ld\n", (long) size); | |
67 | return NULL; | |
68 | } | |
69 | hdr->u.sz = size; | |
70 | ret = (void *) (hdr + 1); | |
71 | write_log("A %p %ld\n", ret, (long) size); | |
72 | return ret; | |
73 | } | |
74 | ||
75 | void *duk_realloc_logging(void *udata, void *ptr, duk_size_t size) { | |
76 | alloc_hdr *hdr; | |
77 | size_t old_size; | |
78 | void *t; | |
79 | void *ret; | |
80 | ||
81 | (void) udata; /* Suppress warning. */ | |
82 | ||
83 | /* Handle the ptr-NULL vs. size-zero cases explicitly to minimize | |
84 | * platform assumptions. You can get away with much less in specific | |
85 | * well-behaving environments. | |
86 | */ | |
87 | ||
88 | if (ptr) { | |
89 | hdr = (alloc_hdr *) (void *) ((unsigned char *) ptr - sizeof(alloc_hdr)); | |
90 | old_size = hdr->u.sz; | |
91 | ||
92 | if (size == 0) { | |
93 | write_log("R %p %ld NULL 0\n", ptr, (long) old_size); | |
94 | free((void *) hdr); | |
95 | return NULL; | |
96 | } else { | |
97 | t = realloc((void *) hdr, size + sizeof(alloc_hdr)); | |
98 | if (!t) { | |
99 | write_log("R %p %ld FAIL %ld\n", ptr, (long) old_size, (long) size); | |
100 | return NULL; | |
101 | } | |
102 | hdr = (alloc_hdr *) t; | |
103 | hdr->u.sz = size; | |
104 | ret = (void *) (hdr + 1); | |
105 | write_log("R %p %ld %p %ld\n", ptr, (long) old_size, ret, (long) size); | |
106 | return ret; | |
107 | } | |
108 | } else { | |
109 | if (size == 0) { | |
110 | write_log("R NULL 0 NULL 0\n"); | |
111 | return NULL; | |
112 | } else { | |
113 | hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr)); | |
114 | if (!hdr) { | |
115 | write_log("R NULL 0 FAIL %ld\n", (long) size); | |
116 | return NULL; | |
117 | } | |
118 | hdr->u.sz = size; | |
119 | ret = (void *) (hdr + 1); | |
120 | write_log("R NULL 0 %p %ld\n", ret, (long) size); | |
121 | return ret; | |
122 | } | |
123 | } | |
124 | } | |
125 | ||
126 | void duk_free_logging(void *udata, void *ptr) { | |
127 | alloc_hdr *hdr; | |
128 | ||
129 | (void) udata; /* Suppress warning. */ | |
130 | ||
131 | if (!ptr) { | |
132 | write_log("F NULL 0\n"); | |
133 | return; | |
134 | } | |
135 | hdr = (alloc_hdr *) (void *) ((unsigned char *) ptr - sizeof(alloc_hdr)); | |
136 | write_log("F %p %ld\n", ptr, (long) hdr->u.sz); | |
137 | free((void *) hdr); | |
138 | } |