Change devPrivates implementation.
Each key now declares which object type it belongs to, this permits keys for different types to share the same offset within the allocated privates. As a special case for XSELinux, a key may be allocated as PRIVATE_XSELINUX which will allow it to continue to be used across the relevant object types. Signed-off-by: Keith Packard <keithp@keithp.com> Reviewed-by: Jamey Sharp <jamey@minilop.net>
This commit is contained in:
parent
faeebead7b
commit
495fc3eb2d
534
dix/privates.c
534
dix/privates.c
|
@ -25,6 +25,28 @@ other dealings in this Software without prior written authorization
|
||||||
from The Open Group.
|
from The Open Group.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright © 2010, Keith Packard
|
||||||
|
* Copyright © 2010, Jamey Sharp
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_DIX_CONFIG_H
|
#ifdef HAVE_DIX_CONFIG_H
|
||||||
#include <dix-config.h>
|
#include <dix-config.h>
|
||||||
|
@ -38,192 +60,300 @@ from The Open Group.
|
||||||
#include "cursorstr.h"
|
#include "cursorstr.h"
|
||||||
#include "colormapst.h"
|
#include "colormapst.h"
|
||||||
#include "inputstr.h"
|
#include "inputstr.h"
|
||||||
|
#include "scrnintstr.h"
|
||||||
|
#include "extnsionst.h"
|
||||||
|
|
||||||
struct _Private {
|
static struct {
|
||||||
int state;
|
DevPrivateKey key;
|
||||||
pointer value;
|
unsigned offset;
|
||||||
|
int created;
|
||||||
|
int allocated;
|
||||||
|
} keys[PRIVATE_LAST];
|
||||||
|
|
||||||
|
static const Bool xselinux_private[PRIVATE_LAST] = {
|
||||||
|
[PRIVATE_CLIENT] = TRUE,
|
||||||
|
[PRIVATE_WINDOW] = TRUE,
|
||||||
|
[PRIVATE_PIXMAP] = TRUE,
|
||||||
|
[PRIVATE_GC] = TRUE,
|
||||||
|
[PRIVATE_CURSOR] = TRUE,
|
||||||
|
[PRIVATE_COLORMAP] = TRUE,
|
||||||
|
[PRIVATE_DEVICE] = TRUE,
|
||||||
|
[PRIVATE_EXTENSION] = TRUE,
|
||||||
|
[PRIVATE_SELECTION] = TRUE,
|
||||||
|
[PRIVATE_PROPERTY] = TRUE,
|
||||||
|
[PRIVATE_PICTURE] = TRUE,
|
||||||
|
[PRIVATE_GLYPHSET] = TRUE,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _PrivateDesc {
|
typedef Bool (*FixupFunc)(PrivatePtr *privates, int offset, unsigned bytes);
|
||||||
DevPrivateKey key;
|
|
||||||
unsigned size;
|
|
||||||
} PrivateDescRec;
|
|
||||||
|
|
||||||
#define PRIV_MAX 256
|
static Bool
|
||||||
#define PRIV_STEP 16
|
dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
|
||||||
|
|
||||||
static int number_privates_allocated;
|
|
||||||
static int number_private_ptrs_allocated;
|
|
||||||
static int bytes_private_data_allocated;
|
|
||||||
|
|
||||||
/* list of all allocated privates */
|
|
||||||
static PrivateDescRec items[PRIV_MAX];
|
|
||||||
static int nextPriv;
|
|
||||||
|
|
||||||
static PrivateDescRec *
|
|
||||||
findItem(const DevPrivateKey key)
|
|
||||||
{
|
{
|
||||||
if (!key->key) {
|
void *new_privates;
|
||||||
if (nextPriv >= PRIV_MAX)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
items[nextPriv].key = key;
|
new_privates = realloc(*privates, old_offset + bytes);
|
||||||
key->key = nextPriv;
|
if (!new_privates)
|
||||||
nextPriv++;
|
return FALSE;
|
||||||
|
memset((char *) new_privates + old_offset, '\0', bytes);
|
||||||
|
*privates = new_privates;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
|
||||||
|
{
|
||||||
|
memmove((char *) *privates + bytes, *privates, new_offset - bytes);
|
||||||
|
memset(*privates, '\0', bytes);
|
||||||
|
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))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
fixupServerClient(FixupFunc fixup, unsigned bytes)
|
||||||
|
{
|
||||||
|
if (serverClient)
|
||||||
|
return fixup(&serverClient->devPrivates, keys[PRIVATE_CLIENT].offset, bytes);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
fixupExtensions(FixupFunc fixup, unsigned bytes)
|
||||||
|
{
|
||||||
|
unsigned char major;
|
||||||
|
ExtensionEntry *extension;
|
||||||
|
for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major)); major++)
|
||||||
|
if (!fixup(&extension->devPrivates, keys[PRIVATE_EXTENSION].offset, bytes))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool
|
||||||
|
fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
for (s = 0; s < screenInfo.numScreens; s++) {
|
||||||
|
ColormapPtr cmap;
|
||||||
|
dixLookupResourceByType((pointer *) &cmap, screenInfo.screens[s]->defColormap,
|
||||||
|
RT_COLORMAP, serverClient, DixCreateAccess);
|
||||||
|
if (cmap && !fixup(&cmap->devPrivates, keys[PRIVATE_COLORMAP].offset, bytes))
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
return TRUE;
|
||||||
return items + key->key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static _X_INLINE int
|
static Bool (* const allocated_early[PRIVATE_LAST])(FixupFunc, unsigned) = {
|
||||||
privateExists(PrivateRec **privates, const DevPrivateKey key)
|
[PRIVATE_SCREEN] = fixupScreens,
|
||||||
{
|
[PRIVATE_CLIENT] = fixupServerClient,
|
||||||
return key->key && *privates &&
|
[PRIVATE_EXTENSION] = fixupExtensions,
|
||||||
(*privates)[0].state > key->key &&
|
[PRIVATE_COLORMAP] = fixupDefaultColormaps,
|
||||||
(*privates)[key->key].state;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Request pre-allocated space.
|
* 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
|
||||||
|
* will be used with all of the private objects. If 'size' is
|
||||||
|
* non-zero, then the specified amount of space will be allocated in
|
||||||
|
* the private storage. Otherwise, space for a single pointer will
|
||||||
|
* be allocated which can be set with dixSetPrivate
|
||||||
*/
|
*/
|
||||||
int
|
Bool
|
||||||
dixRegisterPrivateKey(const DevPrivateKey key, DevPrivateType type, unsigned size)
|
dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
|
||||||
{
|
{
|
||||||
PrivateDescRec *item = findItem(key);
|
DevPrivateType t;
|
||||||
if (!item)
|
int offset;
|
||||||
return FALSE;
|
unsigned bytes;
|
||||||
if (size > item->size)
|
|
||||||
item->size = size;
|
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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
else if (!allocated_early[t](dixReallocPrivates, bytes))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move all existing keys up in the privates space to make
|
||||||
|
* room for this new global key
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
if (allocated_early[t])
|
||||||
|
allocated_early[t](dixMovePrivates, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
} else {
|
||||||
|
/* Resize if we can, or make sure nothing's allocated if we can't */
|
||||||
|
if (!allocated_early[type])
|
||||||
|
assert(!keys[type].created);
|
||||||
|
else if (!allocated_early[type](dixReallocPrivates, bytes))
|
||||||
|
return FALSE;
|
||||||
|
offset = keys[type].offset;
|
||||||
|
keys[type].offset += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup this key */
|
||||||
|
key->offset = offset;
|
||||||
|
key->size = size;
|
||||||
|
key->initialized = TRUE;
|
||||||
|
key->type = type;
|
||||||
|
key->next = keys[type].key;
|
||||||
|
keys[type].key = key;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a private and attach it to an existing object.
|
* Initialize privates by zeroing them
|
||||||
*/
|
|
||||||
static pointer *
|
|
||||||
dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key)
|
|
||||||
{
|
|
||||||
PrivateDescRec *item = findItem(key);
|
|
||||||
PrivateRec *ptr;
|
|
||||||
pointer value;
|
|
||||||
int oldsize, newsize;
|
|
||||||
|
|
||||||
newsize = (key->key / PRIV_STEP + 1) * PRIV_STEP;
|
|
||||||
|
|
||||||
/* resize or init privates array */
|
|
||||||
if (!item)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* initialize privates array if necessary */
|
|
||||||
if (!*privates) {
|
|
||||||
++number_privates_allocated;
|
|
||||||
number_private_ptrs_allocated += newsize;
|
|
||||||
ptr = calloc(newsize, sizeof(*ptr));
|
|
||||||
if (!ptr)
|
|
||||||
return NULL;
|
|
||||||
*privates = ptr;
|
|
||||||
(*privates)[0].state = newsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldsize = (*privates)[0].state;
|
|
||||||
|
|
||||||
/* resize privates array if necessary */
|
|
||||||
if (key->key >= oldsize) {
|
|
||||||
ptr = realloc(*privates, newsize * sizeof(*ptr));
|
|
||||||
if (!ptr)
|
|
||||||
return NULL;
|
|
||||||
memset(ptr + oldsize, 0, (newsize - oldsize) * sizeof(*ptr));
|
|
||||||
*privates = ptr;
|
|
||||||
(*privates)[0].state = newsize;
|
|
||||||
number_private_ptrs_allocated -= oldsize;
|
|
||||||
number_private_ptrs_allocated += newsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize slot */
|
|
||||||
ptr = *privates + key->key;
|
|
||||||
ptr->state = 1;
|
|
||||||
if (item->size) {
|
|
||||||
value = calloc(item->size, 1);
|
|
||||||
if (!value)
|
|
||||||
return NULL;
|
|
||||||
bytes_private_data_allocated += item->size;
|
|
||||||
ptr->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ptr->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look up a private pointer.
|
|
||||||
*/
|
|
||||||
pointer
|
|
||||||
dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key)
|
|
||||||
{
|
|
||||||
pointer *ptr;
|
|
||||||
|
|
||||||
assert (key->key != 0);
|
|
||||||
if (privateExists(privates, key))
|
|
||||||
return (*privates)[key->key].value;
|
|
||||||
|
|
||||||
ptr = dixAllocatePrivate(privates, key);
|
|
||||||
return ptr ? *ptr : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look up the address of a private pointer.
|
|
||||||
*/
|
|
||||||
pointer *
|
|
||||||
dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key)
|
|
||||||
{
|
|
||||||
assert (key->key != 0);
|
|
||||||
|
|
||||||
if (privateExists(privates, key))
|
|
||||||
return &(*privates)[key->key].value;
|
|
||||||
|
|
||||||
return dixAllocatePrivate(privates, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set a private pointer.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
|
|
||||||
{
|
|
||||||
assert (key->key != 0);
|
|
||||||
top:
|
|
||||||
if (privateExists(privates, key)) {
|
|
||||||
(*privates)[key->key].value = val;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dixAllocatePrivate(privates, key))
|
|
||||||
return FALSE;
|
|
||||||
goto top;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called to free privates at object deletion time.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
dixFreePrivates(PrivateRec *privates, DevPrivateType type)
|
_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
|
||||||
{
|
{
|
||||||
int i;
|
keys[type].created++;
|
||||||
|
if (xselinux_private[type])
|
||||||
|
keys[PRIVATE_XSELINUX].created++;
|
||||||
|
if (keys[type].offset == 0)
|
||||||
|
addr = 0;
|
||||||
|
*privates = addr;
|
||||||
|
memset(addr, '\0', keys[type].offset);
|
||||||
|
}
|
||||||
|
|
||||||
if (privates) {
|
/*
|
||||||
number_private_ptrs_allocated -= privates->state;
|
* Clean up privates
|
||||||
number_privates_allocated--;
|
*/
|
||||||
for (i = 1; i < privates->state; i++)
|
void
|
||||||
if (privates[i].state) {
|
_dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
|
||||||
/* free pre-allocated memory */
|
{
|
||||||
if (items[i].size)
|
keys[type].created--;
|
||||||
free(privates[i].value);
|
if (xselinux_private[type])
|
||||||
bytes_private_data_allocated -= items[i].size;
|
keys[PRIVATE_XSELINUX].created--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate new object with privates.
|
||||||
|
*
|
||||||
|
* This is expected to be invoked from the
|
||||||
|
* dixAllocateObjectWithPrivates macro
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
_dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear, unsigned offset, DevPrivateType type)
|
||||||
|
{
|
||||||
|
unsigned totalSize;
|
||||||
|
void *object;
|
||||||
|
PrivatePtr privates;
|
||||||
|
PrivatePtr *devPrivates;
|
||||||
|
|
||||||
|
assert (type > PRIVATE_SCREEN && type < PRIVATE_LAST);
|
||||||
|
|
||||||
|
/* round up so that void * is aligned */
|
||||||
|
baseSize = (baseSize + sizeof (void *) - 1) & ~(sizeof (void *) - 1);
|
||||||
|
totalSize = baseSize + keys[type].offset;
|
||||||
|
object = malloc(totalSize);
|
||||||
|
if (!object)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(object, '\0', clear);
|
||||||
|
privates = (PrivatePtr) (((char *) object) + baseSize);
|
||||||
|
devPrivates = (PrivatePtr *) ((char *) object + offset);
|
||||||
|
|
||||||
|
_dixInitPrivates(devPrivates, privates, type);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate privates separately from containing object.
|
||||||
|
* Used for clients and screens.
|
||||||
|
*/
|
||||||
|
Bool
|
||||||
|
dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
|
||||||
|
{
|
||||||
|
unsigned size;
|
||||||
|
PrivatePtr p;
|
||||||
|
|
||||||
|
assert (type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
|
||||||
|
|
||||||
|
size = keys[type].offset;
|
||||||
|
if (!size) {
|
||||||
|
p = NULL;
|
||||||
|
} else {
|
||||||
|
if (!(p = malloc(size)))
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dixInitPrivates(privates, p, type);
|
||||||
|
++keys[type].allocated;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free an object that has privates
|
||||||
|
*
|
||||||
|
* This is expected to be invoked from the
|
||||||
|
* dixFreeObjectWithPrivates macro
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type)
|
||||||
|
{
|
||||||
|
_dixFiniPrivates(privates, type);
|
||||||
|
free(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to free screen or client privates
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dixFreePrivates(PrivatePtr privates, DevPrivateType type)
|
||||||
|
{
|
||||||
|
_dixFiniPrivates(privates, type);
|
||||||
|
--keys[type].allocated;
|
||||||
free(privates);
|
free(privates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return size of privates for the specified type
|
||||||
|
*/
|
||||||
|
extern _X_EXPORT int
|
||||||
|
dixPrivatesSize(DevPrivateType type)
|
||||||
|
{
|
||||||
|
assert (type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
|
||||||
|
|
||||||
|
return keys[type].offset;
|
||||||
|
}
|
||||||
|
|
||||||
/* Table of devPrivates offsets */
|
/* Table of devPrivates offsets */
|
||||||
static const int offsets[] = {
|
static const int offsets[] = {
|
||||||
-1, /* RT_NONE */
|
-1, /* RT_NONE */
|
||||||
|
@ -256,32 +386,80 @@ dixLookupPrivateOffset(RESTYPE type)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
|
||||||
|
/* 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",
|
||||||
|
|
||||||
|
/* extension privates */
|
||||||
|
[PRIVATE_DBE_WINDOW] = "DBE_WINDOW",
|
||||||
|
[PRIVATE_DAMAGE] = "DAMAGE",
|
||||||
|
[PRIVATE_GLYPH] = "GLYPH",
|
||||||
|
[PRIVATE_GLYPHSET] = "GLYPHSET",
|
||||||
|
[PRIVATE_PICTURE] = "PICTURE",
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
dixPrivateUsage(void)
|
dixPrivateUsage(void)
|
||||||
{
|
{
|
||||||
ErrorF("number of private structures: %d\n",
|
int objects = 0;
|
||||||
number_privates_allocated);
|
int bytes = 0;
|
||||||
ErrorF("total number of private pointers: %d (%zd bytes)\n",
|
int alloc = 0;
|
||||||
number_private_ptrs_allocated,
|
DevPrivateType t;
|
||||||
number_private_ptrs_allocated * sizeof (struct _Private));
|
|
||||||
ErrorF("bytes of extra private data: %d\n",
|
for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
|
||||||
bytes_private_data_allocated);
|
if (keys[t].offset) {
|
||||||
ErrorF("Total privates memory usage: %zd\n",
|
ErrorF("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
|
||||||
bytes_private_data_allocated +
|
key_names[t], keys[t].created, keys[t].offset, keys[t].created * keys[t].offset,
|
||||||
number_private_ptrs_allocated * sizeof (struct _Private));
|
keys[t].allocated);
|
||||||
|
bytes += keys[t].created * keys[t].offset;
|
||||||
|
objects += keys[t].created;
|
||||||
|
alloc += keys[t].allocated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n",
|
||||||
|
objects, bytes, alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dixResetPrivates(void)
|
dixResetPrivates(void)
|
||||||
{
|
{
|
||||||
int i;
|
DevPrivateType t;
|
||||||
|
|
||||||
/* reset private descriptors */
|
for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
|
||||||
for (i = 1; i < nextPriv; i++) {
|
DevPrivateKey key;
|
||||||
items[i].key->key = 0;
|
|
||||||
items[i].size = 0;
|
for (key = keys[t].key; key; key = key->next) {
|
||||||
|
key->offset = 0;
|
||||||
|
key->initialized = FALSE;
|
||||||
|
key->size = 0;
|
||||||
|
key->type = 0;
|
||||||
|
}
|
||||||
|
if (keys[t].created) {
|
||||||
|
ErrorF("%d %ss still allocated at reset\n",
|
||||||
|
keys[t].created, key_names[t]);
|
||||||
|
dixPrivateUsage();
|
||||||
|
}
|
||||||
|
keys[t].key = NULL;
|
||||||
|
keys[t].offset = 0;
|
||||||
|
keys[t].created = 0;
|
||||||
|
keys[t].allocated = 0;
|
||||||
}
|
}
|
||||||
nextPriv = 1;
|
|
||||||
if (number_privates_allocated)
|
|
||||||
dixPrivateUsage();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,11 @@ typedef enum {
|
||||||
} DevPrivateType;
|
} DevPrivateType;
|
||||||
|
|
||||||
typedef struct _DevPrivateKeyRec {
|
typedef struct _DevPrivateKeyRec {
|
||||||
int key;
|
int offset;
|
||||||
|
int size;
|
||||||
|
Bool initialized;
|
||||||
|
DevPrivateType type;
|
||||||
|
struct _DevPrivateKeyRec *next;
|
||||||
} DevPrivateKeyRec, *DevPrivateKey;
|
} DevPrivateKeyRec, *DevPrivateKey;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -91,17 +95,46 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size);
|
||||||
static inline Bool
|
static inline Bool
|
||||||
dixPrivateKeyRegistered(DevPrivateKey key)
|
dixPrivateKeyRegistered(DevPrivateKey key)
|
||||||
{
|
{
|
||||||
return key->key != 0;
|
return key->initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the address of the private storage.
|
||||||
|
*
|
||||||
|
* For keys with pre-defined storage, this gets the base of that storage
|
||||||
|
* Otherwise, it returns the place where the private pointer is stored.
|
||||||
|
*/
|
||||||
|
static inline void *
|
||||||
|
dixGetPrivateAddr(PrivatePtr *privates, const DevPrivateKey key)
|
||||||
|
{
|
||||||
|
assert(key->initialized);
|
||||||
|
return (char *) (*privates) + key->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch a private pointer stored in the object
|
||||||
|
*
|
||||||
|
* Returns the pointer stored with dixSetPrivate.
|
||||||
|
* This must only be used with keys that have
|
||||||
|
* no pre-defined storage
|
||||||
|
*/
|
||||||
|
static inline void *
|
||||||
|
dixGetPrivate(PrivatePtr *privates, const DevPrivateKey key)
|
||||||
|
{
|
||||||
|
assert (key->size == 0);
|
||||||
|
return *(void **) dixGetPrivateAddr(privates, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Associate 'val' with 'key' in 'privates' so that later calls to
|
* Associate 'val' with 'key' in 'privates' so that later calls to
|
||||||
* dixLookupPrivate(privates, key) will return 'val'.
|
* dixLookupPrivate(privates, key) will return 'val'.
|
||||||
*
|
|
||||||
* dixSetPrivate returns FALSE if a memory allocation fails.
|
|
||||||
*/
|
*/
|
||||||
extern _X_EXPORT int
|
static inline void
|
||||||
dixSetPrivate(PrivatePtr *privates, const DevPrivateKey key, pointer val);
|
dixSetPrivate(PrivatePtr *privates, const DevPrivateKey key, pointer val)
|
||||||
|
{
|
||||||
|
assert (key->size == 0);
|
||||||
|
*(pointer *) dixGetPrivateAddr(privates, key) = val;
|
||||||
|
}
|
||||||
|
|
||||||
#include "dix.h"
|
#include "dix.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
@ -113,28 +146,42 @@ dixSetPrivate(PrivatePtr *privates, const DevPrivateKey key, pointer val);
|
||||||
* storage. For privates without defined storage, return the pointer
|
* storage. For privates without defined storage, return the pointer
|
||||||
* contents
|
* contents
|
||||||
*/
|
*/
|
||||||
extern _X_EXPORT pointer
|
static inline pointer
|
||||||
dixLookupPrivate(PrivatePtr *privates, const DevPrivateKey key);
|
dixLookupPrivate(PrivatePtr *privates, const DevPrivateKey key)
|
||||||
|
{
|
||||||
|
if (key->size)
|
||||||
|
return dixGetPrivateAddr(privates, key);
|
||||||
|
else
|
||||||
|
return dixGetPrivate(privates, key);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up the address of a private pointer. If 'key' is not associated with a
|
* Look up the address of the pointer to the storage
|
||||||
* value in 'privates', then dixLookupPrivateAddr calls dixAllocatePrivate and
|
|
||||||
* returns a pointer to the resulting associated value.
|
|
||||||
*
|
*
|
||||||
* dixLookupPrivateAddr returns NULL if 'key' was not previously associated in
|
* This returns the place where the private pointer is stored,
|
||||||
* 'privates' and a memory allocation fails.
|
* which is only valid for privates without predefined storage.
|
||||||
*/
|
*/
|
||||||
extern _X_EXPORT pointer *
|
static inline pointer *
|
||||||
dixLookupPrivateAddr(PrivatePtr *privates, const DevPrivateKey key);
|
dixLookupPrivateAddr(PrivatePtr *privates, const DevPrivateKey key)
|
||||||
|
{
|
||||||
|
assert (key->size == 0);
|
||||||
|
return dixGetPrivateAddr(privates, key);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocates private data separately from main object (clients and colormaps)
|
* Allocates private data separately from main object.
|
||||||
|
*
|
||||||
|
* For objects created during server initialization, this allows those
|
||||||
|
* privates to be re-allocated as new private keys are registered.
|
||||||
|
*
|
||||||
|
* This includes screens, the serverClient, default colormaps and
|
||||||
|
* extensions entries.
|
||||||
*/
|
*/
|
||||||
static inline Bool
|
extern _X_EXPORT Bool
|
||||||
dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) { *privates = NULL; return TRUE; }
|
dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Frees separately allocated private data (screens and clients)
|
* Frees separately allocated private data
|
||||||
*/
|
*/
|
||||||
extern _X_EXPORT void
|
extern _X_EXPORT void
|
||||||
dixFreePrivates(PrivatePtr privates, DevPrivateType type);
|
dixFreePrivates(PrivatePtr privates, DevPrivateType type);
|
||||||
|
@ -142,48 +189,44 @@ dixFreePrivates(PrivatePtr privates, DevPrivateType type);
|
||||||
/*
|
/*
|
||||||
* Initialize privates by zeroing them
|
* Initialize privates by zeroing them
|
||||||
*/
|
*/
|
||||||
static inline void
|
extern _X_EXPORT void
|
||||||
_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) { *privates = NULL; }
|
_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type);
|
||||||
|
|
||||||
#define dixInitPrivates(o, v, type) _dixInitPrivates(&(o)->devPrivates, (v), type);
|
#define dixInitPrivates(o, v, type) _dixInitPrivates(&(o)->devPrivates, (v), type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up privates
|
* Clean up privates
|
||||||
*/
|
*/
|
||||||
static inline void
|
extern _X_EXPORT void
|
||||||
_dixFiniPrivates(PrivatePtr privates, DevPrivateType type) { dixFreePrivates(privates, type); }
|
_dixFiniPrivates(PrivatePtr privates, DevPrivateType type);
|
||||||
|
|
||||||
#define dixFiniPrivates(o,t) _dixFiniPrivates((o)->devPrivates,t)
|
#define dixFiniPrivates(o,t) _dixFiniPrivates((o)->devPrivates,t)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocates private data at object creation time. Required
|
* Allocates private data at object creation time. Required
|
||||||
* for all objects other than ScreenRecs.
|
* for almost all objects, except for the list described
|
||||||
|
* above for dixAllocatePrivates.
|
||||||
*/
|
*/
|
||||||
static inline void *
|
extern _X_EXPORT void *
|
||||||
_dixAllocateObjectWithPrivates(unsigned size, unsigned clear, unsigned offset, DevPrivateType type) {
|
_dixAllocateObjectWithPrivates(unsigned size, unsigned clear, unsigned offset, DevPrivateType type);
|
||||||
return calloc(size, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dixAllocateObjectWithPrivates(t, type) (t *) _dixAllocateObjectWithPrivates(sizeof(t), sizeof(t), offsetof(t, devPrivates), type)
|
#define dixAllocateObjectWithPrivates(t, type) (t *) _dixAllocateObjectWithPrivates(sizeof(t), sizeof(t), offsetof(t, devPrivates), type)
|
||||||
|
|
||||||
static inline void
|
extern _X_EXPORT void
|
||||||
_dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type) {
|
_dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type);
|
||||||
dixFreePrivates(privates, type);
|
|
||||||
free(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dixFreeObjectWithPrivates(o,t) _dixFreeObjectWithPrivates(o, (o)->devPrivates, t)
|
#define dixFreeObjectWithPrivates(o,t) _dixFreeObjectWithPrivates(o, (o)->devPrivates, t)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return size of privates for the specified type
|
* Return size of privates for the specified type
|
||||||
*/
|
*/
|
||||||
static inline int
|
extern _X_EXPORT int
|
||||||
dixPrivatesSize(DevPrivateType type) { return 0; }
|
dixPrivatesSize(DevPrivateType type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dump out private stats to ErrorF
|
* Dump out private stats to ErrorF
|
||||||
*/
|
*/
|
||||||
void
|
extern void
|
||||||
dixPrivateUsage(void);
|
dixPrivateUsage(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -195,6 +238,7 @@ dixResetPrivates(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Looks up the offset where the devPrivates field is located.
|
* Looks up the offset where the devPrivates field is located.
|
||||||
|
*
|
||||||
* Returns -1 if the specified resource has no dev privates.
|
* Returns -1 if the specified resource has no dev privates.
|
||||||
* The position of the devPrivates field varies by structure
|
* The position of the devPrivates field varies by structure
|
||||||
* and calling code might only know the resource type, not the
|
* and calling code might only know the resource type, not the
|
||||||
|
|
Loading…
Reference in New Issue