]>
Commit | Line | Data |
---|---|---|
9385eb3d A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
9385eb3d A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
24 | #ifdef __APPLE_PR3375657_HACK__ | |
25 | ||
26 | /* | |
27 | * When mutexes or spinlocks were added for thread safety, the system would | |
28 | * hang during the boot process, just after changing to the blue background. | |
29 | * So for the common case of not calling _s[eh]m_hack_{add,init}(), we just | |
30 | * use static name lists. This should be reinvestigated when there is time. | |
31 | */ | |
32 | ||
33 | #define PRIVATE __private_extern__ | |
34 | //#define SEM_DEBUG_FILE "/tmp/sem_names" | |
35 | //#define SHM_DEBUG_FILE "/tmp/shm_names" | |
36 | ||
37 | #if defined(SEM_DEBUG_FILE) || defined(SHM_DEBUG_FILE) | |
38 | #include <stdio.h> | |
39 | #include <unistd.h> | |
40 | #endif /* defined(SEM_DEBUG_FILE) || defined(SHM_DEBUG_FILE) */ | |
41 | #include <stdlib.h> | |
42 | #include <string.h> | |
43 | #include <stdlib.h> | |
44 | ||
45 | #ifdef SEM_DEBUG_FILE | |
46 | #define SEM_PRINTF(fmt, args...) \ | |
47 | { \ | |
48 | FILE *_sem_fp_; \ | |
49 | if (access(SEM_DEBUG_FILE, F_OK) == 0 && \ | |
50 | (_sem_fp_ = fopen(SEM_DEBUG_FILE, "a")) != NULL) { \ | |
51 | fprintf(_sem_fp_, fmt, ## args); \ | |
52 | fclose(_sem_fp_); \ | |
53 | } \ | |
54 | } | |
55 | #endif /* SEM_DEBUG_FILE */ | |
56 | #ifdef SHM_DEBUG_FILE | |
57 | #define SHM_PRINTF(fmt, args...) \ | |
58 | { \ | |
59 | FILE *_shm_fp_; \ | |
60 | if (access(SHM_DEBUG_FILE, F_OK) == 0 && \ | |
61 | (_shm_fp_ = fopen(SHM_DEBUG_FILE, "a")) != NULL) { \ | |
62 | fprintf(_shm_fp_, fmt, ## args); \ | |
63 | fclose(_shm_fp_); \ | |
64 | } \ | |
65 | } | |
66 | #endif /* SHM_DEBUG_FILE */ | |
67 | ||
68 | /*----------------------------------------------------------------------- | |
69 | * For the Hack structure: | |
70 | * | |
71 | * first >= 0 starting serial number | |
72 | * first < 0 no serial number | |
73 | * last ending serial number (only if first >= 0) | |
74 | * debug whether an option 'D' can be appended | |
75 | *-----------------------------------------------------------------------*/ | |
76 | typedef struct { | |
77 | const char *name; | |
78 | int first; | |
79 | int last; | |
80 | int debug; | |
81 | } Hack; | |
82 | ||
83 | /*----------------------------------------------------------------------- | |
84 | * For the HackList structure: | |
85 | * | |
86 | * list the list of Hack structures | |
87 | * cur the number of valid Hack structures in list | |
88 | * max the actual number of Hack structures allocated | |
89 | *-----------------------------------------------------------------------*/ | |
90 | #define HACKLISTDELTA 16 | |
91 | #define HACKLISTSTART 16 | |
92 | typedef struct { | |
93 | const Hack *list; | |
94 | int cur; | |
95 | int max; | |
96 | } HackList; | |
97 | ||
98 | static const Hack sem_hack_default_names[] = { | |
99 | {"EDBPool", 1, 255, 0}, | |
100 | {"EDDPoolLock", -1, 0, 0}, | |
101 | {"Mso97SharedDg", 1920, 2047, 1}, | |
102 | {"Office", 1920, 2047, 1}, | |
103 | {"PT_EDBPool", 1, 255, 0}, | |
104 | {"PT_EDDPoolLock", -1, 0, 0}, | |
105 | {"PT_Mso97SharedDg", 1920, 2047, 0}, | |
106 | {"PT_Office", 1920, 2047, 0}, | |
107 | {"ShMemExtCritSection", -1, 0, 0}, | |
108 | {"ShMemIntCritSection", -1, 0, 0}, | |
109 | {NULL, 0, 0, 0}, | |
110 | }; | |
111 | static HackList sem_hack_defaults = { | |
112 | sem_hack_default_names, | |
113 | (sizeof(sem_hack_default_names) / sizeof(const Hack)) - 1, | |
114 | 0 | |
115 | }; | |
116 | static HackList *sem_hack_names = &sem_hack_defaults; | |
117 | ||
118 | static const Hack shm_hack_default_names[] = { | |
119 | {"EDBPool", 1, 255, 0}, | |
120 | {"EDDPoolLock", -1, 0, 0}, | |
121 | {"Mso97SharedDg", 1920, 2047, 1}, | |
122 | {"Office", 1920, 2047, 1}, | |
123 | {"PT_EDBPool", 1, 255, 0}, | |
124 | {"PT_EDDPoolLock", -1, 0, 0}, | |
125 | {"PT_Mso97SharedDg", 1920, 2047, 0}, | |
126 | {"PT_Office", 1920, 2047, 0}, | |
127 | {"PT_ShMemRefCount", -1, 0, 0}, /* not specified by MS, but seen */ | |
128 | {"ShMemRefCount", -1, 0, 0}, | |
129 | {NULL, 0, 0, 0}, | |
130 | }; | |
131 | static HackList shm_hack_defaults = { | |
132 | shm_hack_default_names, | |
133 | (sizeof(shm_hack_default_names) / sizeof(const Hack)) - 1, | |
134 | 0 | |
135 | }; | |
136 | static HackList *shm_hack_names = &shm_hack_defaults; | |
137 | ||
138 | static int comparkey(const void *key, const void *hname); | |
139 | static int comparstr(const void *a, const void *b); | |
140 | static int dosearch(const char *name, const HackList *hl); | |
141 | static int hl_add(HackList *hl, const Hack *h); | |
142 | static void hl_free(HackList *hl); | |
143 | static HackList *hl_init(void); | |
144 | static HackList *initList(const Hack *list); | |
145 | int _sem_hack_add(const Hack *list); | |
146 | void _sem_hack_init(void); | |
147 | PRIVATE int _sem_match(const char *name); | |
148 | int _shm_hack_add(const Hack *list); | |
149 | void _shm_hack_init(void); | |
150 | PRIVATE int _shm_match(const char *name); | |
151 | ||
152 | /*----------------------------------------------------------------------- | |
153 | * comparkey - used by bsearch to find the Hack structure with the given key | |
154 | *-----------------------------------------------------------------------*/ | |
155 | static int | |
156 | comparkey(const void *key, const void *h) | |
157 | { | |
158 | return strcmp(key, ((const Hack *)h)->name); | |
159 | } | |
160 | ||
161 | /*----------------------------------------------------------------------- | |
162 | * comparstr - used by qsort to sort the Hack list | |
163 | *-----------------------------------------------------------------------*/ | |
164 | static int | |
165 | comparstr(const void *a, const void *b) | |
166 | { | |
167 | return strcmp(((const Hack *)a)->name, ((const Hack *)b)->name); | |
168 | } | |
169 | ||
170 | /*----------------------------------------------------------------------- | |
171 | * dosearch - search of the given name in the given HackList. First see | |
172 | * if there is a trailing D, and a serial number. If the serial number | |
173 | * exists, try to match without the serial number, checking the series | |
174 | * range and whether the trailing D is allowed. Otherwise, try to match | |
175 | * the whole string, but check if the matched Hack structure requires a | |
176 | * serial number. | |
177 | *-----------------------------------------------------------------------*/ | |
178 | static int | |
179 | dosearch(const char *name, const HackList *hl) | |
180 | { | |
181 | int series; | |
182 | int len = strlen(name); | |
183 | const char *end, *p; | |
184 | char *key; | |
185 | const Hack *h; | |
186 | ||
187 | end = name + len - 1; | |
188 | if (*end != 'D') | |
189 | end++; | |
190 | p = end - 1; | |
191 | while (p >= name && *p >= '0' && *p <= '9') | |
192 | p--; | |
193 | p++; | |
194 | if (p < end && (len = p - name) > 0) { | |
195 | key = alloca(len + 1); | |
196 | if (key) { | |
197 | series = atoi(p); | |
198 | strncpy(key, name, len); | |
199 | key[len] = 0; | |
200 | h = (const Hack *)bsearch(key, hl->list, hl->cur, | |
201 | sizeof(const Hack), comparkey); | |
202 | if (h && h->first >= 0 | |
203 | && series >= h->first && series <= h->last | |
204 | && (*end == 0 || h->debug)) | |
205 | return 1; | |
206 | } | |
207 | } | |
208 | h = (const Hack *)bsearch(name, hl->list, hl->cur, sizeof(const Hack), | |
209 | comparkey); | |
210 | return (h && h->first < 0); | |
211 | } | |
212 | ||
213 | /*----------------------------------------------------------------------- | |
214 | * hl_add - append to the given HackList a copy of the given Hack structure | |
215 | *-----------------------------------------------------------------------*/ | |
216 | static int | |
217 | hl_add(HackList *hl, const Hack *c) | |
218 | { | |
219 | int i = hl->cur; | |
220 | Hack *h; | |
221 | ||
222 | if (!c->name) | |
223 | return -1; | |
224 | if (i >= hl->max) { | |
225 | int s = hl->max + HACKLISTDELTA; | |
226 | const Hack *new = (const Hack *)realloc((void *)hl->list, | |
227 | s * sizeof(const Hack)); | |
228 | ||
229 | if (!new) | |
230 | return -1; | |
231 | hl->list = new; | |
232 | hl->max = s; | |
233 | } | |
234 | h = (Hack *)(hl->list + i); | |
235 | if ((h->name = strdup(c->name)) == NULL) | |
236 | return -1; | |
237 | h->first = c->first; | |
238 | h->last = c->last; | |
239 | h->debug = c->debug; | |
240 | hl->cur++; | |
241 | return 0; | |
242 | } | |
243 | ||
244 | /*----------------------------------------------------------------------- | |
245 | * hl_free - deallocate all memory from the given HackList | |
246 | *-----------------------------------------------------------------------*/ | |
247 | static void | |
248 | hl_free(HackList *hl) | |
249 | { | |
250 | const Hack *h; | |
251 | int i; | |
252 | ||
253 | for (h = hl->list, i = hl->cur; i > 0; h++, i--) | |
254 | free((void *)h->name); | |
255 | free((void *)hl->list); | |
256 | free(hl); | |
257 | } | |
258 | ||
259 | /*----------------------------------------------------------------------- | |
260 | * hl_init - create a new HackList, with preallocated Hack structures | |
261 | *-----------------------------------------------------------------------*/ | |
262 | static HackList * | |
263 | hl_init(void) | |
264 | { | |
265 | HackList *hl = (HackList *)malloc(sizeof(HackList)); | |
266 | ||
267 | if (!hl) | |
268 | return NULL; | |
269 | hl->list = (Hack *)malloc(HACKLISTSTART * sizeof(Hack)); | |
270 | if (!hl->list) { | |
271 | free(hl); | |
272 | return NULL; | |
273 | } | |
274 | hl->cur = 0; | |
275 | hl->max = HACKLISTSTART; | |
276 | return hl; | |
277 | } | |
278 | ||
279 | /*----------------------------------------------------------------------- | |
280 | * initList - initialize a new HackList with the given list of Hack structures | |
281 | *-----------------------------------------------------------------------*/ | |
282 | static HackList * | |
283 | initList(const Hack *list) | |
284 | { | |
285 | HackList *hl = hl_init(); | |
286 | ||
287 | if (hl == NULL) | |
288 | return NULL; | |
289 | for (; list->name; list++) | |
290 | if (hl_add(hl, list) < 0) { | |
291 | hl_free(hl); | |
292 | return NULL; | |
293 | } | |
294 | return hl; | |
295 | } | |
296 | ||
297 | /*----------------------------------------------------------------------- | |
298 | * PUBLIC _sem_hack_add - add the given Hack list to sem_hack_names. | |
299 | *-----------------------------------------------------------------------*/ | |
300 | int | |
301 | _sem_hack_add(const Hack *list) | |
302 | { | |
303 | if (list == NULL) | |
304 | return -1; | |
305 | if (sem_hack_names == &sem_hack_defaults) { | |
306 | HackList *hl = initList(sem_hack_default_names); | |
307 | if (!hl) | |
308 | return -1; | |
309 | sem_hack_names = hl; | |
310 | } | |
311 | for (; list->name; list++) | |
312 | if (hl_add(sem_hack_names, list) < 0) | |
313 | return -1; | |
314 | qsort((void *)sem_hack_names->list, sem_hack_names->cur, | |
315 | sizeof(const Hack), comparstr); | |
316 | return 0; | |
317 | } | |
318 | ||
319 | /*----------------------------------------------------------------------- | |
320 | * PUBLIC _sem_hack_init - reinitialize sem_hack_names to the default | |
321 | *-----------------------------------------------------------------------*/ | |
322 | void | |
323 | _sem_hack_init(void) | |
324 | { | |
325 | if (sem_hack_names == &sem_hack_defaults) | |
326 | return; | |
327 | hl_free(sem_hack_names); | |
328 | sem_hack_names = &sem_hack_defaults; | |
329 | } | |
330 | ||
331 | /*----------------------------------------------------------------------- | |
332 | * _sem_match - try to match the given named to sem_hack_names. Called | |
333 | * by sem_open() and sem_unlink(). | |
334 | *-----------------------------------------------------------------------*/ | |
335 | PRIVATE int | |
336 | _sem_match(const char *name) | |
337 | { | |
338 | #ifdef SEM_DEBUG_FILE | |
339 | int match; | |
340 | #endif /* SEM_DEBUG_FILE */ | |
341 | ||
342 | if (!name || !*name) | |
343 | return 0; | |
344 | #ifdef SEM_DEBUG_FILE | |
345 | match = dosearch(name, sem_hack_names); | |
346 | if (!match) | |
347 | SEM_PRINTF("%s\n", name); | |
348 | return match; | |
349 | #else /* SEM_DEBUG_FILE */ | |
350 | return dosearch(name, sem_hack_names); | |
351 | #endif /* SEM_DEBUG_FILE */ | |
352 | } | |
353 | ||
354 | /*----------------------------------------------------------------------- | |
355 | * PUBLIC _shm_hack_add - add the given Hack list to shm_hack_names. | |
356 | *-----------------------------------------------------------------------*/ | |
357 | int | |
358 | _shm_hack_add(const Hack *list) | |
359 | { | |
360 | if (list == NULL) | |
361 | return -1; | |
362 | if (shm_hack_names == &shm_hack_defaults) { | |
363 | HackList *hl = initList(shm_hack_default_names); | |
364 | if (!hl) | |
365 | return -1; | |
366 | shm_hack_names = hl; | |
367 | } | |
368 | for (; list->name; list++) | |
369 | if (hl_add(shm_hack_names, list) < 0) | |
370 | return -1; | |
371 | qsort((void *)shm_hack_names->list, shm_hack_names->cur, | |
372 | sizeof(const Hack), comparstr); | |
373 | return 0; | |
374 | } | |
375 | ||
376 | /*----------------------------------------------------------------------- | |
377 | * PUBLIC _shm_hack_init - reinitialize shm_hack_names to the default | |
378 | *-----------------------------------------------------------------------*/ | |
379 | void | |
380 | _shm_hack_init(void) | |
381 | { | |
382 | if (shm_hack_names == &shm_hack_defaults) | |
383 | return; | |
384 | hl_free(shm_hack_names); | |
385 | shm_hack_names = &shm_hack_defaults; | |
386 | } | |
387 | ||
388 | /*----------------------------------------------------------------------- | |
389 | * _shm_match - try to match the given named to shm_hack_names. Called | |
390 | * by shm_open() and shm_unlink(). | |
391 | *-----------------------------------------------------------------------*/ | |
392 | PRIVATE int | |
393 | _shm_match(const char *name) | |
394 | { | |
395 | #ifdef SHM_DEBUG_FILE | |
396 | int match; | |
397 | #endif /* SHM_DEBUG_FILE */ | |
398 | ||
399 | if (!name || !*name) | |
400 | return 0; | |
401 | #ifdef SHM_DEBUG_FILE | |
402 | match = dosearch(name, shm_hack_names); | |
403 | if (!match) | |
404 | SHM_PRINTF("%s\n", name); | |
405 | return match; | |
406 | #else /* SHM_DEBUG_FILE */ | |
407 | return dosearch(name, shm_hack_names); | |
408 | #endif /* SHM_DEBUG_FILE */ | |
409 | } | |
410 | ||
411 | #endif /* __APPLE_PR3375657_HACK__ */ |