From 16f2b8892d9ebcef6410a675d10549043223f617 Mon Sep 17 00:00:00 2001 From: Eamon Walsh Date: Fri, 23 Feb 2007 13:20:43 -0500 Subject: [PATCH] devPrivates rework: add new interface implementation. --- dix/privates.c | 317 +++++++++++++++++++++++++++++++++++++ hw/xfree86/loader/dixsym.c | 6 + 2 files changed, 323 insertions(+) diff --git a/dix/privates.c b/dix/privates.c index b20a1dbf0..feab86714 100644 --- a/dix/privates.c +++ b/dix/privates.c @@ -36,6 +36,7 @@ from The Open Group. #include "os.h" #include "windowstr.h" #include "resource.h" +#include "privates.h" #include "dixstruct.h" #include "gcstruct.h" #include "colormapst.h" @@ -44,6 +45,322 @@ from The Open Group. #include "inputstr.h" #include "extnsionst.h" +typedef struct _PrivateDescItem { + int index; + RESTYPE type; + pointer parent; + unsigned size; + CallbackListPtr initfuncs; + CallbackListPtr deletefuncs; +} PrivateDescItemRec, *PrivateDescItemPtr; + +/* keeps track of whether resource objects have been created */ +static char *instances = NULL; +static RESTYPE instancesSize = 0; +static char anyInstances = 0; + +/* list of all allocated privates */ +static PrivateDescItemPtr items = NULL; +static unsigned itemsSize = 0; +static unsigned nextPrivateIndex = 0; + +/* number of extra slots to add when resizing the tables */ +#define PRIV_TAB_INCREMENT 48 +/* set in index value for privates registered after resources were created */ +#define PRIV_DYN_MASK (1<<30) +/* descriptor item lookup convenience macro */ +#define GET_DESCRIPTOR(index) (items + ((index) & (PRIV_DYN_MASK - 1))) +/* type mask convenience macro */ +#define TYPE_BITS(type) ((type) & TypeMask) + +static _X_INLINE ResourcePtr +findResourceBucket(RESTYPE type, pointer instance) { + ResourcePtr res = *((ResourcePtr *)instance); + + while (res->type != type) + res = res->nexttype; + return res; +} + +/* + * Request functions; the latter calls the former internally. + */ +_X_EXPORT int +dixRequestPrivate(RESTYPE type, unsigned size, pointer parent) +{ + int index = nextPrivateIndex; + + /* check if privates descriptor table needs to be resized */ + if (nextPrivateIndex >= itemsSize) { + unsigned bytes; + unsigned size = itemsSize; + + while (nextPrivateIndex >= size) + size += PRIV_TAB_INCREMENT; + + bytes = size * sizeof(PrivateDescItemRec); + items = (PrivateDescItemPtr)xrealloc(items, bytes); + if (!items) { + itemsSize = nextPrivateIndex = 0; + return -1; + } + memset(items + itemsSize, 0, + (size - itemsSize) * sizeof(PrivateDescItemRec)); + } + + /* figure out if resource instances already exist */ + if ((type != RC_ANY && instances[TYPE_BITS(type)]) || + (type == RC_ANY && anyInstances)) + index |= PRIV_DYN_MASK; + + /* add privates descriptor */ + items[nextPrivateIndex].index = index; + items[nextPrivateIndex].type = type; + items[nextPrivateIndex].parent = parent; + items[nextPrivateIndex].size = size; + nextPrivateIndex++; + return index; +} + +_X_EXPORT int +dixRequestSinglePrivate(RESTYPE type, unsigned size, pointer instance) +{ + PrivatePtr ptr; + ResourcePtr res = findResourceBucket(type, instance); + int index = dixRequestPrivate(type, size, instance); + if (index < 0) + return index; + + ptr = (PrivatePtr)xalloc(sizeof(PrivateRec) + size); + if (!ptr) + return -1; + ptr->index = index; + ptr->value = ptr + 1; + ptr->next = res->privates; + res->privates = ptr; + return index; +} + +/* + * Lookup function (some of this could be static inlined) + */ +_X_EXPORT pointer +dixLookupPrivate(RESTYPE type, int index, pointer instance) +{ + ResourcePtr res = findResourceBucket(type, instance); + PrivatePtr ptr = res->privates; + PrivateDescItemPtr item; + PrivateCallbackRec calldata; + + /* see if private has already been allocated (likely) */ + while (ptr) { + if (ptr->index == index) + return ptr->value; + ptr = ptr->next; + } + + /* past this point, need to create private on the fly */ + /* create the new private */ + item = GET_DESCRIPTOR(index); + ptr = (PrivatePtr)xalloc(sizeof(PrivateRec) + item->size); + if (!ptr) + return NULL; + memset(ptr, 0, sizeof(PrivateRec) + item->size); + ptr->index = index; + ptr->value = ptr + 1; + ptr->next = res->privates; + res->privates = ptr; + + /* call any init funcs and return */ + calldata.value = ptr->value; + calldata.index = index; + calldata.resource = res; + CallCallbacks(&item->initfuncs, &calldata); + return ptr->value; +} + +/* + * Callback registration + */ +_X_EXPORT int +dixRegisterPrivateInitFunc(RESTYPE type, int index, + CallbackProcPtr callback, pointer data) +{ + return AddCallback(&GET_DESCRIPTOR(index)->initfuncs, callback, data); +} + +_X_EXPORT int +dixRegisterPrivateDeleteFunc(RESTYPE type, int index, + CallbackProcPtr callback, pointer data) +{ + return AddCallback(&GET_DESCRIPTOR(index)->deletefuncs, callback, data); +} + +/* + * Internal function called from the main loop to reset the subsystem. + */ +void +dixResetPrivates(void) +{ + if (items) + xfree(items); + items = NULL; + itemsSize = 0; + nextPrivateIndex = 0; + + if (instances) + xfree(instances); + instances = NULL; + instancesSize = 0; + anyInstances = 0; +} + +/* + * Internal function called from CreateNewResourceType. + */ +int +dixUpdatePrivates(void) +{ + RESTYPE next = lastResourceType + 1; + + /* check if instances table needs to be resized */ + if (next >= instancesSize) { + RESTYPE size = instancesSize; + + while (next >= size) + size += PRIV_TAB_INCREMENT; + + instances = (char *)xrealloc(instances, size); + if (!instances) { + instancesSize = 0; + return FALSE; + } + memset(instances + instancesSize, 0, size - instancesSize); + instancesSize = size; + } + return TRUE; +} + +/* + * Internal function called from dixAddResource. + * Allocates a ResourceRec along with any private space all in one chunk. + */ +ResourcePtr +dixAllocateResourceRec(RESTYPE type, pointer instance, pointer parent) +{ + unsigned i, count = 0, size = sizeof(ResourceRec); + ResourcePtr res; + PrivatePtr ptr; + char *value; + + /* first pass figures out total size */ + for (i=0; iprivates = (count > 0) ? ptr : NULL; + + /* second pass sets up privates records */ + count = 0; + for (i=0; i 0) + ptr[count-1].next = NULL; + + /* hook up back-pointer to resource record(s) */ + if (type & RC_PRIVATES) { + res->nexttype = *((ResourcePtr *)instance); + *((ResourcePtr *)instance) = res; + } + + instances[TYPE_BITS(type)] = anyInstances = 1; + return res; +} + +/* + * Internal function called from dixAddResource. + * Calls the init functions on a newly allocated resource. + */ +void +dixCallPrivateInitFuncs(ResourcePtr res) +{ + PrivatePtr ptr = res->privates; + PrivateCallbackRec calldata; + + calldata.resource = res; + while (ptr) { + calldata.value = ptr->value; + calldata.index = ptr->index; + CallCallbacks(&GET_DESCRIPTOR(ptr->index)->initfuncs, &calldata); + ptr = ptr->next; + } +} + +/* + * Internal function called from the various delete resource functions. + * Calls delete callbacks before freeing the ResourceRec and other bits. + */ +void +dixFreeResourceRec(ResourcePtr res) +{ + ResourcePtr *tmp; + PrivatePtr ptr, next, base; + PrivateCallbackRec calldata; + + /* first pass calls the delete callbacks */ + ptr = res->privates; + calldata.resource = res; + while (ptr) { + calldata.value = ptr->value; + calldata.index = ptr->index; + CallCallbacks(&GET_DESCRIPTOR(ptr->index)->deletefuncs, &calldata); + ptr = ptr->next; + } + + /* second pass frees any off-struct private records */ + ptr = res->privates; + base = (PrivatePtr)(res + 1); + while (ptr && ptr != base) { + next = ptr->next; + xfree(ptr); + ptr = next; + } + + /* remove the record from the nexttype linked list and free it*/ + if (res->type & RC_PRIVATES) { + tmp = (ResourcePtr *)res->value; + while (*tmp != res) + tmp = &(*tmp)->nexttype; + *tmp = (*tmp)->nexttype; + } + xfree(res); +} + +/* + * Following is the old devPrivates support. These functions and variables + * are deprecated, and should no longer be used. + */ + /* * See the Wrappers and devPrivates section in "Definition of the * Porting Layer for the X v11 Sample Server" (doc/Server/ddx.tbl.ms) diff --git a/hw/xfree86/loader/dixsym.c b/hw/xfree86/loader/dixsym.c index 32e0e4f68..9136351a2 100644 --- a/hw/xfree86/loader/dixsym.c +++ b/hw/xfree86/loader/dixsym.c @@ -63,6 +63,7 @@ #include "globals.h" #include "os.h" #include "osdep.h" +#include "privates.h" #include "resource.h" #include "servermd.h" #include "scrnintstr.h" @@ -259,6 +260,11 @@ _X_HIDDEN void *dixLookupTab[] = { SYMFUNC(GetScratchPixmapHeader) SYMFUNC(FreeScratchPixmapHeader) /* privates.c */ + SYMFUNC(dixRequestPrivate) + SYMFUNC(dixRequestSinglePrivate) + SYMFUNC(dixLookupPrivate) + SYMFUNC(dixRegisterPrivateInitFunc) + SYMFUNC(dixRegisterPrivateDeleteFunc) SYMFUNC(AllocateExtensionPrivate) SYMFUNC(AllocateExtensionPrivateIndex) SYMFUNC(AllocateClientPrivate)