Mercurial > dropbear
annotate dbmalloc.c @ 1564:86e4995bbedf
more portable for `which hg` test
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 28 Feb 2018 23:42:57 +0800 |
parents | 7209a6e30932 |
children | c42e8ff42bd1 |
rev | line source |
---|---|
1361 | 1 #include "dbmalloc.h" |
2 #include "dbutil.h" | |
3 | |
4 struct dbmalloc_header { | |
5 unsigned int epoch; | |
1378 | 6 struct dbmalloc_header *prev; |
7 struct dbmalloc_header *next; | |
1361 | 8 }; |
9 | |
1378 | 10 static void put_alloc(struct dbmalloc_header *header); |
11 static void remove_alloc(struct dbmalloc_header *header); | |
12 | |
13 /* end of the linked list */ | |
14 static struct dbmalloc_header* staple; | |
1361 | 15 |
16 unsigned int current_epoch = 0; | |
17 | |
18 void m_malloc_set_epoch(unsigned int epoch) { | |
19 current_epoch = epoch; | |
20 } | |
21 | |
1378 | 22 void m_malloc_free_epoch(unsigned int epoch, int dofree) { |
23 struct dbmalloc_header* header; | |
24 struct dbmalloc_header* nextheader = NULL; | |
25 struct dbmalloc_header* oldstaple = staple; | |
26 staple = NULL; | |
27 /* free allocations from this epoch, create a new staple-anchored list from | |
28 the remainder */ | |
29 for (header = oldstaple; header; header = nextheader) | |
30 { | |
31 nextheader = header->next; | |
32 if (header->epoch == epoch) { | |
33 if (dofree) { | |
34 free(header); | |
1361 | 35 } |
1378 | 36 } else { |
37 header->prev = NULL; | |
38 header->next = NULL; | |
39 put_alloc(header); | |
1361 | 40 } |
41 } | |
42 } | |
43 | |
44 static void put_alloc(struct dbmalloc_header *header) { | |
1378 | 45 assert(header->next == NULL); |
46 assert(header->prev == NULL); | |
47 if (staple) { | |
48 staple->prev = header; | |
1361 | 49 } |
1378 | 50 header->next = staple; |
51 staple = header; | |
1361 | 52 } |
53 | |
54 static void remove_alloc(struct dbmalloc_header *header) { | |
1378 | 55 if (header->prev) { |
56 header->prev->next = header->next; | |
57 } | |
58 if (header->next) { | |
59 header->next->prev = header->prev; | |
60 } | |
61 if (staple == header) { | |
62 staple = header->next; | |
63 } | |
64 header->prev = NULL; | |
65 header->next = NULL; | |
1361 | 66 } |
67 | |
68 static struct dbmalloc_header* get_header(void* ptr) { | |
69 char* bptr = ptr; | |
70 return (struct dbmalloc_header*)&bptr[-sizeof(struct dbmalloc_header)]; | |
71 } | |
72 | |
73 void * m_malloc(size_t size) { | |
74 char* mem = NULL; | |
75 struct dbmalloc_header* header = NULL; | |
76 | |
77 if (size == 0 || size > 1e9) { | |
78 dropbear_exit("m_malloc failed"); | |
79 } | |
80 | |
81 size = size + sizeof(struct dbmalloc_header); | |
82 | |
83 mem = calloc(1, size); | |
84 if (mem == NULL) { | |
85 dropbear_exit("m_malloc failed"); | |
86 } | |
87 header = (struct dbmalloc_header*)mem; | |
88 put_alloc(header); | |
89 header->epoch = current_epoch; | |
90 return &mem[sizeof(struct dbmalloc_header)]; | |
91 } | |
92 | |
93 void * m_calloc(size_t nmemb, size_t size) { | |
1365
9aa6cd66b51d
zlib can use m_malloc/m_free too
Matt Johnston <matt@ucc.asn.au>
parents:
1361
diff
changeset
|
94 if (SIZE_T_MAX / nmemb < size) { |
9aa6cd66b51d
zlib can use m_malloc/m_free too
Matt Johnston <matt@ucc.asn.au>
parents:
1361
diff
changeset
|
95 dropbear_exit("m_calloc failed"); |
9aa6cd66b51d
zlib can use m_malloc/m_free too
Matt Johnston <matt@ucc.asn.au>
parents:
1361
diff
changeset
|
96 } |
1361 | 97 return m_malloc(nmemb*size); |
98 } | |
99 | |
100 void * m_realloc(void* ptr, size_t size) { | |
101 char* mem = NULL; | |
102 struct dbmalloc_header* header = NULL; | |
103 if (size == 0 || size > 1e9) { | |
104 dropbear_exit("m_realloc failed"); | |
105 } | |
106 | |
107 header = get_header(ptr); | |
108 remove_alloc(header); | |
109 | |
110 size = size + sizeof(struct dbmalloc_header); | |
111 mem = realloc(header, size); | |
112 if (mem == NULL) { | |
113 dropbear_exit("m_realloc failed"); | |
114 } | |
115 | |
116 header = (struct dbmalloc_header*)mem; | |
117 put_alloc(header); | |
118 return &mem[sizeof(struct dbmalloc_header)]; | |
119 } | |
120 | |
121 void m_free_direct(void* ptr) { | |
122 struct dbmalloc_header* header = NULL; | |
123 if (!ptr) { | |
124 return; | |
125 } | |
126 header = get_header(ptr); | |
127 remove_alloc(header); | |
128 free(header); | |
129 } | |
130 | |
131 void * m_strdup(const char * str) { | |
132 char* ret; | |
133 unsigned int len; | |
134 len = strlen(str); | |
135 | |
136 ret = m_malloc(len+1); | |
137 if (ret == NULL) { | |
138 dropbear_exit("m_strdup failed"); | |
139 } | |
140 memcpy(ret, str, len+1); | |
141 return ret; | |
142 } | |
143 | |
144 |