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