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.
|
||||
|
||||
*/
|
||||
/*
|
||||
* 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
|
||||
#include <dix-config.h>
|
||||
|
@ -38,192 +60,300 @@ from The Open Group.
|
|||
#include "cursorstr.h"
|
||||
#include "colormapst.h"
|
||||
#include "inputstr.h"
|
||||
#include "scrnintstr.h"
|
||||
#include "extnsionst.h"
|
||||
|
||||
struct _Private {
|
||||
int state;
|
||||
pointer value;
|
||||
static struct {
|
||||
DevPrivateKey key;
|
||||
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 {
|
||||
DevPrivateKey key;
|
||||
unsigned size;
|
||||
} PrivateDescRec;
|
||||
typedef Bool (*FixupFunc)(PrivatePtr *privates, int offset, unsigned bytes);
|
||||
|
||||
#define PRIV_MAX 256
|
||||
#define PRIV_STEP 16
|
||||
|
||||
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)
|
||||
static Bool
|
||||
dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
|
||||
{
|
||||
if (!key->key) {
|
||||
if (nextPriv >= PRIV_MAX)
|
||||
return NULL;
|
||||
void *new_privates;
|
||||
|
||||
items[nextPriv].key = key;
|
||||
key->key = nextPriv;
|
||||
nextPriv++;
|
||||
new_privates = realloc(*privates, old_offset + bytes);
|
||||
if (!new_privates)
|
||||
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 items + key->key;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static _X_INLINE int
|
||||
privateExists(PrivateRec **privates, const DevPrivateKey key)
|
||||
{
|
||||
return key->key && *privates &&
|
||||
(*privates)[0].state > key->key &&
|
||||
(*privates)[key->key].state;
|
||||
}
|
||||
static Bool (* const allocated_early[PRIVATE_LAST])(FixupFunc, unsigned) = {
|
||||
[PRIVATE_SCREEN] = fixupScreens,
|
||||
[PRIVATE_CLIENT] = fixupServerClient,
|
||||
[PRIVATE_EXTENSION] = fixupExtensions,
|
||||
[PRIVATE_COLORMAP] = fixupDefaultColormaps,
|
||||
};
|
||||
|
||||
/*
|
||||
* 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
|
||||
dixRegisterPrivateKey(const DevPrivateKey key, DevPrivateType type, unsigned size)
|
||||
Bool
|
||||
dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
|
||||
{
|
||||
PrivateDescRec *item = findItem(key);
|
||||
if (!item)
|
||||
return FALSE;
|
||||
if (size > item->size)
|
||||
item->size = size;
|
||||
DevPrivateType t;
|
||||
int offset;
|
||||
unsigned bytes;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a private and attach it to an existing object.
|
||||
*/
|
||||
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.
|
||||
* Initialize privates by zeroing them
|
||||
*/
|
||||
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;
|
||||
number_privates_allocated--;
|
||||
for (i = 1; i < privates->state; i++)
|
||||
if (privates[i].state) {
|
||||
/* free pre-allocated memory */
|
||||
if (items[i].size)
|
||||
free(privates[i].value);
|
||||
bytes_private_data_allocated -= items[i].size;
|
||||
}
|
||||
/*
|
||||
* Clean up privates
|
||||
*/
|
||||
void
|
||||
_dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
|
||||
{
|
||||
keys[type].created--;
|
||||
if (xselinux_private[type])
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
static const int offsets[] = {
|
||||
-1, /* RT_NONE */
|
||||
|
@ -256,32 +386,80 @@ dixLookupPrivateOffset(RESTYPE type)
|
|||
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
|
||||
dixPrivateUsage(void)
|
||||
{
|
||||
ErrorF("number of private structures: %d\n",
|
||||
number_privates_allocated);
|
||||
ErrorF("total number of private pointers: %d (%zd bytes)\n",
|
||||
number_private_ptrs_allocated,
|
||||
number_private_ptrs_allocated * sizeof (struct _Private));
|
||||
ErrorF("bytes of extra private data: %d\n",
|
||||
bytes_private_data_allocated);
|
||||
ErrorF("Total privates memory usage: %zd\n",
|
||||
bytes_private_data_allocated +
|
||||
number_private_ptrs_allocated * sizeof (struct _Private));
|
||||
int objects = 0;
|
||||
int bytes = 0;
|
||||
int alloc = 0;
|
||||
DevPrivateType t;
|
||||
|
||||
for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n",
|
||||
objects, bytes, alloc);
|
||||
}
|
||||
|
||||
void
|
||||
dixResetPrivates(void)
|
||||
{
|
||||
int i;
|
||||
DevPrivateType t;
|
||||
|
||||
/* reset private descriptors */
|
||||
for (i = 1; i < nextPriv; i++) {
|
||||
items[i].key->key = 0;
|
||||
items[i].size = 0;
|
||||
for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
|
||||
DevPrivateKey key;
|
||||
|
||||
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;
|
||||
|
||||
typedef struct _DevPrivateKeyRec {
|
||||
int key;
|
||||
int offset;
|
||||
int size;
|
||||
Bool initialized;
|
||||
DevPrivateType type;
|
||||
struct _DevPrivateKeyRec *next;
|
||||
} DevPrivateKeyRec, *DevPrivateKey;
|
||||
|
||||
/*
|
||||
|
@ -91,17 +95,46 @@ dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size);
|
|||
static inline Bool
|
||||
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
|
||||
* dixLookupPrivate(privates, key) will return 'val'.
|
||||
*
|
||||
* dixSetPrivate returns FALSE if a memory allocation fails.
|
||||
*/
|
||||
extern _X_EXPORT int
|
||||
dixSetPrivate(PrivatePtr *privates, const DevPrivateKey key, pointer val);
|
||||
static inline void
|
||||
dixSetPrivate(PrivatePtr *privates, const DevPrivateKey key, pointer val)
|
||||
{
|
||||
assert (key->size == 0);
|
||||
*(pointer *) dixGetPrivateAddr(privates, key) = val;
|
||||
}
|
||||
|
||||
#include "dix.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
|
||||
* contents
|
||||
*/
|
||||
extern _X_EXPORT pointer
|
||||
dixLookupPrivate(PrivatePtr *privates, const DevPrivateKey key);
|
||||
static inline pointer
|
||||
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
|
||||
* value in 'privates', then dixLookupPrivateAddr calls dixAllocatePrivate and
|
||||
* returns a pointer to the resulting associated value.
|
||||
* Look up the address of the pointer to the storage
|
||||
*
|
||||
* dixLookupPrivateAddr returns NULL if 'key' was not previously associated in
|
||||
* 'privates' and a memory allocation fails.
|
||||
* This returns the place where the private pointer is stored,
|
||||
* which is only valid for privates without predefined storage.
|
||||
*/
|
||||
extern _X_EXPORT pointer *
|
||||
dixLookupPrivateAddr(PrivatePtr *privates, const DevPrivateKey key);
|
||||
static inline pointer *
|
||||
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
|
||||
dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type) { *privates = NULL; return TRUE; }
|
||||
extern _X_EXPORT Bool
|
||||
dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type);
|
||||
|
||||
/*
|
||||
* Frees separately allocated private data (screens and clients)
|
||||
* Frees separately allocated private data
|
||||
*/
|
||||
extern _X_EXPORT void
|
||||
dixFreePrivates(PrivatePtr privates, DevPrivateType type);
|
||||
|
@ -142,48 +189,44 @@ dixFreePrivates(PrivatePtr privates, DevPrivateType type);
|
|||
/*
|
||||
* Initialize privates by zeroing them
|
||||
*/
|
||||
static inline void
|
||||
_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type) { *privates = NULL; }
|
||||
extern _X_EXPORT void
|
||||
_dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type);
|
||||
|
||||
#define dixInitPrivates(o, v, type) _dixInitPrivates(&(o)->devPrivates, (v), type);
|
||||
|
||||
/*
|
||||
* Clean up privates
|
||||
*/
|
||||
static inline void
|
||||
_dixFiniPrivates(PrivatePtr privates, DevPrivateType type) { dixFreePrivates(privates, type); }
|
||||
extern _X_EXPORT void
|
||||
_dixFiniPrivates(PrivatePtr privates, DevPrivateType type);
|
||||
|
||||
#define dixFiniPrivates(o,t) _dixFiniPrivates((o)->devPrivates,t)
|
||||
|
||||
/*
|
||||
* 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 *
|
||||
_dixAllocateObjectWithPrivates(unsigned size, unsigned clear, unsigned offset, DevPrivateType type) {
|
||||
return calloc(size, 1);
|
||||
}
|
||||
extern _X_EXPORT void *
|
||||
_dixAllocateObjectWithPrivates(unsigned size, unsigned clear, unsigned offset, DevPrivateType type);
|
||||
|
||||
#define dixAllocateObjectWithPrivates(t, type) (t *) _dixAllocateObjectWithPrivates(sizeof(t), sizeof(t), offsetof(t, devPrivates), type)
|
||||
|
||||
static inline void
|
||||
_dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type) {
|
||||
dixFreePrivates(privates, type);
|
||||
free(object);
|
||||
}
|
||||
extern _X_EXPORT void
|
||||
_dixFreeObjectWithPrivates(void *object, PrivatePtr privates, DevPrivateType type);
|
||||
|
||||
#define dixFreeObjectWithPrivates(o,t) _dixFreeObjectWithPrivates(o, (o)->devPrivates, t)
|
||||
|
||||
/*
|
||||
* Return size of privates for the specified type
|
||||
*/
|
||||
static inline int
|
||||
dixPrivatesSize(DevPrivateType type) { return 0; }
|
||||
extern _X_EXPORT int
|
||||
dixPrivatesSize(DevPrivateType type);
|
||||
|
||||
/*
|
||||
* Dump out private stats to ErrorF
|
||||
*/
|
||||
void
|
||||
extern void
|
||||
dixPrivateUsage(void);
|
||||
|
||||
/*
|
||||
|
@ -195,6 +238,7 @@ dixResetPrivates(void);
|
|||
|
||||
/*
|
||||
* Looks up the offset where the devPrivates field is located.
|
||||
*
|
||||
* Returns -1 if the specified resource has no dev privates.
|
||||
* The position of the devPrivates field varies by structure
|
||||
* and calling code might only know the resource type, not the
|
||||
|
|
Loading…
Reference in New Issue
Block a user