KFW Network Identity Manager (Beta 2)
[krb5.git] / src / windows / identity / util / perfstat.c
1 /*\r
2  * Copyright (c) 2005 Massachusetts Institute of Technology\r
3  *\r
4  * Permission is hereby granted, free of charge, to any person\r
5  * obtaining a copy of this software and associated documentation\r
6  * files (the "Software"), to deal in the Software without\r
7  * restriction, including without limitation the rights to use, copy,\r
8  * modify, merge, publish, distribute, sublicense, and/or sell copies\r
9  * of the Software, and to permit persons to whom the Software is\r
10  * furnished to do so, subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be\r
13  * included in all copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
22  * SOFTWARE.\r
23  */\r
24 \r
25 /* $Id$ */\r
26 \r
27 #include<windows.h>\r
28 #include<utils.h>\r
29 #include<malloc.h>\r
30 #include<stdio.h>\r
31 #include<strsafe.h>\r
32 #include<assert.h>\r
33 \r
34 #define HASHSIZE 1151\r
35 #define ALLOCBLOCK 1024\r
36 \r
37 #define HASHPTR(p) (((size_t) (p)) % HASHSIZE)\r
38 \r
39 typedef struct tag_allocation {\r
40     char   file[8];\r
41     int    line;\r
42     size_t size;\r
43     void * ptr;\r
44 \r
45     LDCL(struct tag_allocation);\r
46 } allocation;\r
47 \r
48 static allocation * ht[HASHSIZE];\r
49 \r
50 static allocation * next_alloc = NULL;\r
51 static size_t       idx_next_alloc = 0;\r
52 static allocation * free_alloc = NULL;\r
53 \r
54 static CRITICAL_SECTION cs_alloc;\r
55 static LONG ctr = 0;\r
56 static int  perf_ready = 0;\r
57 \r
58 static void perf_once(void) {\r
59     if (InterlockedIncrement(&ctr) == 1) {\r
60         InitializeCriticalSection(&cs_alloc);\r
61         ZeroMemory(ht, sizeof(ht));\r
62 \r
63         next_alloc = malloc(sizeof(allocation) * ALLOCBLOCK);\r
64         assert(next_alloc);\r
65         idx_next_alloc = 0;\r
66         free_alloc = NULL;\r
67 \r
68         perf_ready = 1;\r
69     } else {\r
70         while(!perf_ready) {\r
71             Sleep(0);           /* relinquish control to the thread\r
72                                    that is initializing the alloc\r
73                                    data. */\r
74         }\r
75     }\r
76 }\r
77 \r
78 static allocation * get_allocation(void) {\r
79     allocation * a;\r
80 \r
81     LPOP(&free_alloc, &a);\r
82     if (!a) {\r
83         if (idx_next_alloc == ALLOCBLOCK) {\r
84             next_alloc = malloc(sizeof(allocation) * ALLOCBLOCK);\r
85             assert(next_alloc);\r
86             idx_next_alloc = 0;\r
87         }\r
88 \r
89         a = &next_alloc[idx_next_alloc];\r
90         idx_next_alloc++;\r
91     }\r
92 \r
93     return a;\r
94 }\r
95 \r
96 #define MAXCB_STR 32768\r
97 \r
98 KHMEXP wchar_t *\r
99 perf_wcsdup(char * file, int line, const wchar_t * str) {\r
100     size_t cb;\r
101     wchar_t * dest;\r
102 \r
103     if (FAILED(StringCbLength(str, MAXCB_STR, &cb)))\r
104         return NULL;\r
105     cb += sizeof(wchar_t);\r
106 \r
107     dest = (wchar_t *) perf_malloc(file, line, cb);\r
108     StringCbCopy(dest, cb, str);\r
109 \r
110     return dest;\r
111 }\r
112 \r
113 KHMEXP char *\r
114 perf_strdup(char * file, int line, const char * str) {\r
115     size_t cb;\r
116     char * dest;\r
117 \r
118     if (FAILED(StringCbLengthA(str, MAXCB_STR, &cb)))\r
119         return NULL;\r
120     cb += sizeof(char);\r
121 \r
122     dest = (char *) perf_malloc(file, line, cb);\r
123     StringCbCopyA(dest, cb, str);\r
124 \r
125     return dest;\r
126 }\r
127 \r
128 KHMEXP void * \r
129 perf_malloc(char * file, int line, size_t s) {\r
130     allocation * a;\r
131     void * ptr;\r
132     size_t h;\r
133 \r
134     perf_once();\r
135 \r
136     assert(s > 0);\r
137 \r
138     EnterCriticalSection(&cs_alloc);\r
139     a = get_allocation();\r
140 \r
141     ptr = malloc(s);\r
142 \r
143     assert(ptr);                /* TODO: handle this gracefully */\r
144 \r
145     if (file[0] == '.' && file[1] == '\\')\r
146         file += 2;\r
147 \r
148     StringCbCopyA(a->file, sizeof(a->file), file);\r
149     a->line = line;\r
150     a->size = s;\r
151     a->ptr = ptr;\r
152 \r
153     h = HASHPTR(ptr);\r
154 \r
155     LPUSH(&ht[h], a);\r
156     LeaveCriticalSection(&cs_alloc);\r
157 \r
158     return ptr;\r
159 }\r
160 \r
161 KHMEXP void *\r
162 perf_realloc(char * file, int line, void * data, size_t s) {\r
163     void * n_data;\r
164     allocation * a;\r
165     size_t h;\r
166 \r
167     if (data == NULL)\r
168         return perf_malloc(file, line, s);\r
169 \r
170     perf_once();\r
171     h = HASHPTR(data);\r
172 \r
173     n_data = realloc(data, s);\r
174 \r
175     assert(n_data);\r
176 \r
177     EnterCriticalSection(&cs_alloc);\r
178     for (a = ht[h]; a; a = LNEXT(a)) {\r
179         if (a->ptr == data)\r
180             break;\r
181     }\r
182 \r
183     assert(a);\r
184 \r
185     LDELETE(&ht[h], a);\r
186 \r
187     a->size = s;\r
188     a->ptr = n_data;\r
189 \r
190     h = HASHPTR(n_data);\r
191     LPUSH(&ht[h], a);\r
192     LeaveCriticalSection(&cs_alloc);\r
193 \r
194     return n_data;\r
195 }\r
196 \r
197 KHMEXP void\r
198 perf_free  (void * b) {\r
199     size_t h;\r
200     allocation * a;\r
201 \r
202     perf_once();\r
203     h = HASHPTR(b);\r
204 \r
205     EnterCriticalSection(&cs_alloc);\r
206     for(a = ht[h]; a; a = LNEXT(a)) {\r
207         if (a->ptr == b)\r
208             break;\r
209     }\r
210 \r
211     assert(a);\r
212 \r
213     LDELETE(&ht[h], a);\r
214     LPUSH(&free_alloc, a);\r
215     LeaveCriticalSection(&cs_alloc);\r
216 }\r
217 \r
218 KHMEXP void\r
219 perf_dump(char * file) {\r
220     FILE * f;\r
221     size_t i;\r
222     allocation * a;\r
223     size_t total = 0;\r
224 \r
225     perf_once();\r
226 \r
227     EnterCriticalSection(&cs_alloc);\r
228     f = fopen(file, "w");\r
229     if (!f)\r
230         return;\r
231 \r
232     fprintf(f, "Leaked allocations list ....\n");\r
233     fprintf(f, "File\tLine\tSize\n");\r
234 \r
235     for (i=0; i < HASHSIZE; i++) {\r
236         for (a = ht[i]; a; a = LNEXT(a)) {\r
237             fprintf(f, "%s\t%6d\t%6d\n", a->file, a->line, a->size);\r
238             total += a->size;\r
239         }\r
240     }\r
241 \r
242     fprintf(f, "----------------------------------------\n");\r
243     fprintf(f, "Total\t\t%d\n", total);\r
244     fprintf(f, "----------------- End ------------------\n");\r
245 \r
246     fclose(f);\r
247 \r
248     LeaveCriticalSection(&cs_alloc);\r
249 }\r