summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEamon Walsh <ewalsh@tycho.nsa.gov>2007-03-01 15:00:02 -0500
committerEamon Walsh <ewalsh@moss-uranus.epoch.ncsc.mil>2007-03-05 11:50:45 -0500
commite684824709fa8ffe03dde3c8dfbc58c267515a4f (patch)
treedd9172343b3dea7cd2ab0ae365724c62cff81673
parent74f1de1de9633119c2cf26086875717181c8a6f7 (diff)
devPrivates rework: redo interface and implementation.
-rw-r--r--dix/main.c3
-rw-r--r--dix/privates.c433
-rw-r--r--dix/resource.c6
-rw-r--r--hw/xfree86/loader/dixsym.c7
-rw-r--r--include/privates.h126
-rw-r--r--include/resource.h23
6 files changed, 312 insertions, 286 deletions
diff --git a/dix/main.c b/dix/main.c
index b5954af2b..ed5e358c4 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -357,7 +357,8 @@ main(int argc, char *argv[], char *envp[])
InitAtoms();
InitEvents();
InitGlyphCaching();
- dixResetPrivates();
+ if (!dixResetPrivates())
+ FatalError("couldn't init private data storage");
ResetExtensionPrivates();
ResetClientPrivates();
ResetScreenPrivates();
diff --git a/dix/privates.c b/dix/privates.c
index feab86714..c4ecf6ada 100644
--- a/dix/privates.c
+++ b/dix/privates.c
@@ -31,6 +31,7 @@ from The Open Group.
#endif
#include <X11/X.h>
+#include <stddef.h>
#include "scrnintstr.h"
#include "misc.h"
#include "os.h"
@@ -45,315 +46,265 @@ from The Open Group.
#include "inputstr.h"
#include "extnsionst.h"
-typedef struct _PrivateDescItem {
- int index;
+typedef struct _PrivateDesc {
+ devprivate_key_t *key;
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;
+ struct _PrivateDesc *next;
+} PrivateDescRec;
/* 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 PrivateDescRec *items = NULL;
-static _X_INLINE ResourcePtr
-findResourceBucket(RESTYPE type, pointer instance) {
- ResourcePtr res = *((ResourcePtr *)instance);
-
- while (res->type != type)
- res = res->nexttype;
- return res;
+static _X_INLINE PrivateDescRec *
+findItem(devprivate_key_t *const key)
+{
+ PrivateDescRec *item = items;
+ while (item) {
+ if (item->key == key)
+ return item;
+ item = item->next;
+ }
+ return NULL;
}
/*
- * Request functions; the latter calls the former internally.
+ * Request pre-allocated space in resources of a given type.
*/
_X_EXPORT int
-dixRequestPrivate(RESTYPE type, unsigned size, pointer parent)
-{
- int index = nextPrivateIndex;
+dixRequestPrivate(RESTYPE type, devprivate_key_t *const key,
+ unsigned size, pointer parent)
+{
+ PrivateDescRec *item = findItem(key);
+ if (item) {
+ assert(item->type == type);
+ if (size > item->size)
+ item->size = size;
+ } else {
+ item = (PrivateDescRec *)xalloc(sizeof(PrivateDescRec));
+ if (!item)
+ return FALSE;
+ memset(item, 0, sizeof(PrivateDescRec));
+
+ /* add privates descriptor */
+ item->key = key;
+ item->type = type;
+ item->parent = parent;
+ item->size = size;
+ item->next = items;
+ items = item;
+ }
+ return TRUE;
+}
- /* check if privates descriptor table needs to be resized */
- if (nextPrivateIndex >= itemsSize) {
- unsigned bytes;
- unsigned size = itemsSize;
+/*
+ * Allocate a private and attach it to an existing object.
+ */
+_X_EXPORT pointer *
+dixAllocatePrivate(PrivateRec **privates, devprivate_key_t *const key)
+{
+ PrivateDescRec *item = findItem(key);
+ PrivateRec *ptr;
+ unsigned size = sizeof(PrivateRec);
+
+ if (item)
+ size += item->size;
- while (nextPrivateIndex >= size)
- size += PRIV_TAB_INCREMENT;
+ ptr = (PrivateRec *)xalloc(size);
+ if (!ptr)
+ return NULL;
+ memset(ptr, 0, size);
+ ptr->key = key;
+ ptr->value = (size > sizeof(PrivateRec)) ? (ptr + 1) : NULL;
+ ptr->next = *privates;
+ *privates = ptr;
- bytes = size * sizeof(PrivateDescItemRec);
- items = (PrivateDescItemPtr)xrealloc(items, bytes);
- if (!items) {
- itemsSize = nextPrivateIndex = 0;
- return -1;
- }
- memset(items + itemsSize, 0,
- (size - itemsSize) * sizeof(PrivateDescItemRec));
+ /* call any init funcs and return */
+ if (item) {
+ PrivateCallbackRec calldata = { key, ptr->value };
+ CallCallbacks(&item->initfuncs, &calldata);
}
-
- /* 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;
+ return &ptr->value;
}
-_X_EXPORT int
-dixRequestSinglePrivate(RESTYPE type, unsigned size, pointer instance)
+/*
+ * Allocates pre-requested privates in a single chunk.
+ */
+_X_EXPORT PrivateRec *
+dixAllocatePrivates(RESTYPE type, pointer parent)
{
- PrivatePtr ptr;
- ResourcePtr res = findResourceBucket(type, instance);
- int index = dixRequestPrivate(type, size, instance);
- if (index < 0)
- return index;
+ unsigned count = 0, size = 0;
+ PrivateCallbackRec calldata;
+ PrivateDescRec *item;
+ PrivateRec *ptr;
+ char *value;
+
+ /* first pass figures out total size */
+ for (item = items; item; item = item->next)
+ if ((item->type == type || item->type == RC_ANY) &&
+ (item->parent == NULL || item->parent == parent)) {
+
+ size += sizeof(PrivateRec) + item->size;
+ count++;
+ }
- ptr = (PrivatePtr)xalloc(sizeof(PrivateRec) + size);
+ /* allocate one chunk of memory for everything */
+ ptr = (PrivateRec *)xalloc(size);
if (!ptr)
- return -1;
- ptr->index = index;
- ptr->value = ptr + 1;
- ptr->next = res->privates;
- res->privates = ptr;
- return index;
+ return NULL;
+ memset(ptr, 0, size);
+ value = (char *)(ptr + count);
+
+ /* second pass sets up records and calls init funcs */
+ count = 0;
+ for (item = items; item; item = item->next)
+ if ((item->type == type || item->type == RC_ANY) &&
+ (item->parent == NULL || item->parent == parent)) {
+
+ ptr[count].key = calldata.key = item->key;
+ ptr[count].dontfree = (count > 0);
+ ptr[count].value = calldata.value = (items->size ? value : NULL);
+ ptr[count].next = ptr + (count + 1);
+
+ CallCallbacks(&item->initfuncs, &calldata);
+
+ count++;
+ value += item->size;
+ }
+
+ if (count > 0)
+ ptr[count-1].next = NULL;
+
+ return ptr;
}
/*
- * Lookup function (some of this could be static inlined)
+ * Called to free privates at object deletion time.
*/
-_X_EXPORT pointer
-dixLookupPrivate(RESTYPE type, int index, pointer instance)
+_X_EXPORT void
+dixFreePrivates(PrivateRec *privates)
{
- ResourcePtr res = findResourceBucket(type, instance);
- PrivatePtr ptr = res->privates;
- PrivateDescItemPtr item;
+ PrivateRec *ptr, *next;
+ PrivateDescRec *item;
PrivateCallbackRec calldata;
- /* see if private has already been allocated (likely) */
+ /* first pass calls the delete callbacks */
+ for (ptr = privates; ptr; ptr = ptr->next) {
+ item = findItem(ptr->key);
+ if (item) {
+ calldata.key = ptr->key;
+ calldata.value = ptr->value;
+ CallCallbacks(&item->deletefuncs, &calldata);
+ }
+ }
+
+ /* second pass frees the memory */
+ ptr = privates;
while (ptr) {
- if (ptr->index == index)
- return ptr->value;
- ptr = ptr->next;
+ if (ptr->dontfree)
+ ptr = ptr->next;
+ else {
+ next = ptr->next;
+ while (next && next->dontfree)
+ next = next->next;
+
+ xfree(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;
+ /* no more use of privates permitted */
+ *privates = NULL;
}
/*
* Callback registration
*/
_X_EXPORT int
-dixRegisterPrivateInitFunc(RESTYPE type, int index,
+dixRegisterPrivateInitFunc(devprivate_key_t *const key,
CallbackProcPtr callback, pointer data)
{
- return AddCallback(&GET_DESCRIPTOR(index)->initfuncs, callback, data);
+ PrivateDescRec *item = findItem(key);
+ if (!item)
+ return FALSE;
+ return AddCallback(&item->initfuncs, callback, data);
}
_X_EXPORT int
-dixRegisterPrivateDeleteFunc(RESTYPE type, int index,
+dixRegisterPrivateDeleteFunc(devprivate_key_t *const key,
CallbackProcPtr callback, pointer data)
{
- return AddCallback(&GET_DESCRIPTOR(index)->deletefuncs, callback, data);
+ PrivateDescRec *item = findItem(key);
+ if (!item)
+ return FALSE;
+ return AddCallback(&item->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;
-}
+/* Table of devPrivates offsets */
+static unsigned *offsets = NULL;
+static unsigned offsetsSize = 0;
/*
- * Internal function called from CreateNewResourceType.
+ * Specify where the devPrivates field is located in a structure type
*/
-int
-dixUpdatePrivates(void)
+_X_EXPORT int
+dixRegisterPrivateOffset(RESTYPE type, unsigned offset)
{
- 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;
+ type = type & TypeMask;
- instances = (char *)xrealloc(instances, size);
- if (!instances) {
- instancesSize = 0;
+ /* resize offsets table if necessary */
+ while (type >= offsetsSize) {
+ offsets = (unsigned *)xrealloc(offsets,
+ offsetsSize * 2 * sizeof(unsigned));
+ if (!offsets) {
+ offsetsSize = 0;
return FALSE;
}
- memset(instances + instancesSize, 0, size - instancesSize);
- instancesSize = size;
+ offsetsSize *= 2;
}
+
+ offsets[type] = offset;
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)
+_X_EXPORT unsigned
+dixLookupPrivateOffset(RESTYPE type)
{
- 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;
+ assert(type & RC_PRIVATES);
+ type = type & TypeMask;
+ assert(type < offsetsSize);
+ return offsets[type];
}
-
+
/*
- * Internal function called from dixAddResource.
- * Calls the init functions on a newly allocated resource.
+ * Called from the main loop to reset the subsystem.
*/
-void
-dixCallPrivateInitFuncs(ResourcePtr res)
+int
+dixResetPrivates(void)
{
- 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;
+ PrivateDescRec *next;
+ while (items) {
+ next = items->next;
+ xfree(items);
+ items = 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;
+ if (offsets)
+ xfree(offsets);
- /* 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;
- }
+ offsetsSize = 16;
+ offsets = (unsigned *)xalloc(offsetsSize * sizeof(unsigned));
+ if (!offsets)
+ return FALSE;
- /* 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;
- }
+ /* register basic resource offsets */
+ if (!dixRegisterPrivateOffset(RT_WINDOW, offsetof(WindowRec,devPrivates)))
+ return FALSE;
- /* 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);
+ return TRUE;
}
/*
diff --git a/dix/resource.c b/dix/resource.c
index c568ed0b0..2cad7c01b 100644
--- a/dix/resource.c
+++ b/dix/resource.c
@@ -169,6 +169,12 @@ static void RebuildTable(
#define INITHASHSIZE 6
#define MAXHASHSIZE 11
+typedef struct _Resource {
+ struct _Resource *next;
+ XID id;
+ RESTYPE type;
+ pointer value;
+} ResourceRec, *ResourcePtr;
#define NullResource ((ResourcePtr)NULL)
typedef struct _ClientResource {
diff --git a/hw/xfree86/loader/dixsym.c b/hw/xfree86/loader/dixsym.c
index 9136351a2..5479ed0df 100644
--- a/hw/xfree86/loader/dixsym.c
+++ b/hw/xfree86/loader/dixsym.c
@@ -261,10 +261,13 @@ _X_HIDDEN void *dixLookupTab[] = {
SYMFUNC(FreeScratchPixmapHeader)
/* privates.c */
SYMFUNC(dixRequestPrivate)
- SYMFUNC(dixRequestSinglePrivate)
- SYMFUNC(dixLookupPrivate)
SYMFUNC(dixRegisterPrivateInitFunc)
SYMFUNC(dixRegisterPrivateDeleteFunc)
+ SYMFUNC(dixAllocatePrivate)
+ SYMFUNC(dixAllocatePrivates)
+ SYMFUNC(dixFreePrivates)
+ SYMFUNC(dixRegisterPrivateOffset)
+ SYMFUNC(dixLookupPrivateOffset)
SYMFUNC(AllocateExtensionPrivate)
SYMFUNC(AllocateExtensionPrivateIndex)
SYMFUNC(AllocateClientPrivate)
diff --git a/include/privates.h b/include/privates.h
index 8d7427074..898fdd9c9 100644
--- a/include/privates.h
+++ b/include/privates.h
@@ -19,59 +19,141 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* STUFF FOR PRIVATES
*****************************************************************/
+typedef struct _PrivateKey {
+ int unused;
+} devprivate_key_t;
+
+typedef struct _Private {
+ devprivate_key_t *key;
+ int dontfree;
+ pointer value;
+ struct _Private *next;
+} PrivateRec;
+
/*
- * Request private space for your driver/module in all resources of a type.
- * A non-null pScreen argument restricts to resources on a given screen.
+ * Request pre-allocated private space for your driver/module.
+ * A non-null pScreen argument restricts to objects on a given screen.
*/
extern int
-dixRequestPrivate(RESTYPE type, unsigned size, pointer pScreen);
+dixRequestPrivate(RESTYPE type, devprivate_key_t *const key,
+ unsigned size, pointer pScreen);
/*
- * Request private space in just one individual resource object.
+ * Allocates a new private and attaches it to an existing object.
*/
-extern int
-dixRequestSinglePrivate(RESTYPE type, unsigned size, pointer instance);
+extern pointer *
+dixAllocatePrivate(PrivateRec **privates, devprivate_key_t *const key);
/*
* Look up a private pointer.
*/
-extern pointer
-dixLookupPrivate(RESTYPE type, int index, pointer instance);
+static _X_INLINE pointer
+dixLookupPrivate(PrivateRec **privates, devprivate_key_t *const key)
+{
+ PrivateRec *rec = *privates;
+ pointer *ptr;
+
+ while (rec) {
+ if (rec->key == key)
+ return rec->value;
+ rec = rec->next;
+ }
+
+ ptr = dixAllocatePrivate(privates, key);
+ return ptr ? *ptr : NULL;
+}
+
+/*
+ * Look up the address of a private pointer.
+ */
+static _X_INLINE pointer *
+dixLookupPrivateAddr(PrivateRec **privates, devprivate_key_t *const key)
+{
+ PrivateRec *rec = *privates;
+
+ while (rec) {
+ if (rec->key == key)
+ return &rec->value;
+ rec = rec->next;
+ }
+
+ return dixAllocatePrivate(privates, key);
+}
+
+/*
+ * Set a private pointer.
+ */
+static _X_INLINE int
+dixSetPrivate(PrivateRec **privates, devprivate_key_t *const key, pointer val)
+{
+ PrivateRec *rec;
+
+ top:
+ rec = *privates;
+ while (rec) {
+ if (rec->key == key) {
+ rec->value = val;
+ return TRUE;
+ }
+ rec = rec->next;
+ }
+
+ if (!dixAllocatePrivate(privates, key))
+ return FALSE;
+ goto top;
+}
/*
* Register callbacks to be called on private allocation/freeing.
* The calldata argument to the callbacks is a PrivateCallbackPtr.
*/
typedef struct _PrivateCallback {
+ devprivate_key_t *key; /* private registration key */
pointer value; /* pointer to private */
- int index; /* registration index */
- ResourcePtr resource; /* resource record (do not modify!) */
-} PrivateCallbackRec, *PrivateCallbackPtr;
+} PrivateCallbackRec;
extern int
-dixRegisterPrivateInitFunc(RESTYPE type, int index,
+dixRegisterPrivateInitFunc(devprivate_key_t *const key,
CallbackProcPtr callback, pointer userdata);
extern int
-dixRegisterPrivateDeleteFunc(RESTYPE type, int index,
+dixRegisterPrivateDeleteFunc(devprivate_key_t *const key,
CallbackProcPtr callback, pointer userdata);
/*
- * Internal functions
+ * Allocates all pre-requested private space in one chunk.
+ */
+extern PrivateRec *
+dixAllocatePrivates(RESTYPE type, pointer parent);
+
+/*
+ * Frees any private space that is not part of an object.
*/
extern void
-dixResetPrivates(void);
+dixFreePrivates(PrivateRec *privates);
+/*
+ * Resets the subsystem, called from the main loop.
+ */
extern int
-dixUpdatePrivates(void);
+dixResetPrivates(void);
-extern ResourcePtr
-dixAllocateResourceRec(RESTYPE type, pointer value, pointer parent);
+/*
+ * These next two functions are necessary because the position of
+ * the devPrivates field varies by structure and calling code might
+ * only know the resource type, not the structure definition.
+ */
-extern void
-dixCallPrivateInitFuncs(ResourcePtr res);
+/*
+ * Looks up the offset where the devPrivates field is located by type.
+ */
+extern unsigned
+dixLookupPrivateOffset(RESTYPE type);
-extern void
-dixFreeResourceRec(ResourcePtr res);
+/*
+ * Specifies the offset where the devPrivates field is located.
+ */
+extern int
+dixRegisterPrivateOffset(RESTYPE type, unsigned offset);
#endif /* PRIVATES_H */
diff --git a/include/resource.h b/include/resource.h
index 902305805..40259ac27 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -53,27 +53,10 @@ SOFTWARE.
* STUFF FOR RESOURCES
*****************************************************************/
-/* Resource structures */
+/* classes for Resource routines */
typedef unsigned long RESTYPE;
-typedef struct _Private {
- int index;
- pointer value;
- struct _Private *next;
-} PrivateRec, *PrivatePtr;
-
-typedef struct _Resource {
- struct _Resource *next;
- struct _Resource *nexttype;
- XID id;
- RESTYPE type;
- pointer value;
- PrivatePtr privates;
-} ResourceRec, *ResourcePtr;
-
-/* classes for Resource routines */
-
#define RC_VANILLA ((RESTYPE)0)
#define RC_CACHED ((RESTYPE)1<<31)
#define RC_DRAWABLE ((RESTYPE)1<<30)
@@ -84,8 +67,8 @@ typedef struct _Resource {
*/
#define RC_NEVERRETAIN ((RESTYPE)1<<29)
/* Use class RC_PRIVATES for resources that support extra private data.
- * Resources having this class must provide a field of type ResourcePtr
- * at the top of the resource structure, which must be initalized to NULL.
+ * Resources having this class must provide a field of type PrivateRec *.
+ * Refer to the X server documentation on devPrivates for the details.
*/
#define RC_PRIVATES ((RESTYPE)1<<28)
#define RC_LASTPREDEF RC_PRIVATES