1 /*
2
3 Copyright 1993, 1998 The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
26
27 */
28 /*
29 * Copyright © 2010, Keith Packard
30 * Copyright © 2010, Jamey Sharp
31 *
32 * Permission to use, copy, modify, distribute, and sell this software and its
33 * documentation for any purpose is hereby granted without fee, provided that
34 * the above copyright notice appear in all copies and that both that copyright
35 * notice and this permission notice appear in supporting documentation, and
36 * that the name of the copyright holders not be used in advertising or
37 * publicity pertaining to distribution of the software without specific,
38 * written prior permission. The copyright holders make no representations
39 * about the suitability of this software for any purpose. It is provided "as
40 * is" without express or implied warranty.
41 *
42 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
44 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
45 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
46 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
47 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
48 * OF THIS SOFTWARE.
49 */
50
51 #ifdef HAVE_DIX_CONFIG_H
52 #include <dix-config.h>
53 #endif
54
55 #include <stddef.h>
56 #include "windowstr.h"
57 #include "resource.h"
58 #include "privates.h"
59 #include "gcstruct.h"
60 #include "cursorstr.h"
61 #include "colormapst.h"
62 #include "inputstr.h"
63 #include "scrnintstr.h"
64 #include "extnsionst.h"
65 #include "inputstr.h"
66
67 static DevPrivateSetRec global_keys[PRIVATE_LAST];
68
69 static const Bool xselinux_private[PRIVATE_LAST] = {
70 [PRIVATE_SCREEN] = TRUE,
71 [PRIVATE_CLIENT] = TRUE,
72 [PRIVATE_WINDOW] = TRUE,
73 [PRIVATE_PIXMAP] = TRUE,
74 [PRIVATE_GC] = TRUE,
75 [PRIVATE_CURSOR] = TRUE,
76 [PRIVATE_COLORMAP] = TRUE,
77 [PRIVATE_DEVICE] = TRUE,
78 [PRIVATE_EXTENSION] = TRUE,
79 [PRIVATE_SELECTION] = TRUE,
80 [PRIVATE_PROPERTY] = TRUE,
81 [PRIVATE_PICTURE] = TRUE,
82 [PRIVATE_GLYPHSET] = TRUE,
83 };
84
85 static const char *key_names[PRIVATE_LAST] = {
86 /* XSELinux uses the same private keys for numerous objects */
87 [PRIVATE_XSELINUX] = "XSELINUX",
88
89 /* Otherwise, you get a private in just the requested structure
90 */
91 /* These can have objects created before all of the keys are registered */
92 [PRIVATE_SCREEN] = "SCREEN",
93 [PRIVATE_EXTENSION] = "EXTENSION",
94 [PRIVATE_COLORMAP] = "COLORMAP",
95 [PRIVATE_DEVICE] = "DEVICE",
96
97 /* These cannot have any objects before all relevant keys are registered */
98 [PRIVATE_CLIENT] = "CLIENT",
99 [PRIVATE_PROPERTY] = "PROPERTY",
100 [PRIVATE_SELECTION] = "SELECTION",
101 [PRIVATE_WINDOW] = "WINDOW",
102 [PRIVATE_PIXMAP] = "PIXMAP",
103 [PRIVATE_GC] = "GC",
104 [PRIVATE_CURSOR] = "CURSOR",
105 [PRIVATE_CURSOR_BITS] = "CURSOR_BITS",
106
107 /* extension privates */
108 [PRIVATE_GLYPH] = "GLYPH",
109 [PRIVATE_GLYPHSET] = "GLYPHSET",
110 [PRIVATE_PICTURE] = "PICTURE",
111 [PRIVATE_SYNC_FENCE] = "SYNC_FENCE",
112 };
113
114 static const Bool screen_specific_private[PRIVATE_LAST] = {
115 [PRIVATE_SCREEN] = FALSE,
116 [PRIVATE_CLIENT] = FALSE,
117 [PRIVATE_WINDOW] = TRUE,
118 [PRIVATE_PIXMAP] = TRUE,
119 [PRIVATE_GC] = TRUE,
120 [PRIVATE_CURSOR] = FALSE,
121 [PRIVATE_COLORMAP] = FALSE,
122 [PRIVATE_DEVICE] = FALSE,
123 [PRIVATE_EXTENSION] = FALSE,
124 [PRIVATE_SELECTION] = FALSE,
125 [PRIVATE_PROPERTY] = FALSE,
126 [PRIVATE_PICTURE] = TRUE,
127 [PRIVATE_GLYPHSET] = FALSE,
128 };
129
130 typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes);
131
132 typedef enum { FixupMove, FixupRealloc } FixupType;
133
134 static Bool
dixReallocPrivates(PrivatePtr * privates,int old_offset,unsigned bytes)135 dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
136 {
137 void *new_privates;
138
139 new_privates = realloc(*privates, old_offset + bytes);
140 if (!new_privates)
141 return FALSE;
142 memset((char *) new_privates + old_offset, '\0', bytes);
143 *privates = new_privates;
144 return TRUE;
145 }
146
147 static Bool
dixMovePrivates(PrivatePtr * privates,int new_offset,unsigned bytes)148 dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
149 {
150 memmove((char *) *privates + bytes, *privates, new_offset - bytes);
151 memset(*privates, '\0', bytes);
152 return TRUE;
153 }
154
155 static Bool
fixupOneScreen(ScreenPtr pScreen,FixupFunc fixup,unsigned bytes)156 fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
157 {
158 intptr_t dist;
159 char *old;
160 char *new;
161 DevPrivateKey *keyp, key;
162 DevPrivateType type;
163 int size;
164
165 old = (char *) pScreen->devPrivates;
166 size = global_keys[PRIVATE_SCREEN].offset;
167 if (!fixup (&pScreen->devPrivates, size, bytes))
168 return FALSE;
169
170 /* Screen privates can contain screen-specific private keys
171 * for other types. When they move, the linked list we use to
172 * track them gets scrambled. Fix that by computing the change
173 * in the location of each private adjusting our linked list
174 * pointers to match
175 */
176
177 new = (char *) pScreen->devPrivates;
178
179 /* Moving means everyone shifts up in the privates by 'bytes' amount,
180 * realloc means the base pointer moves
181 */
182 if (fixup == dixMovePrivates)
183 new += bytes;
184
185 dist = new - old;
186
187 if (dist) {
188 for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
189
190 /* Walk the privates list, being careful as the
191 * pointers are scrambled before we patch them.
192 */
193 for (keyp = &pScreen->screenSpecificPrivates[type].key;
194 (key = *keyp) != NULL;
195 keyp = &key->next)
196 {
197
198 /* Only mangle things if the private structure
199 * is contained within the allocation. Privates
200 * stored elsewhere will be left alone
201 */
202 if (old <= (char *) key && (char *) key < old + size)
203 {
204 /* Compute new location of key */
205 key = (DevPrivateKey) ((char *) key + dist);
206
207 /* Patch the list */
208 *keyp = key;
209 }
210 }
211 }
212 return TRUE;
213 }
214
215 static Bool
fixupScreens(FixupFunc fixup,unsigned bytes)216 fixupScreens(FixupFunc fixup, unsigned bytes)
217 {
218 int s;
219
220 for (s = 0; s < screenInfo.numScreens; s++)
221 if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes))
222 return FALSE;
223
224 for (s = 0; s < screenInfo.numGPUScreens; s++)
225 if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes))
226 return FALSE;
227 return TRUE;
228 }
229
230 static Bool
fixupServerClient(FixupFunc fixup,unsigned bytes)231 fixupServerClient(FixupFunc fixup, unsigned bytes)
232 {
233 if (serverClient)
234 return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset,
235 bytes);
236 return TRUE;
237 }
238
239 static Bool
fixupExtensions(FixupFunc fixup,unsigned bytes)240 fixupExtensions(FixupFunc fixup, unsigned bytes)
241 {
242 unsigned char major;
243 ExtensionEntry *extension;
244
245 for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major));
246 major++)
247 if (!fixup
248 (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes))
249 return FALSE;
250 return TRUE;
251 }
252
253 static Bool
fixupDefaultColormaps(FixupFunc fixup,unsigned bytes)254 fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
255 {
256 int s;
257
258 for (s = 0; s < screenInfo.numScreens; s++) {
259 ColormapPtr cmap;
260
261 dixLookupResourceByType((void **) &cmap,
262 screenInfo.screens[s]->defColormap, RT_COLORMAP,
263 serverClient, DixCreateAccess);
264 if (cmap &&
265 !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes))
266 return FALSE;
267 }
268 return TRUE;
269 }
270
271 static Bool
fixupDeviceList(DeviceIntPtr device,FixupFunc fixup,unsigned bytes)272 fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes)
273 {
274 while (device) {
275 if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes))
276 return FALSE;
277 device = device->next;
278 }
279 return TRUE;
280 }
281
282 static Bool
fixupDevices(FixupFunc fixup,unsigned bytes)283 fixupDevices(FixupFunc fixup, unsigned bytes)
284 {
285 return (fixupDeviceList(inputInfo.devices, fixup, bytes) &&
286 fixupDeviceList(inputInfo.off_devices, fixup, bytes));
287 }
288
289 static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = {
290 [PRIVATE_SCREEN] = fixupScreens,
291 [PRIVATE_CLIENT] = fixupServerClient,
292 [PRIVATE_EXTENSION] = fixupExtensions,
293 [PRIVATE_COLORMAP] = fixupDefaultColormaps,
294 [PRIVATE_DEVICE] = fixupDevices,
295 };
296
297 static void
grow_private_set(DevPrivateSetPtr set,unsigned bytes)298 grow_private_set(DevPrivateSetPtr set, unsigned bytes)
299 {
300 DevPrivateKey k;
301
302 for (k = set->key; k; k = k->next)
303 k->offset += bytes;
304 set->offset += bytes;
305 }
306
307 static void
grow_screen_specific_set(DevPrivateType type,unsigned bytes)308 grow_screen_specific_set(DevPrivateType type, unsigned bytes)
309 {
310 int s;
311
312 /* Update offsets for all screen-specific keys */
313 for (s = 0; s < screenInfo.numScreens; s++) {
314 ScreenPtr pScreen = screenInfo.screens[s];
315
316 grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
317 }
318 for (s = 0; s < screenInfo.numGPUScreens; s++) {
319 ScreenPtr pScreen = screenInfo.gpuscreens[s];
320
321 grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
322 }
323 }
324
325 /*
326 * Register a private key. This takes the type of object the key will
327 * be used with, which may be PRIVATE_ALL indicating that this key
328 * will be used with all of the private objects. If 'size' is
329 * non-zero, then the specified amount of space will be allocated in
330 * the private storage. Otherwise, space for a single pointer will
331 * be allocated which can be set with dixSetPrivate
332 */
333 Bool
dixRegisterPrivateKey(DevPrivateKey key,DevPrivateType type,unsigned size)334 dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
335 {
336 DevPrivateType t;
337 int offset;
338 unsigned bytes;
339
340 if (key->initialized) {
341 assert(size == key->size);
342 return TRUE;
343 }
344
345 /* Compute required space */
346 bytes = size;
347 if (size == 0)
348 bytes = sizeof(void *);
349
350 /* align to pointer size */
351 bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
352
353 /* Update offsets for all affected keys */
354 if (type == PRIVATE_XSELINUX) {
355
356 /* Resize if we can, or make sure nothing's allocated if we can't
357 */
358 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
359 if (xselinux_private[t]) {
360 if (!allocated_early[t])
361 assert(!global_keys[t].created);
362 else if (!allocated_early[t] (dixReallocPrivates, bytes))
363 return FALSE;
364 }
365
366 /* Move all existing keys up in the privates space to make
367 * room for this new global key
368 */
369 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
370 if (xselinux_private[t]) {
371 grow_private_set(&global_keys[t], bytes);
372 grow_screen_specific_set(t, bytes);
373 if (allocated_early[t])
374 allocated_early[t] (dixMovePrivates, bytes);
375 }
376
377 }
378
379 offset = 0;
380 }
381 else {
382 /* Resize if we can, or make sure nothing's allocated if we can't */
383 if (!allocated_early[type])
384 assert(!global_keys[type].created);
385 else if (!allocated_early[type] (dixReallocPrivates, bytes))
386 return FALSE;
387 offset = global_keys[type].offset;
388 global_keys[type].offset += bytes;
389 grow_screen_specific_set(type, bytes);
390 }
391
392 /* Setup this key */
393 key->offset = offset;
394 key->size = size;
395 key->initialized = TRUE;
396 key->type = type;
397 key->allocated = FALSE;
398 key->next = global_keys[type].key;
399 global_keys[type].key = key;
400
401 return TRUE;
402 }
403
404 Bool
dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey,ScreenPtr pScreen,DevPrivateType type,unsigned size)405 dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen,
406 DevPrivateType type, unsigned size)
407 {
408 DevPrivateKey key;
409
410 if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0))
411 return FALSE;
412 key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey);
413 if (key != NULL) {
414 assert(key->size == size);
415 assert(key->type == type);
416 return TRUE;
417 }
418 key = calloc(sizeof(DevPrivateKeyRec), 1);
419 if (!key)
420 return FALSE;
421 if (!dixRegisterPrivateKey(key, type, size)) {
422 free(key);
423 return FALSE;
424 }
425 key->allocated = TRUE;
426 dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key);
427 return TRUE;
428 }
429
430 DevPrivateKey
_dixGetScreenPrivateKey(const DevScreenPrivateKey key,ScreenPtr pScreen)431 _dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen)
432 {
433 return dixGetPrivate(&pScreen->devPrivates, &key->screenKey);
434 }
435
436 /*
437 * Initialize privates by zeroing them
438 */
439 void
_dixInitPrivates(PrivatePtr * privates,void * addr,DevPrivateType type)440 _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
441 {
442 assert (!screen_specific_private[type]);
443
444 global_keys[type].created++;
445 if (xselinux_private[type])
446 global_keys[PRIVATE_XSELINUX].created++;
447 if (global_keys[type].offset == 0)
448 addr = 0;
449 *privates = addr;
450 memset(addr, '\0', global_keys[type].offset);
451 }
452
453 /*
454 * Clean up privates
455 */
456 void
_dixFiniPrivates(PrivatePtr privates,DevPrivateType type)457 _dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
458 {
459 global_keys[type].created--;
460 if (xselinux_private[type])
461 global_keys[PRIVATE_XSELINUX].created--;
462 }
463
464 /*
465 * Allocate new object with privates.
466 *
467 * This is expected to be invoked from the
468 * dixAllocateObjectWithPrivates macro
469 */
470 void *
_dixAllocateObjectWithPrivates(unsigned baseSize,unsigned clear,unsigned offset,DevPrivateType type)471 _dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear,
472 unsigned offset, DevPrivateType type)
473 {
474 unsigned totalSize;
475 void *object;
476 PrivatePtr privates;
477 PrivatePtr *devPrivates;
478
479 assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
480 assert(!screen_specific_private[type]);
481
482 /* round up so that void * is aligned */
483 baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
484 totalSize = baseSize + global_keys[type].offset;
485 object = malloc(totalSize);
486 if (!object)
487 return NULL;
488
489 memset(object, '\0', clear);
490 privates = (PrivatePtr) (((char *) object) + baseSize);
491 devPrivates = (PrivatePtr *) ((char *) object + offset);
492
493 _dixInitPrivates(devPrivates, privates, type);
494
495 return object;
496 }
497
498 /*
499 * Allocate privates separately from containing object.
500 * Used for clients and screens.
501 */
502 Bool
dixAllocatePrivates(PrivatePtr * privates,DevPrivateType type)503 dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
504 {
505 unsigned size;
506 PrivatePtr p;
507
508 assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
509 assert(!screen_specific_private[type]);
510
511 size = global_keys[type].offset;
512 if (!size) {
513 p = NULL;
514 }
515 else {
516 if (!(p = malloc(size)))
517 return FALSE;
518 }
519
520 _dixInitPrivates(privates, p, type);
521 ++global_keys[type].allocated;
522
523 return TRUE;
524 }
525
526 /*
527 * Free an object that has privates
528 *
529 * This is expected to be invoked from the
530 * dixFreeObjectWithPrivates macro
531 */
532 void
_dixFreeObjectWithPrivates(void * object,PrivatePtr privates,DevPrivateType type)533 _dixFreeObjectWithPrivates(void *object, PrivatePtr privates,
534 DevPrivateType type)
535 {
536 _dixFiniPrivates(privates, type);
537 free(object);
538 }
539
540 /*
541 * Called to free screen or client privates
542 */
543 void
dixFreePrivates(PrivatePtr privates,DevPrivateType type)544 dixFreePrivates(PrivatePtr privates, DevPrivateType type)
545 {
546 _dixFiniPrivates(privates, type);
547 --global_keys[type].allocated;
548 free(privates);
549 }
550
551 /*
552 * Return size of privates for the specified type
553 */
554 extern _X_EXPORT int
dixPrivatesSize(DevPrivateType type)555 dixPrivatesSize(DevPrivateType type)
556 {
557 assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
558 assert (!screen_specific_private[type]);
559
560 return global_keys[type].offset;
561 }
562
563 /* Table of devPrivates offsets */
564 static const int offsets[] = {
565 -1, /* RT_NONE */
566 offsetof(WindowRec, devPrivates), /* RT_WINDOW */
567 offsetof(PixmapRec, devPrivates), /* RT_PIXMAP */
568 offsetof(GC, devPrivates), /* RT_GC */
569 -1, /* RT_FONT */
570 offsetof(CursorRec, devPrivates), /* RT_CURSOR */
571 offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
572 };
573
574 int
dixLookupPrivateOffset(RESTYPE type)575 dixLookupPrivateOffset(RESTYPE type)
576 {
577 /*
578 * Special kludge for DBE which registers a new resource type that
579 * points at pixmaps (thanks, DBE)
580 */
581 if (type & RC_DRAWABLE) {
582 if (type == RT_WINDOW)
583 return offsets[RT_WINDOW & TypeMask];
584 else
585 return offsets[RT_PIXMAP & TypeMask];
586 }
587 type = type & TypeMask;
588 if (type < ARRAY_SIZE(offsets))
589 return offsets[type];
590 return -1;
591 }
592
593 /*
594 * Screen-specific privates
595 */
596
597 extern _X_EXPORT Bool
dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen,DevPrivateKey key,DevPrivateType type,unsigned size)598 dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key,
599 DevPrivateType type, unsigned size)
600 {
601 int offset;
602 unsigned bytes;
603
604 if (!screen_specific_private[type])
605 FatalError("Attempt to allocate screen-specific private storage for type %s\n",
606 key_names[type]);
607
608 if (key->initialized) {
609 assert(size == key->size);
610 return TRUE;
611 }
612
613 /* Compute required space */
614 bytes = size;
615 if (size == 0)
616 bytes = sizeof(void *);
617
618 /* align to void * size */
619 bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
620
621 assert (!allocated_early[type]);
622 assert (!pScreen->screenSpecificPrivates[type].created);
623 offset = pScreen->screenSpecificPrivates[type].offset;
624 pScreen->screenSpecificPrivates[type].offset += bytes;
625
626 /* Setup this key */
627 key->offset = offset;
628 key->size = size;
629 key->initialized = TRUE;
630 key->type = type;
631 key->allocated = FALSE;
632 key->next = pScreen->screenSpecificPrivates[type].key;
633 pScreen->screenSpecificPrivates[type].key = key;
634
635 return TRUE;
636 }
637
638 /* Clean up screen-specific privates before CloseScreen */
639 void
dixFreeScreenSpecificPrivates(ScreenPtr pScreen)640 dixFreeScreenSpecificPrivates(ScreenPtr pScreen)
641 {
642 DevPrivateType t;
643
644 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
645 DevPrivateKey key;
646
647 for (key = pScreen->screenSpecificPrivates[t].key; key; key = key->next) {
648 key->initialized = FALSE;
649 }
650 }
651 }
652
653 /* Initialize screen-specific privates in AddScreen */
654 void
dixInitScreenSpecificPrivates(ScreenPtr pScreen)655 dixInitScreenSpecificPrivates(ScreenPtr pScreen)
656 {
657 DevPrivateType t;
658
659 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
660 pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset;
661 }
662
663 /* Initialize screen-specific privates in AddScreen */
664 void
_dixInitScreenPrivates(ScreenPtr pScreen,PrivatePtr * privates,void * addr,DevPrivateType type)665 _dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type)
666 {
667 int privates_size;
668 assert (screen_specific_private[type]);
669
670 if (pScreen) {
671 privates_size = pScreen->screenSpecificPrivates[type].offset;
672 pScreen->screenSpecificPrivates[type].created++;
673 }
674 else
675 privates_size = global_keys[type].offset;
676
677 global_keys[type].created++;
678 if (xselinux_private[type])
679 global_keys[PRIVATE_XSELINUX].created++;
680 if (privates_size == 0)
681 addr = 0;
682 *privates = addr;
683 memset(addr, '\0', privates_size);
684 }
685
686 void *
_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen,unsigned baseSize,unsigned clear,unsigned offset,DevPrivateType type)687 _dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen,
688 unsigned baseSize,
689 unsigned clear,
690 unsigned offset,
691 DevPrivateType type)
692 {
693 unsigned totalSize;
694 void *object;
695 PrivatePtr privates;
696 PrivatePtr *devPrivates;
697 int privates_size;
698
699 assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
700 assert (screen_specific_private[type]);
701
702 if (pScreen)
703 privates_size = pScreen->screenSpecificPrivates[type].offset;
704 else
705 privates_size = global_keys[type].offset;
706 /* round up so that pointer is aligned */
707 baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
708 totalSize = baseSize + privates_size;
709 object = malloc(totalSize);
710 if (!object)
711 return NULL;
712
713 memset(object, '\0', clear);
714 privates = (PrivatePtr) (((char *) object) + baseSize);
715 devPrivates = (PrivatePtr *) ((char *) object + offset);
716
717 _dixInitScreenPrivates(pScreen, devPrivates, privates, type);
718
719 return object;
720 }
721
722 int
dixScreenSpecificPrivatesSize(ScreenPtr pScreen,DevPrivateType type)723 dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type)
724 {
725 assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
726
727 if (screen_specific_private[type])
728 return pScreen->screenSpecificPrivates[type].offset;
729 else
730 return global_keys[type].offset;
731 }
732
733 void
dixPrivateUsage(void)734 dixPrivateUsage(void)
735 {
736 int objects = 0;
737 int bytes = 0;
738 int alloc = 0;
739 DevPrivateType t;
740
741 for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
742 if (global_keys[t].offset) {
743 ErrorF
744 ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
745 key_names[t], global_keys[t].created, global_keys[t].offset,
746 global_keys[t].created * global_keys[t].offset, global_keys[t].allocated);
747 bytes += global_keys[t].created * global_keys[t].offset;
748 objects += global_keys[t].created;
749 alloc += global_keys[t].allocated;
750 }
751 }
752 ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc);
753 }
754
755 void
dixResetPrivates(void)756 dixResetPrivates(void)
757 {
758 DevPrivateType t;
759
760 for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
761 DevPrivateKey key, next;
762
763 for (key = global_keys[t].key; key; key = next) {
764 next = key->next;
765 key->offset = 0;
766 key->initialized = FALSE;
767 key->size = 0;
768 key->type = 0;
769 if (key->allocated)
770 free(key);
771 }
772 if (global_keys[t].created) {
773 ErrorF("%d %ss still allocated at reset\n",
774 global_keys[t].created, key_names[t]);
775 dixPrivateUsage();
776 }
777 global_keys[t].key = NULL;
778 global_keys[t].offset = 0;
779 global_keys[t].created = 0;
780 global_keys[t].allocated = 0;
781 }
782 }
783
784 Bool
dixPrivatesCreated(DevPrivateType type)785 dixPrivatesCreated(DevPrivateType type)
786 {
787 if (global_keys[type].created)
788 return TRUE;
789 else
790 return FALSE;
791 }
792