[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