diff options
author | Eamon Walsh <ewalsh@tycho.nsa.gov> | 2007-02-23 13:20:43 -0500 |
---|---|---|
committer | Eamon Walsh <ewalsh@moss-uranus.epoch.ncsc.mil> | 2007-02-23 13:22:46 -0500 |
commit | 16f2b8892d9ebcef6410a675d10549043223f617 (patch) | |
tree | e7fbd6606da9eddeafb1eb84024637b0ce70d371 /dix/privates.c | |
parent | 779faccfb78648a9f7e70b77dcfa9f6e19559772 (diff) |
devPrivates rework: add new interface implementation.
Diffstat (limited to 'dix/privates.c')
-rw-r--r-- | dix/privates.c | 317 |
1 files changed, 317 insertions, 0 deletions
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; i<nextPrivateIndex; i++) + if (items[i].type == type && + (items[i].parent == NULL || items[i].parent == parent)) { + + size += sizeof(PrivateRec) + items[i].size; + count++; + } + + /* allocate resource bucket */ + res = (ResourcePtr)xalloc(size); + if (!res) + return res; + memset(res, 0, size); + ptr = (PrivatePtr)(res + 1); + value = (char *)(ptr + count); + res->privates = (count > 0) ? ptr : NULL; + + /* second pass sets up privates records */ + count = 0; + for (i=0; i<nextPrivateIndex; i++) + if (items[i].type == type && + (items[i].parent == NULL || items[i].parent == parent)) { + + ptr[count].index = items[i].index; + ptr[count].value = value; + ptr[count].next = ptr + (count + 1); + count++; + value += items[i].size; + } + + if (count > 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) |