summaryrefslogtreecommitdiff
path: root/dix/privates.c
diff options
context:
space:
mode:
authorEamon Walsh <ewalsh@tycho.nsa.gov>2007-02-23 13:20:43 -0500
committerEamon Walsh <ewalsh@moss-uranus.epoch.ncsc.mil>2007-02-23 13:22:46 -0500
commit16f2b8892d9ebcef6410a675d10549043223f617 (patch)
treee7fbd6606da9eddeafb1eb84024637b0ce70d371 /dix/privates.c
parent779faccfb78648a9f7e70b77dcfa9f6e19559772 (diff)
devPrivates rework: add new interface implementation.
Diffstat (limited to 'dix/privates.c')
-rw-r--r--dix/privates.c317
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)