diff options
Diffstat (limited to 'xorg-server/dix/privates.c')
-rw-r--r-- | xorg-server/dix/privates.c | 414 |
1 files changed, 335 insertions, 79 deletions
diff --git a/xorg-server/dix/privates.c b/xorg-server/dix/privates.c index 21faf5b94..04fa24ad3 100644 --- a/xorg-server/dix/privates.c +++ b/xorg-server/dix/privates.c @@ -62,13 +62,9 @@ from The Open Group. #include "inputstr.h" #include "scrnintstr.h" #include "extnsionst.h" +#include "inputstr.h" -static struct { - DevPrivateKey key; - unsigned offset; - int created; - int allocated; -} keys[PRIVATE_LAST]; +static DevPrivateSetRec global_keys[PRIVATE_LAST]; static const Bool xselinux_private[PRIVATE_LAST] = { /* PRIVATE_XSELINUX,*/ FALSE, @@ -91,8 +87,63 @@ static const Bool xselinux_private[PRIVATE_LAST] = { /* [PRIVATE_PICTURE] =*/ TRUE }; +static const char *key_names[PRIVATE_LAST] = { + /* XSELinux uses the same private keys for numerous objects */ + /*[PRIVATE_XSELINUX] =*/ "XSELINUX", + + /* Otherwise, you get a private in just the requested structure + */ + /* These can have objects created before all of the keys are registered */ + /*[PRIVATE_SCREEN] =*/ "SCREEN", + /*[PRIVATE_EXTENSION] =*/ "EXTENSION", + /*[PRIVATE_COLORMAP] =*/ "COLORMAP", + /*[PRIVATE_DEVICE] =*/ "DEVICE", + + /* These cannot have any objects before all relevant keys are registered */ + /*[PRIVATE_CLIENT] =*/ "CLIENT", + /*[PRIVATE_PROPERTY] =*/ "PROPERTY", + /*[PRIVATE_SELECTION] =*/ "SELECTION", + /*[PRIVATE_WINDOW] =*/ "WINDOW", + /*[PRIVATE_PIXMAP] =*/ "PIXMAP", + /*[PRIVATE_GC] =*/ "GC", + /*[PRIVATE_CURSOR] =*/ "CURSOR", + /*[PRIVATE_CURSOR_BITS] =*/ "CURSOR_BITS", + + /* extension privates */ + /*[PRIVATE_DBE_WINDOW] =*/ "DBE_WINDOW", + /*[PRIVATE_DAMAGE] =*/ "DAMAGE", + /*[PRIVATE_GLYPH] =*/ "GLYPH", + /*[PRIVATE_GLYPHSET] =*/ "GLYPHSET", + /*[PRIVATE_PICTURE] =*/ "PICTURE", + /*[PRIVATE_SYNC_FENCE] =*/ "SYNC_FENCE", +}; + +static const Bool screen_specific_private[PRIVATE_LAST] = { + /*[PRIVATE_XSELINUX] =*/ FALSE, + /*[PRIVATE_SCREEN] =*/ FALSE, + /*[PRIVATE_EXTENSION] =*/ FALSE, + /*[PRIVATE_COLORMAP] =*/ FALSE, + /*[PRIVATE_DEVICE] =*/ FALSE, + /*[PRIVATE_CLIENT] =*/ FALSE, + /*[PRIVATE_PROPERTY] =*/ FALSE, + /*[PRIVATE_SELECTION] =*/ FALSE, + /*[PRIVATE_WINDOW] =*/ TRUE, + /*[PRIVATE_PIXMAP] =*/ TRUE, + /*[PRIVATE_GC] =*/ TRUE, + /*[PRIVATE_CURSOR] =*/ FALSE, + /*[PRIVATE_CURSOR_BITS] =*/ FALSE, + /*[PRIVATE_DBE_WINDOW] =*/ FALSE, + /*[PRIVATE_DAMAGE] =*/ FALSE, + /*[PRIVATE_GLYPH] =*/ FALSE, + /*[PRIVATE_GLYPHSET] =*/ FALSE, + /*[PRIVATE_PICTURE] =*/ TRUE, + /*[PRIVATE_SYNC_FENCE] =*/ FALSE +}; + typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes); +typedef enum { FixupMove, FixupRealloc } FixupType; + static Bool dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes) { @@ -115,14 +166,72 @@ dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes) } static Bool +fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes) +{ + intptr_t dist; + char *old; + char *new; + DevPrivateKey *keyp, key; + DevPrivateType type; + int size; + + old = (char *) pScreen->devPrivates; + size = global_keys[PRIVATE_SCREEN].offset; + if (!fixup (&pScreen->devPrivates, size, bytes)) + return FALSE; + + /* Screen privates can contain screen-specific private keys + * for other types. When they move, the linked list we use to + * track them gets scrambled. Fix that by computing the change + * in the location of each private adjusting our linked list + * pointers to match + */ + + new = (char *) pScreen->devPrivates; + + /* Moving means everyone shifts up in the privates by 'bytes' amount, + * realloc means the base pointer moves + */ + if (fixup == dixMovePrivates) + new += bytes; + + dist = new - old; + + if (dist) { + for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++) + + /* Walk the privates list, being careful as the + * pointers are scrambled before we patch them. + */ + for (keyp = &pScreen->screenSpecificPrivates[type].key; + (key = *keyp) != NULL; + keyp = &key->next) + { + + /* Only mangle things if the private structure + * is contained within the allocation. Privates + * stored elsewhere will be left alone + */ + if (old <= (char *) key && (char *) key < old + size) + { + /* Compute new location of key */ + key = (DevPrivateKey) ((char *) key + dist); + + /* Patch the list */ + *keyp = key; + } + } + } + return TRUE; +} + +static Bool fixupScreens(FixupFunc fixup, unsigned bytes) { int s; for (s = 0; s < screenInfo.numScreens; s++) - if (!fixup - (&screenInfo.screens[s]->devPrivates, keys[PRIVATE_SCREEN].offset, - bytes)) + if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes)) return FALSE; return TRUE; } @@ -131,7 +240,7 @@ static Bool fixupServerClient(FixupFunc fixup, unsigned bytes) { if (serverClient) - return fixup(&serverClient->devPrivates, keys[PRIVATE_CLIENT].offset, + return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset, bytes); return TRUE; } @@ -145,7 +254,7 @@ fixupExtensions(FixupFunc fixup, unsigned bytes) for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); major++) if (!fixup - (&extension->devPrivates, keys[PRIVATE_EXTENSION].offset, bytes)) + (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes)) return FALSE; return TRUE; } @@ -162,19 +271,37 @@ fixupDefaultColormaps(FixupFunc fixup, unsigned bytes) screenInfo.screens[s]->defColormap, RT_COLORMAP, serverClient, DixCreateAccess); if (cmap && - !fixup(&cmap->devPrivates, keys[PRIVATE_COLORMAP].offset, bytes)) + !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes)) return FALSE; } return TRUE; } +static Bool +fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes) +{ + while (device) { + if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes)) + return FALSE; + device = device->next; + } + return TRUE; +} + +static Bool +fixupDevices(FixupFunc fixup, unsigned bytes) +{ + return (fixupDeviceList(inputInfo.devices, fixup, bytes) && + fixupDeviceList(inputInfo.off_devices, fixup, bytes)); +} + static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = { /*PRIVATE_XSELINUX,*/ NULL, - /*[PRIVATE_SCREEN] =*/ fixupScreens, - /*[PRIVATE_EXTENSION] =*/ fixupExtensions, - /*[PRIVATE_COLORMAP] =*/ fixupDefaultColormaps, - /*PRIVATE_DEVICE,*/ NULL, - /*[PRIVATE_CLIENT] =*/ fixupServerClient, + /*PRIVATE_SCREEN =*/ fixupScreens, + /*PRIVATE_EXTENSION =*/ fixupExtensions, + /*PRIVATE_COLORMAP =*/ fixupDefaultColormaps, + /*PRIVATE_DEVICE,*/ fixupDevices, + /*PRIVATE_CLIENT =*/ fixupServerClient, /*PRIVATE_PROPERTY,*/ NULL, /*PRIVATE_SELECTION,*/ NULL, /*PRIVATE_WINDOW,*/ NULL, @@ -186,9 +313,33 @@ static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = { /*PRIVATE_DAMAGE,*/ NULL, /*PRIVATE_GLYPH,*/ NULL, /*PRIVATE_GLYPHSET,*/ NULL, - /*PRIVATE_PICTURE,*/ NULL + /*PRIVATE_PICTURE,*/ NULL, + /*PRIVATE_SYNC_FENCE,*/ NULL }; +static void +grow_private_set(DevPrivateSetPtr set, unsigned bytes) +{ + DevPrivateKey k; + + for (k = set->key; k; k = k->next) + k->offset += bytes; + set->offset += bytes; +} + +static void +grow_screen_specific_set(DevPrivateType type, unsigned bytes) +{ + int s; + + /* Update offsets for all screen-specific keys */ + for (s = 0; s < screenInfo.numScreens; s++) { + ScreenPtr pScreen = screenInfo.screens[s]; + + grow_private_set(&pScreen->screenSpecificPrivates[type], bytes); + } +} + /* * Register a private key. This takes the type of object the key will * be used with, which may be PRIVATE_ALL indicating that this key @@ -219,14 +370,13 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) /* Update offsets for all affected keys */ if (type == PRIVATE_XSELINUX) { - DevPrivateKey k; /* Resize if we can, or make sure nothing's allocated if we can't */ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) if (xselinux_private[t]) { if (!allocated_early[t]) - assert(!keys[t].created); + assert(!global_keys[t].created); else if (!allocated_early[t] (dixReallocPrivates, bytes)) return FALSE; } @@ -236,12 +386,12 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) */ for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { if (xselinux_private[t]) { - for (k = keys[t].key; k; k = k->next) - k->offset += bytes; - keys[t].offset += bytes; + grow_private_set(&global_keys[t], bytes); + grow_screen_specific_set(t, bytes); if (allocated_early[t]) allocated_early[t] (dixMovePrivates, bytes); } + } offset = 0; @@ -249,11 +399,12 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) else { /* Resize if we can, or make sure nothing's allocated if we can't */ if (!allocated_early[type]) - assert(!keys[type].created); + assert(!global_keys[type].created); else if (!allocated_early[type] (dixReallocPrivates, bytes)) return FALSE; - offset = keys[type].offset; - keys[type].offset += bytes; + offset = global_keys[type].offset; + global_keys[type].offset += bytes; + grow_screen_specific_set(type, bytes); } /* Setup this key */ @@ -262,8 +413,8 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size) key->initialized = TRUE; key->type = type; key->allocated = FALSE; - key->next = keys[type].key; - keys[type].key = key; + key->next = global_keys[type].key; + global_keys[type].key = key; return TRUE; } @@ -306,13 +457,15 @@ _dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen) void _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) { - keys[type].created++; + assert (!screen_specific_private[type]); + + global_keys[type].created++; if (xselinux_private[type]) - keys[PRIVATE_XSELINUX].created++; - if (keys[type].offset == 0) + global_keys[PRIVATE_XSELINUX].created++; + if (global_keys[type].offset == 0) addr = 0; *privates = addr; - memset(addr, '\0', keys[type].offset); + memset(addr, '\0', global_keys[type].offset); } /* @@ -321,9 +474,9 @@ _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) void _dixFiniPrivates(PrivatePtr privates, DevPrivateType type) { - keys[type].created--; + global_keys[type].created--; if (xselinux_private[type]) - keys[PRIVATE_XSELINUX].created--; + global_keys[PRIVATE_XSELINUX].created--; } /* @@ -342,10 +495,11 @@ _dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, PrivatePtr *devPrivates; assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST); + assert(!screen_specific_private[type]); /* round up so that void * is aligned */ baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); - totalSize = baseSize + keys[type].offset; + totalSize = baseSize + global_keys[type].offset; object = malloc(totalSize); if (!object) return NULL; @@ -370,8 +524,9 @@ dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) PrivatePtr p; assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST); + assert(!screen_specific_private[type]); - size = keys[type].offset; + size = global_keys[type].offset; if (!size) { p = NULL; } @@ -381,7 +536,7 @@ dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) } _dixInitPrivates(privates, p, type); - ++keys[type].allocated; + ++global_keys[type].allocated; return TRUE; } @@ -407,7 +562,7 @@ void dixFreePrivates(PrivatePtr privates, DevPrivateType type) { _dixFiniPrivates(privates, type); - --keys[type].allocated; + --global_keys[type].allocated; free(privates); } @@ -418,8 +573,9 @@ extern _X_EXPORT int dixPrivatesSize(DevPrivateType type) { assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST); + assert (!screen_specific_private[type]); - return keys[type].offset; + return global_keys[type].offset; } /* Table of devPrivates offsets */ @@ -454,36 +610,136 @@ dixLookupPrivateOffset(RESTYPE type) return -1; } -static const char *key_names[PRIVATE_LAST] = { - /* XSELinux uses the same private keys for numerous objects */ - /*[PRIVATE_XSELINUX] =*/ "XSELINUX", +/* + * Screen-specific privates + */ - /* Otherwise, you get a private in just the requested structure - */ - /* These can have objects created before all of the keys are registered */ - /*[PRIVATE_SCREEN] =*/ "SCREEN", - /*[PRIVATE_EXTENSION] =*/ "EXTENSION", - /*[PRIVATE_COLORMAP] =*/ "COLORMAP", +extern _X_EXPORT Bool +dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key, + DevPrivateType type, unsigned size) +{ + int offset; + unsigned bytes; - /* These cannot have any objects before all relevant keys are registered */ - /*[PRIVATE_DEVICE] =*/ "DEVICE", - /*[PRIVATE_CLIENT] =*/ "CLIENT", - /*[PRIVATE_PROPERTY] =*/ "PROPERTY", - /*[PRIVATE_SELECTION] =*/ "SELECTION", - /*[PRIVATE_WINDOW] =*/ "WINDOW", - /*[PRIVATE_PIXMAP] =*/ "PIXMAP", - /*[PRIVATE_GC] =*/ "GC", - /*[PRIVATE_CURSOR] =*/ "CURSOR", - /*[PRIVATE_CURSOR_BITS] =*/ "CURSOR_BITS", + if (!screen_specific_private[type]) + FatalError("Attempt to allocate screen-specific private storage for type %s\n", + key_names[type]); - /* extension privates */ - /*[PRIVATE_DBE_WINDOW] =*/ "DBE_WINDOW", - /*[PRIVATE_DAMAGE] =*/ "DAMAGE", - /*[PRIVATE_GLYPH] =*/ "GLYPH", - /*[PRIVATE_GLYPHSET] =*/ "GLYPHSET", - /*[PRIVATE_PICTURE] =*/ "PICTURE" , - /*[PRIVATE_SYNC_FENCE] =*/ "SYNC_FENCE" -}; + if (key->initialized) { + assert(size == key->size); + return TRUE; + } + + /* Compute required space */ + bytes = size; + if (size == 0) + bytes = sizeof(void *); + + /* align to void * size */ + bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1); + + assert (!allocated_early[type]); + assert (!pScreen->screenSpecificPrivates[type].created); + offset = pScreen->screenSpecificPrivates[type].offset; + pScreen->screenSpecificPrivates[type].offset += bytes; + + /* Setup this key */ + key->offset = offset; + key->size = size; + key->initialized = TRUE; + key->type = type; + key->allocated = FALSE; + key->next = pScreen->screenSpecificPrivates[type].key; + pScreen->screenSpecificPrivates[type].key = key; + + return TRUE; +} + +/* Clean up screen-specific privates before CloseScreen */ +void +dixFreeScreenSpecificPrivates(ScreenPtr pScreen) +{ +} + +/* Initialize screen-specific privates in AddScreen */ +void +dixInitScreenSpecificPrivates(ScreenPtr pScreen) +{ + DevPrivateType t; + + for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) + pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset; +} + +/* Initialize screen-specific privates in AddScreen */ +void +_dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type) +{ + int privates_size; + assert (screen_specific_private[type]); + + if (pScreen) { + privates_size = pScreen->screenSpecificPrivates[type].offset; + pScreen->screenSpecificPrivates[type].created++; + } + else + privates_size = global_keys[type].offset; + + global_keys[type].created++; + if (xselinux_private[type]) + global_keys[PRIVATE_XSELINUX].created++; + if (privates_size == 0) + addr = 0; + *privates = addr; + memset(addr, '\0', privates_size); +} + +void * +_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen, + unsigned baseSize, + unsigned clear, + unsigned offset, + DevPrivateType type) +{ + unsigned totalSize; + void *object; + PrivatePtr privates; + PrivatePtr *devPrivates; + int privates_size; + + assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST); + assert (screen_specific_private[type]); + + if (pScreen) + privates_size = pScreen->screenSpecificPrivates[type].offset; + else + privates_size = global_keys[type].offset; + /* round up so that void * is aligned */ + baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1); + totalSize = baseSize + privates_size; + object = malloc(totalSize); + if (!object) + return NULL; + + memset(object, '\0', clear); + privates = (PrivatePtr) (((char *) object) + baseSize); + devPrivates = (PrivatePtr *) ((char *) object + offset); + + _dixInitScreenPrivates(pScreen, devPrivates, privates, type); + + return object; +} + +int +dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type) +{ + assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST); + + if (screen_specific_private[type]) + return pScreen->screenSpecificPrivates[type].offset; + else + return global_keys[type].offset; +} void dixPrivateUsage(void) @@ -494,14 +750,14 @@ dixPrivateUsage(void) DevPrivateType t; for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) { - if (keys[t].offset) { + if (global_keys[t].offset) { ErrorF ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n", - key_names[t], keys[t].created, keys[t].offset, - keys[t].created * keys[t].offset, keys[t].allocated); - bytes += keys[t].created * keys[t].offset; - objects += keys[t].created; - alloc += keys[t].allocated; + key_names[t], global_keys[t].created, global_keys[t].offset, + global_keys[t].created * global_keys[t].offset, global_keys[t].allocated); + bytes += global_keys[t].created * global_keys[t].offset; + objects += global_keys[t].created; + alloc += global_keys[t].allocated; } } ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc); @@ -515,7 +771,7 @@ dixResetPrivates(void) for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) { DevPrivateKey key, next; - for (key = keys[t].key; key; key = next) { + for (key = global_keys[t].key; key; key = next) { next = key->next; key->offset = 0; key->initialized = FALSE; @@ -524,14 +780,14 @@ dixResetPrivates(void) if (key->allocated) free(key); } - if (keys[t].created) { + if (global_keys[t].created) { ErrorF("%d %ss still allocated at reset\n", - keys[t].created, key_names[t]); + global_keys[t].created, key_names[t]); dixPrivateUsage(); } - keys[t].key = NULL; - keys[t].offset = 0; - keys[t].created = 0; - keys[t].allocated = 0; + global_keys[t].key = NULL; + global_keys[t].offset = 0; + global_keys[t].created = 0; + global_keys[t].allocated = 0; } } |