[PATCH 3/4] devPrivates rework: add implementation of interface
Eamon Walsh
ewalsh at tycho.nsa.gov
Thu Feb 22 16:07:19 PST 2007
Adds new interface implementation.
---
dix/privates.c | 305 ++++++++++++++++++++++++++++++++++++++++++++
hw/xfree86/loader/dixsym.c | 6 +
2 files changed, 311 insertions(+), 0 deletions(-)
diff --git a/dix/privates.c b/dix/privates.c
index b20a1db..2fc0449 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,310 @@ 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 (TYPE_BITS(res->type) != TYPE_BITS(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_BITS(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 parent)
+{
+ unsigned i, count = 0, size = sizeof(ResourceRec);
+ ResourcePtr res;
+ PrivatePtr ptr;
+ char *value;
+ type = TYPE_BITS(type);
+
+ /* 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;
+
+ instances[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)
+{
+ 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;
+ }
+
+ /* finally, free the ResourceRec itself */
+ 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 32e0e4f..9136351 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)
-- 1.4.4.2
More information about the xorg
mailing list