make X server use system libdrm - this requires libdrm >= 2.3.0
This patch blacklists the load "drm" line, moves some functions in dri module
links dri module against libdrm, and removes the X copy of libdrm
(cherry picked from fd91630b73
commit)
This commit is contained in:
parent
69820a10e3
commit
e87285c2a0
|
@ -615,10 +615,11 @@ AM_CONDITIONAL(DRI, test "x$DRI" = xyes)
|
|||
if test "x$DRI" = xyes; then
|
||||
AC_DEFINE(XF86DRI, 1, [Build DRI extension])
|
||||
PKG_CHECK_MODULES([DRIPROTO], [xf86driproto])
|
||||
PKG_CHECK_MODULES([LIBDRM], [libdrm])
|
||||
PKG_CHECK_MODULES([LIBDRM], [libdrm >= 2.3.0])
|
||||
PKG_CHECK_MODULES([GL], [glproto >= 1.4.1])
|
||||
AC_SUBST(DRIPROTO_CFLAGS)
|
||||
AC_SUBST(LIBDRM_CFLAGS)
|
||||
AC_SUBST(LIBDRM_LIBS)
|
||||
AC_SUBST(GL_CFLAGS)
|
||||
fi
|
||||
|
||||
|
@ -1744,7 +1745,6 @@ hw/xfree86/loader/Makefile
|
|||
hw/xfree86/os-support/Makefile
|
||||
hw/xfree86/os-support/bsd/Makefile
|
||||
hw/xfree86/os-support/bus/Makefile
|
||||
hw/xfree86/os-support/drm/Makefile
|
||||
hw/xfree86/os-support/hurd/Makefile
|
||||
hw/xfree86/os-support/misc/Makefile
|
||||
hw/xfree86/os-support/linux/Makefile
|
||||
|
|
|
@ -251,7 +251,7 @@ xf86ModulelistFromConfig(pointer **optlist)
|
|||
{
|
||||
int count = 0, i = 0;
|
||||
char **modulearray;
|
||||
char *ignore[] = { "GLcore", "speedo", "bitmap", NULL };
|
||||
char *ignore[] = { "GLcore", "speedo", "bitmap", "drm", NULL };
|
||||
pointer *optarray;
|
||||
XF86LoadPtr modp;
|
||||
|
||||
|
|
|
@ -7,13 +7,10 @@ libdri_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \
|
|||
-I$(top_builddir)/GL/include \
|
||||
-I@MESA_SOURCE@/include \
|
||||
-DHAVE_XORG_CONFIG_H \
|
||||
\
|
||||
\
|
||||
\
|
||||
@DRIPROTO_CFLAGS@ \
|
||||
@LIBDRM_CFLAGS@ \
|
||||
@GL_CFLAGS@
|
||||
libdri_la_LDFLAGS = -module -avoid-version
|
||||
libdri_la_LDFLAGS = -module -avoid-version @LIBDRM_LIBS@
|
||||
libdri_ladir = $(moduledir)/extensions
|
||||
libdri_la_SOURCES = \
|
||||
dri.c \
|
||||
|
|
|
@ -42,11 +42,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define NEED_REPLIES
|
||||
#define NEED_EVENTS
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include "xf86drm.h"
|
||||
#include "misc.h"
|
||||
#include "dixstruct.h"
|
||||
#include "extnsionst.h"
|
||||
|
@ -67,6 +69,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include "glxserver.h"
|
||||
#include "mi.h"
|
||||
#include "mipointer.h"
|
||||
#include "xf86_OSproc.h"
|
||||
|
||||
#if !defined(PANORAMIX)
|
||||
extern Bool noPanoramiXExtension;
|
||||
|
@ -104,6 +107,7 @@ DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
Bool
|
||||
DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
|
||||
{
|
||||
|
@ -571,6 +575,26 @@ DRICloseScreen(ScreenPtr pScreen)
|
|||
}
|
||||
}
|
||||
|
||||
#define DRM_MSG_VERBOSITY 3
|
||||
|
||||
static int dri_drm_debug_print(const char *format, va_list ap)
|
||||
{
|
||||
xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dri_drm_get_perms(gid_t *group, mode_t *mode)
|
||||
{
|
||||
*group = xf86ConfigDRI.group;
|
||||
*mode = xf86ConfigDRI.mode;
|
||||
}
|
||||
|
||||
static drmServerInfo DRIDRMServerInfo = {
|
||||
dri_drm_debug_print,
|
||||
xf86LoadKernelModule,
|
||||
dri_drm_get_perms,
|
||||
};
|
||||
|
||||
Bool
|
||||
DRIExtensionInit(void)
|
||||
{
|
||||
|
@ -598,6 +622,8 @@ DRIExtensionInit(void)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
drmSetServerInfo(&DRIDRMServerInfo);
|
||||
|
||||
RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL);
|
||||
|
||||
return TRUE;
|
||||
|
@ -2075,3 +2101,71 @@ DRICreatePCIBusID(pciVideoPtr PciInfo)
|
|||
PciInfo->device, PciInfo->func);
|
||||
return busID;
|
||||
}
|
||||
|
||||
static void drmSIGIOHandler(int interrupt, void *closure)
|
||||
{
|
||||
unsigned long key;
|
||||
void *value;
|
||||
ssize_t count;
|
||||
drm_ctx_t ctx;
|
||||
typedef void (*_drmCallback)(int, void *, void *);
|
||||
char buf[256];
|
||||
drm_context_t old;
|
||||
drm_context_t new;
|
||||
void *oldctx;
|
||||
void *newctx;
|
||||
char *pt;
|
||||
drmHashEntry *entry;
|
||||
void *hash_table;
|
||||
|
||||
hash_table = drmGetHashTable();
|
||||
|
||||
if (!hash_table) return;
|
||||
if (drmHashFirst(hash_table, &key, &value)) {
|
||||
entry = value;
|
||||
do {
|
||||
#if 0
|
||||
fprintf(stderr, "Trying %d\n", entry->fd);
|
||||
#endif
|
||||
if ((count = read(entry->fd, buf, sizeof(buf))) > 0) {
|
||||
buf[count] = '\0';
|
||||
#if 0
|
||||
fprintf(stderr, "Got %s\n", buf);
|
||||
#endif
|
||||
|
||||
for (pt = buf; *pt != ' '; ++pt); /* Find first space */
|
||||
++pt;
|
||||
old = strtol(pt, &pt, 0);
|
||||
new = strtol(pt, NULL, 0);
|
||||
oldctx = drmGetContextTag(entry->fd, old);
|
||||
newctx = drmGetContextTag(entry->fd, new);
|
||||
#if 0
|
||||
fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx);
|
||||
#endif
|
||||
((_drmCallback)entry->f)(entry->fd, oldctx, newctx);
|
||||
ctx.handle = new;
|
||||
ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
|
||||
}
|
||||
} while (drmHashNext(hash_table, &key, &value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *))
|
||||
{
|
||||
drmHashEntry *entry;
|
||||
|
||||
entry = drmGetEntry(fd);
|
||||
entry->f = f;
|
||||
|
||||
return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
|
||||
}
|
||||
|
||||
int drmRemoveSIGIOHandler(int fd)
|
||||
{
|
||||
drmHashEntry *entry = drmGetEntry(fd);
|
||||
|
||||
entry->f = NULL;
|
||||
|
||||
return xf86RemoveSIGIOHandler(fd);
|
||||
}
|
||||
|
|
|
@ -339,6 +339,8 @@ extern void DRIMoveBuffersHelper(ScreenPtr pScreen,
|
|||
|
||||
extern char *DRICreatePCIBusID(pciVideoPtr PciInfo);
|
||||
|
||||
extern int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *));
|
||||
extern int drmRemoveSIGIOHandler(int fd);
|
||||
#define _DRI_H_
|
||||
|
||||
#endif
|
||||
|
|
|
@ -74,23 +74,14 @@ static pointer
|
|||
driSetup(pointer module, pointer opts, int *errmaj, int *errmin)
|
||||
{
|
||||
static Bool setupDone = FALSE;
|
||||
pointer drm = NULL;
|
||||
|
||||
if (!setupDone) {
|
||||
setupDone = TRUE;
|
||||
|
||||
drm =
|
||||
LoadSubModule(module, "drm", NULL, NULL, NULL, NULL, errmaj, errmin);
|
||||
|
||||
if (!drm) {
|
||||
if (errmaj) *errmaj = LDR_NOSUBENT;
|
||||
} else {
|
||||
LoadExtension(&XF86DRIExt, FALSE);
|
||||
}
|
||||
LoadExtension(&XF86DRIExt, FALSE);
|
||||
} else {
|
||||
if (errmaj) *errmaj = LDR_ONCEONLY;
|
||||
}
|
||||
/* Need a non-NULL return value to indicate success */
|
||||
return drm;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
if DRI
|
||||
DRI_SUBDIRS=drm
|
||||
endif
|
||||
|
||||
SUBDIRS = bus @XORG_OS_SUBDIR@ misc $(DRI_SUBDIRS)
|
||||
DIST_SUBDIRS = bsd bus drm misc linux lynxos solaris sysv sco usl hurd
|
||||
|
||||
sdk_HEADERS = xf86_OSproc.h xf86_OSlib.h xf86_ansic.h xf86_libc.h \
|
||||
assyntax.h xf86OSKbd.h xf86OSmouse.h
|
||||
|
||||
EXTRA_DIST = int10Defines.h xf86OSpriv.h README.OS-lib xf86drm.h
|
||||
EXTRA_DIST = int10Defines.h xf86OSpriv.h README.OS-lib
|
||||
|
||||
# to get the grouping semantics right, you have to glom these three together
|
||||
# as one library, otherwise libtool will actively defeat your attempts to
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
libdrm_la_LTLIBRARIES = libdrm.la
|
||||
libdrm_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \
|
||||
-I$(top_srcdir)/hw/xfree86/dri \
|
||||
-I$(top_srcdir)/hw/xfree86/os-support \
|
||||
-I$(top_srcdir)/hw/xfree86/os-support/bus \
|
||||
-I$(top_srcdir)/hw/xfree86/os-suport/shared/drm/kernel \
|
||||
-I$(top_srcdir)/GL/glx \
|
||||
-I$(top_srcdir)/GL/include \
|
||||
-DHAVE_XORG_CONFIG_H \
|
||||
@LIBDRM_CFLAGS@
|
||||
|
||||
libdrm_la_LDFLAGS = -module -avoid-version
|
||||
libdrm_ladir = $(moduledir)/@XORG_OS@
|
||||
libdrm_la_SOURCES = \
|
||||
xf86drm.c \
|
||||
xf86drmHash.c \
|
||||
xf86drmRandom.c \
|
||||
xf86drmSL.c \
|
||||
drmmodule.c
|
|
@ -1,57 +0,0 @@
|
|||
/* drmmodule.c -- Module initialization
|
||||
* Created: Fri Jun 4 09:05:48 1999 by faith@precisioninsight.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_XORG_CONFIG_H
|
||||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#include "xf86Module.h"
|
||||
|
||||
static MODULESETUPPROTO(drmSetup);
|
||||
|
||||
static XF86ModuleVersionInfo VersRec =
|
||||
{
|
||||
"drm",
|
||||
MODULEVENDORSTRING,
|
||||
MODINFOSTRING1,
|
||||
MODINFOSTRING2,
|
||||
XORG_VERSION_CURRENT,
|
||||
1, 0, 0,
|
||||
ABI_CLASS_EXTENSION,
|
||||
ABI_EXTENSION_VERSION,
|
||||
MOD_CLASS_NONE,
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
_X_EXPORT XF86ModuleData drmModuleData = { &VersRec, drmSetup, NULL };
|
||||
|
||||
static pointer
|
||||
drmSetup(pointer module, pointer opts, int *errmaj, int *errmin)
|
||||
{
|
||||
return (void *)1;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,432 +0,0 @@
|
|||
/* xf86drmHash.c -- Small hash table support for integer -> integer mapping
|
||||
* Created: Sun Apr 18 09:35:45 1999 by faith@precisioninsight.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file contains a straightforward implementation of a fixed-sized
|
||||
* hash table using self-organizing linked lists [Knuth73, pp. 398-399] for
|
||||
* collision resolution. There are two potentially interesting things
|
||||
* about this implementation:
|
||||
*
|
||||
* 1) The table is power-of-two sized. Prime sized tables are more
|
||||
* traditional, but do not have a significant advantage over power-of-two
|
||||
* sized table, especially when double hashing is not used for collision
|
||||
* resolution.
|
||||
*
|
||||
* 2) The hash computation uses a table of random integers [Hanson97,
|
||||
* pp. 39-41].
|
||||
*
|
||||
* FUTURE ENHANCEMENTS
|
||||
*
|
||||
* With a table size of 512, the current implementation is sufficient for a
|
||||
* few hundred keys. Since this is well above the expected size of the
|
||||
* tables for which this implementation was designed, the implementation of
|
||||
* dynamic hash tables was postponed until the need arises. A common (and
|
||||
* naive) approach to dynamic hash table implementation simply creates a
|
||||
* new hash table when necessary, rehashes all the data into the new table,
|
||||
* and destroys the old table. The approach in [Larson88] is superior in
|
||||
* two ways: 1) only a portion of the table is expanded when needed,
|
||||
* distributing the expansion cost over several insertions, and 2) portions
|
||||
* of the table can be locked, enabling a scalable thread-safe
|
||||
* implementation.
|
||||
*
|
||||
* REFERENCES
|
||||
*
|
||||
* [Hanson97] David R. Hanson. C Interfaces and Implementations:
|
||||
* Techniques for Creating Reusable Software. Reading, Massachusetts:
|
||||
* Addison-Wesley, 1997.
|
||||
*
|
||||
* [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3:
|
||||
* Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973.
|
||||
*
|
||||
* [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April
|
||||
* 1988, pp. 446-457.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_XORG_CONFIG_H
|
||||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#define HASH_MAIN 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if !HASH_MAIN
|
||||
# include "drm.h"
|
||||
# include "xf86drm.h"
|
||||
# include "xf86.h"
|
||||
#endif
|
||||
|
||||
#define N(x) drm##x
|
||||
|
||||
#define HASH_MAGIC 0xdeadbeef
|
||||
#define HASH_DEBUG 0
|
||||
#define HASH_SIZE 512 /* Good for about 100 entries */
|
||||
/* If you change this value, you probably
|
||||
have to change the HashHash hashing
|
||||
function! */
|
||||
|
||||
#if HASH_MAIN
|
||||
#define HASH_ALLOC malloc
|
||||
#define HASH_FREE free
|
||||
#define HASH_RANDOM_DECL
|
||||
#define HASH_RANDOM_INIT(seed) srandom(seed)
|
||||
#define HASH_RANDOM random()
|
||||
#else
|
||||
#define HASH_ALLOC drmMalloc
|
||||
#define HASH_FREE drmFree
|
||||
#define HASH_RANDOM_DECL void *state
|
||||
#define HASH_RANDOM_INIT(seed) state = drmRandomCreate(seed)
|
||||
#define HASH_RANDOM drmRandom(state)
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct HashBucket {
|
||||
unsigned long key;
|
||||
void *value;
|
||||
struct HashBucket *next;
|
||||
} HashBucket, *HashBucketPtr;
|
||||
|
||||
typedef struct HashTable {
|
||||
unsigned long magic;
|
||||
unsigned long entries;
|
||||
unsigned long hits; /* At top of linked list */
|
||||
unsigned long partials; /* Not at top of linked list */
|
||||
unsigned long misses; /* Not in table */
|
||||
HashBucketPtr buckets[HASH_SIZE];
|
||||
int p0;
|
||||
HashBucketPtr p1;
|
||||
} HashTable, *HashTablePtr;
|
||||
|
||||
#if HASH_MAIN
|
||||
extern void *N(HashCreate)(void);
|
||||
extern int N(HashDestroy)(void *t);
|
||||
extern int N(HashLookup)(void *t, unsigned long key, unsigned long *value);
|
||||
extern int N(HashInsert)(void *t, unsigned long key, unsigned long value);
|
||||
extern int N(HashDelete)(void *t, unsigned long key);
|
||||
#endif
|
||||
|
||||
static unsigned long HashHash(unsigned long key)
|
||||
{
|
||||
unsigned long hash = 0;
|
||||
unsigned long tmp = key;
|
||||
static int init = 0;
|
||||
static unsigned long scatter[256];
|
||||
int i;
|
||||
|
||||
if (!init) {
|
||||
HASH_RANDOM_DECL;
|
||||
HASH_RANDOM_INIT(37);
|
||||
for (i = 0; i < 256; i++) scatter[i] = HASH_RANDOM;
|
||||
++init;
|
||||
}
|
||||
|
||||
while (tmp) {
|
||||
hash = (hash << 1) + scatter[tmp & 0xff];
|
||||
tmp >>= 8;
|
||||
}
|
||||
|
||||
hash %= HASH_SIZE;
|
||||
#if HASH_DEBUG
|
||||
printf( "Hash(%d) = %d\n", key, hash);
|
||||
#endif
|
||||
return hash;
|
||||
}
|
||||
|
||||
void *N(HashCreate)(void)
|
||||
{
|
||||
HashTablePtr table;
|
||||
int i;
|
||||
|
||||
table = HASH_ALLOC(sizeof(*table));
|
||||
if (!table) return NULL;
|
||||
table->magic = HASH_MAGIC;
|
||||
table->entries = 0;
|
||||
table->hits = 0;
|
||||
table->partials = 0;
|
||||
table->misses = 0;
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++) table->buckets[i] = NULL;
|
||||
return table;
|
||||
}
|
||||
|
||||
int N(HashDestroy)(void *t)
|
||||
{
|
||||
HashTablePtr table = (HashTablePtr)t;
|
||||
HashBucketPtr bucket;
|
||||
HashBucketPtr next;
|
||||
int i;
|
||||
|
||||
if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
for (bucket = table->buckets[i]; bucket;) {
|
||||
next = bucket->next;
|
||||
HASH_FREE(bucket);
|
||||
bucket = next;
|
||||
}
|
||||
}
|
||||
HASH_FREE(table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find the bucket and organize the list so that this bucket is at the
|
||||
top. */
|
||||
|
||||
static HashBucketPtr HashFind(HashTablePtr table,
|
||||
unsigned long key, unsigned long *h)
|
||||
{
|
||||
unsigned long hash = HashHash(key);
|
||||
HashBucketPtr prev = NULL;
|
||||
HashBucketPtr bucket;
|
||||
|
||||
if (h) *h = hash;
|
||||
|
||||
for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) {
|
||||
if (bucket->key == key) {
|
||||
if (prev) {
|
||||
/* Organize */
|
||||
prev->next = bucket->next;
|
||||
bucket->next = table->buckets[hash];
|
||||
table->buckets[hash] = bucket;
|
||||
++table->partials;
|
||||
} else {
|
||||
++table->hits;
|
||||
}
|
||||
return bucket;
|
||||
}
|
||||
prev = bucket;
|
||||
}
|
||||
++table->misses;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int N(HashLookup)(void *t, unsigned long key, void **value)
|
||||
{
|
||||
HashTablePtr table = (HashTablePtr)t;
|
||||
HashBucketPtr bucket;
|
||||
|
||||
if (!table || table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
bucket = HashFind(table, key, NULL);
|
||||
if (!bucket) return 1; /* Not found */
|
||||
*value = bucket->value;
|
||||
return 0; /* Found */
|
||||
}
|
||||
|
||||
int N(HashInsert)(void *t, unsigned long key, void *value)
|
||||
{
|
||||
HashTablePtr table = (HashTablePtr)t;
|
||||
HashBucketPtr bucket;
|
||||
unsigned long hash;
|
||||
|
||||
if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
if (HashFind(table, key, &hash)) return 1; /* Already in table */
|
||||
|
||||
bucket = HASH_ALLOC(sizeof(*bucket));
|
||||
if (!bucket) return -1; /* Error */
|
||||
bucket->key = key;
|
||||
bucket->value = value;
|
||||
bucket->next = table->buckets[hash];
|
||||
table->buckets[hash] = bucket;
|
||||
#if HASH_DEBUG
|
||||
printf("Inserted %d at %d/%p\n", key, hash, bucket);
|
||||
#endif
|
||||
return 0; /* Added to table */
|
||||
}
|
||||
|
||||
int N(HashDelete)(void *t, unsigned long key)
|
||||
{
|
||||
HashTablePtr table = (HashTablePtr)t;
|
||||
unsigned long hash;
|
||||
HashBucketPtr bucket;
|
||||
|
||||
if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
bucket = HashFind(table, key, &hash);
|
||||
|
||||
if (!bucket) return 1; /* Not found */
|
||||
|
||||
table->buckets[hash] = bucket->next;
|
||||
HASH_FREE(bucket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int N(HashNext)(void *t, unsigned long *key, void **value)
|
||||
{
|
||||
HashTablePtr table = (HashTablePtr)t;
|
||||
|
||||
for (; table->p0 < HASH_SIZE;
|
||||
++table->p0, table->p1 = table->buckets[table->p0]) {
|
||||
if (table->p1) {
|
||||
*key = table->p1->key;
|
||||
*value = table->p1->value;
|
||||
table->p1 = table->p1->next;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int N(HashFirst)(void *t, unsigned long *key, void **value)
|
||||
{
|
||||
HashTablePtr table = (HashTablePtr)t;
|
||||
|
||||
if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
table->p0 = 0;
|
||||
table->p1 = table->buckets[0];
|
||||
return N(HashNext)(table, key, value);
|
||||
}
|
||||
|
||||
#if HASH_MAIN
|
||||
#define DIST_LIMIT 10
|
||||
static int dist[DIST_LIMIT];
|
||||
|
||||
static void clear_dist(void) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DIST_LIMIT; i++) dist[i] = 0;
|
||||
}
|
||||
|
||||
static int count_entries(HashBucketPtr bucket)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (; bucket; bucket = bucket->next) ++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
static void update_dist(int count)
|
||||
{
|
||||
if (count >= DIST_LIMIT) ++dist[DIST_LIMIT-1];
|
||||
else ++dist[count];
|
||||
}
|
||||
|
||||
static void compute_dist(HashTablePtr table)
|
||||
{
|
||||
int i;
|
||||
HashBucketPtr bucket;
|
||||
|
||||
printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n",
|
||||
table->entries, table->hits, table->partials, table->misses);
|
||||
clear_dist();
|
||||
for (i = 0; i < HASH_SIZE; i++) {
|
||||
bucket = table->buckets[i];
|
||||
update_dist(count_entries(bucket));
|
||||
}
|
||||
for (i = 0; i < DIST_LIMIT; i++) {
|
||||
if (i != DIST_LIMIT-1) printf("%5d %10d\n", i, dist[i]);
|
||||
else printf("other %10d\n", dist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_table(HashTablePtr table,
|
||||
unsigned long key, unsigned long value)
|
||||
{
|
||||
unsigned long retval = 0;
|
||||
int retcode = N(HashLookup)(table, key, &retval);
|
||||
|
||||
switch (retcode) {
|
||||
case -1:
|
||||
printf("Bad magic = 0x%08lx:"
|
||||
" key = %lu, expected = %lu, returned = %lu\n",
|
||||
table->magic, key, value, retval);
|
||||
break;
|
||||
case 1:
|
||||
printf("Not found: key = %lu, expected = %lu returned = %lu\n",
|
||||
key, value, retval);
|
||||
break;
|
||||
case 0:
|
||||
if (value != retval)
|
||||
printf("Bad value: key = %lu, expected = %lu, returned = %lu\n",
|
||||
key, value, retval);
|
||||
break;
|
||||
default:
|
||||
printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n",
|
||||
retcode, key, value, retval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
HashTablePtr table;
|
||||
int i;
|
||||
|
||||
printf("\n***** 256 consecutive integers ****\n");
|
||||
table = N(HashCreate)();
|
||||
for (i = 0; i < 256; i++) N(HashInsert)(table, i, i);
|
||||
for (i = 0; i < 256; i++) check_table(table, i, i);
|
||||
for (i = 256; i >= 0; i--) check_table(table, i, i);
|
||||
compute_dist(table);
|
||||
N(HashDestroy)(table);
|
||||
|
||||
printf("\n***** 1024 consecutive integers ****\n");
|
||||
table = N(HashCreate)();
|
||||
for (i = 0; i < 1024; i++) N(HashInsert)(table, i, i);
|
||||
for (i = 0; i < 1024; i++) check_table(table, i, i);
|
||||
for (i = 1024; i >= 0; i--) check_table(table, i, i);
|
||||
compute_dist(table);
|
||||
N(HashDestroy)(table);
|
||||
|
||||
printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
|
||||
table = N(HashCreate)();
|
||||
for (i = 0; i < 1024; i++) N(HashInsert)(table, i*4096, i);
|
||||
for (i = 0; i < 1024; i++) check_table(table, i*4096, i);
|
||||
for (i = 1024; i >= 0; i--) check_table(table, i*4096, i);
|
||||
compute_dist(table);
|
||||
N(HashDestroy)(table);
|
||||
|
||||
printf("\n***** 1024 random integers ****\n");
|
||||
table = N(HashCreate)();
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++) N(HashInsert)(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++) check_table(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 1024; i++) check_table(table, random(), i);
|
||||
compute_dist(table);
|
||||
N(HashDestroy)(table);
|
||||
|
||||
printf("\n***** 5000 random integers ****\n");
|
||||
table = N(HashCreate)();
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++) N(HashInsert)(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++) check_table(table, random(), i);
|
||||
srandom(0xbeefbeef);
|
||||
for (i = 0; i < 5000; i++) check_table(table, random(), i);
|
||||
compute_dist(table);
|
||||
N(HashDestroy)(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -1,216 +0,0 @@
|
|||
/* xf86drmRandom.c -- "Minimal Standard" PRNG Implementation
|
||||
* Created: Mon Apr 19 08:28:13 1999 by faith@precisioninsight.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file contains a simple, straightforward implementation of the Park
|
||||
* & Miller "Minimal Standard" PRNG [PM88, PMS93], which is a Lehmer
|
||||
* multiplicative linear congruential generator (MLCG) with a period of
|
||||
* 2^31-1.
|
||||
*
|
||||
* This implementation is intended to provide a reliable, portable PRNG
|
||||
* that is suitable for testing a hash table implementation and for
|
||||
* implementing skip lists.
|
||||
*
|
||||
* FUTURE ENHANCEMENTS
|
||||
*
|
||||
* If initial seeds are not selected randomly, two instances of the PRNG
|
||||
* can be correlated. [Knuth81, pp. 32-33] describes a shuffling technique
|
||||
* that can eliminate this problem.
|
||||
*
|
||||
* If PRNGs are used for simulation, the period of the current
|
||||
* implementation may be too short. [LE88] discusses methods of combining
|
||||
* MLCGs to produce much longer periods, and suggests some alternative
|
||||
* values for A and M. [LE90 and Sch92] also provide information on
|
||||
* long-period PRNGs.
|
||||
*
|
||||
* REFERENCES
|
||||
*
|
||||
* [Knuth81] Donald E. Knuth. The Art of Computer Programming. Volume 2:
|
||||
* Seminumerical Algorithms. Reading, Massachusetts: Addison-Wesley, 1981.
|
||||
*
|
||||
* [LE88] Pierre L'Ecuyer. "Efficient and Portable Combined Random Number
|
||||
* Generators". CACM 31(6), June 1988, pp. 742-774.
|
||||
*
|
||||
* [LE90] Pierre L'Ecuyer. "Random Numbers for Simulation". CACM 33(10,
|
||||
* October 1990, pp. 85-97.
|
||||
*
|
||||
* [PM88] Stephen K. Park and Keith W. Miller. "Random Number Generators:
|
||||
* Good Ones are Hard to Find". CACM 31(10), October 1988, pp. 1192-1201.
|
||||
*
|
||||
* [Sch92] Bruce Schneier. "Pseudo-Ransom Sequence Generator for 32-Bit
|
||||
* CPUs". Dr. Dobb's Journal 17(2), February 1992, pp. 34, 37-38, 40.
|
||||
*
|
||||
* [PMS93] Stephen K. Park, Keith W. Miller, and Paul K. Stockmeyer. In
|
||||
* "Technical Correspondence: Remarks on Choosing and Implementing Random
|
||||
* Number Generators". CACM 36(7), July 1993, pp. 105-110.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_XORG_CONFIG_H
|
||||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#define RANDOM_MAIN 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#if !RANDOM_MAIN
|
||||
# include "drm.h"
|
||||
# include "xf86drm.h"
|
||||
# include "xf86.h"
|
||||
#endif
|
||||
|
||||
#define N(x) drm##x
|
||||
|
||||
#define RANDOM_MAGIC 0xfeedbeef
|
||||
#define RANDOM_DEBUG 0
|
||||
|
||||
#if RANDOM_MAIN
|
||||
#define RANDOM_ALLOC malloc
|
||||
#define RANDOM_FREE free
|
||||
#else
|
||||
#define RANDOM_ALLOC drmMalloc
|
||||
#define RANDOM_FREE drmFree
|
||||
#endif
|
||||
|
||||
typedef struct RandomState {
|
||||
unsigned long magic;
|
||||
unsigned long a;
|
||||
unsigned long m;
|
||||
unsigned long q; /* m div a */
|
||||
unsigned long r; /* m mod a */
|
||||
unsigned long check;
|
||||
long seed;
|
||||
} RandomState;
|
||||
|
||||
#if RANDOM_MAIN
|
||||
extern void *N(RandomCreate)(unsigned long seed);
|
||||
extern int N(RandomDestroy)(void *state);
|
||||
extern unsigned long N(Random)(void *state);
|
||||
extern double N(RandomDouble)(void *state);
|
||||
#endif
|
||||
|
||||
void *N(RandomCreate)(unsigned long seed)
|
||||
{
|
||||
RandomState *state;
|
||||
|
||||
state = RANDOM_ALLOC(sizeof(*state));
|
||||
if (!state) return NULL;
|
||||
state->magic = RANDOM_MAGIC;
|
||||
#if 0
|
||||
/* Park & Miller, October 1988 */
|
||||
state->a = 16807;
|
||||
state->m = 2147483647;
|
||||
state->check = 1043618065; /* After 10000 iterations */
|
||||
#else
|
||||
/* Park, Miller, and Stockmeyer, July 1993 */
|
||||
state->a = 48271;
|
||||
state->m = 2147483647;
|
||||
state->check = 399268537; /* After 10000 iterations */
|
||||
#endif
|
||||
state->q = state->m / state->a;
|
||||
state->r = state->m % state->a;
|
||||
|
||||
state->seed = seed;
|
||||
/* Check for illegal boundary conditions,
|
||||
and choose closest legal value. */
|
||||
if (state->seed <= 0) state->seed = 1;
|
||||
if (state->seed >= state->m) state->seed = state->m - 1;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
int N(RandomDestroy)(void *state)
|
||||
{
|
||||
RANDOM_FREE(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long N(Random)(void *state)
|
||||
{
|
||||
RandomState *s = (RandomState *)state;
|
||||
long hi;
|
||||
long lo;
|
||||
|
||||
hi = s->seed / s->q;
|
||||
lo = s->seed % s->q;
|
||||
s->seed = s->a * lo - s->r * hi;
|
||||
if (s->seed <= 0) s->seed += s->m;
|
||||
|
||||
return s->seed;
|
||||
}
|
||||
|
||||
double N(RandomDouble)(void *state)
|
||||
{
|
||||
RandomState *s = (RandomState *)state;
|
||||
|
||||
return (double)N(Random)(state)/(double)s->m;
|
||||
}
|
||||
|
||||
#if RANDOM_MAIN
|
||||
static void check_period(long seed)
|
||||
{
|
||||
unsigned long count = 0;
|
||||
unsigned long initial;
|
||||
void *state;
|
||||
|
||||
state = N(RandomCreate)(seed);
|
||||
initial = N(Random)(state);
|
||||
++count;
|
||||
while (initial != N(Random)(state)) {
|
||||
if (!++count) break;
|
||||
}
|
||||
printf("With seed of %10ld, period = %10lu (0x%08lx)\n",
|
||||
seed, count, count);
|
||||
N(RandomDestroy)(state);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
RandomState *state;
|
||||
int i;
|
||||
unsigned long rand;
|
||||
|
||||
state = N(RandomCreate)(1);
|
||||
for (i = 0; i < 10000; i++) {
|
||||
rand = N(Random)(state);
|
||||
}
|
||||
printf("After 10000 iterations: %lu (%lu expected): %s\n",
|
||||
rand, state->check,
|
||||
rand - state->check ? "*INCORRECT*" : "CORRECT");
|
||||
N(RandomDestroy)(state);
|
||||
|
||||
printf("Checking periods...\n");
|
||||
check_period(1);
|
||||
check_period(2);
|
||||
check_period(31415926);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -1,488 +0,0 @@
|
|||
/* xf86drmSL.c -- Skip list support
|
||||
* Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file contains a straightforward skip list implementation.n
|
||||
*
|
||||
* FUTURE ENHANCEMENTS
|
||||
*
|
||||
* REFERENCES
|
||||
*
|
||||
* [Pugh90] William Pugh. Skip Lists: A Probabilistic Alternative to
|
||||
* Balanced Trees. CACM 33(6), June 1990, pp. 668-676.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_XORG_CONFIG_H
|
||||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#define SL_MAIN 0
|
||||
|
||||
#if SL_MAIN
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
# include "drm.h"
|
||||
# include "xf86drm.h"
|
||||
# include "xf86.h"
|
||||
#endif
|
||||
|
||||
#define N(x) drm##x
|
||||
|
||||
#define SL_LIST_MAGIC 0xfacade00LU
|
||||
#define SL_ENTRY_MAGIC 0x00fab1edLU
|
||||
#define SL_FREED_MAGIC 0xdecea5edLU
|
||||
#define SL_MAX_LEVEL 16
|
||||
#define SL_DEBUG 0
|
||||
#define SL_RANDOM_SEED 0xc01055a1LU
|
||||
|
||||
#if SL_MAIN
|
||||
#define SL_ALLOC malloc
|
||||
#define SL_FREE free
|
||||
#define SL_RANDOM_DECL static int state = 0;
|
||||
#define SL_RANDOM_INIT(seed) if (!state) { srandom(seed); ++state; }
|
||||
#define SL_RANDOM random()
|
||||
#else
|
||||
#define SL_ALLOC drmMalloc
|
||||
#define SL_FREE drmFree
|
||||
#define SL_RANDOM_DECL static void *state = NULL
|
||||
#define SL_RANDOM_INIT(seed) if (!state) state = drmRandomCreate(seed)
|
||||
#define SL_RANDOM drmRandom(state)
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct SLEntry {
|
||||
unsigned long magic; /* SL_ENTRY_MAGIC */
|
||||
unsigned long key;
|
||||
void *value;
|
||||
int levels;
|
||||
struct SLEntry *forward[1]; /* variable sized array */
|
||||
} SLEntry, *SLEntryPtr;
|
||||
|
||||
typedef struct SkipList {
|
||||
unsigned long magic; /* SL_LIST_MAGIC */
|
||||
int level;
|
||||
int count;
|
||||
SLEntryPtr head;
|
||||
SLEntryPtr p0; /* Position for iteration */
|
||||
} SkipList, *SkipListPtr;
|
||||
|
||||
#if SL_MAIN
|
||||
extern void *N(SLCreate)(void);
|
||||
extern int N(SLDestroy)(void *l);
|
||||
extern int N(SLLookup)(void *l, unsigned long key, void **value);
|
||||
extern int N(SLInsert)(void *l, unsigned long key, void *value);
|
||||
extern int N(SLDelete)(void *l, unsigned long key);
|
||||
extern int N(SLNext)(void *l, unsigned long *key, void **value);
|
||||
extern int N(SLFirst)(void *l, unsigned long *key, void **value);
|
||||
extern void N(SLDump)(void *l);
|
||||
extern int N(SLLookupNeighbors)(void *l, unsigned long key,
|
||||
unsigned long *prev_key, void **prev_value,
|
||||
unsigned long *next_key, void **next_value);
|
||||
#endif
|
||||
|
||||
static SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value)
|
||||
{
|
||||
SLEntryPtr entry;
|
||||
|
||||
if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL;
|
||||
|
||||
entry = SL_ALLOC(sizeof(*entry)
|
||||
+ (max_level + 1) * sizeof(entry->forward[0]));
|
||||
if (!entry) return NULL;
|
||||
entry->magic = SL_ENTRY_MAGIC;
|
||||
entry->key = key;
|
||||
entry->value = value;
|
||||
entry->levels = max_level + 1;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static int SLRandomLevel(void)
|
||||
{
|
||||
int level = 1;
|
||||
SL_RANDOM_DECL;
|
||||
|
||||
SL_RANDOM_INIT(SL_RANDOM_SEED);
|
||||
|
||||
while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level;
|
||||
return level;
|
||||
}
|
||||
|
||||
void *N(SLCreate)(void)
|
||||
{
|
||||
SkipListPtr list;
|
||||
int i;
|
||||
|
||||
list = SL_ALLOC(sizeof(*list));
|
||||
if (!list) return NULL;
|
||||
list->magic = SL_LIST_MAGIC;
|
||||
list->level = 0;
|
||||
list->head = SLCreateEntry(SL_MAX_LEVEL, 0, NULL);
|
||||
list->count = 0;
|
||||
|
||||
for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
int N(SLDestroy)(void *l)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
SLEntryPtr entry;
|
||||
SLEntryPtr next;
|
||||
|
||||
if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
for (entry = list->head; entry; entry = next) {
|
||||
if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */
|
||||
next = entry->forward[0];
|
||||
entry->magic = SL_FREED_MAGIC;
|
||||
SL_FREE(entry);
|
||||
}
|
||||
|
||||
list->magic = SL_FREED_MAGIC;
|
||||
SL_FREE(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
SLEntryPtr entry;
|
||||
int i;
|
||||
|
||||
if (list->magic != SL_LIST_MAGIC) return NULL;
|
||||
|
||||
for (i = list->level, entry = list->head; i >= 0; i--) {
|
||||
while (entry->forward[i] && entry->forward[i]->key < key)
|
||||
entry = entry->forward[i];
|
||||
update[i] = entry;
|
||||
}
|
||||
|
||||
return entry->forward[0];
|
||||
}
|
||||
|
||||
int N(SLInsert)(void *l, unsigned long key, void *value)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
SLEntryPtr entry;
|
||||
SLEntryPtr update[SL_MAX_LEVEL + 1];
|
||||
int level;
|
||||
int i;
|
||||
|
||||
if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
entry = SLLocate(list, key, update);
|
||||
|
||||
if (entry && entry->key == key) return 1; /* Already in list */
|
||||
|
||||
|
||||
level = SLRandomLevel();
|
||||
if (level > list->level) {
|
||||
level = ++list->level;
|
||||
update[level] = list->head;
|
||||
}
|
||||
|
||||
entry = SLCreateEntry(level, key, value);
|
||||
|
||||
/* Fix up forward pointers */
|
||||
for (i = 0; i <= level; i++) {
|
||||
entry->forward[i] = update[i]->forward[i];
|
||||
update[i]->forward[i] = entry;
|
||||
}
|
||||
|
||||
++list->count;
|
||||
return 0; /* Added to table */
|
||||
}
|
||||
|
||||
int N(SLDelete)(void *l, unsigned long key)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
SLEntryPtr update[SL_MAX_LEVEL + 1];
|
||||
SLEntryPtr entry;
|
||||
int i;
|
||||
|
||||
if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
entry = SLLocate(list, key, update);
|
||||
|
||||
if (!entry || entry->key != key) return 1; /* Not found */
|
||||
|
||||
/* Fix up forward pointers */
|
||||
for (i = 0; i <= list->level; i++) {
|
||||
if (update[i]->forward[i] == entry)
|
||||
update[i]->forward[i] = entry->forward[i];
|
||||
}
|
||||
|
||||
entry->magic = SL_FREED_MAGIC;
|
||||
SL_FREE(entry);
|
||||
|
||||
while (list->level && !list->head->forward[list->level]) --list->level;
|
||||
--list->count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int N(SLLookup)(void *l, unsigned long key, void **value)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
SLEntryPtr update[SL_MAX_LEVEL + 1];
|
||||
SLEntryPtr entry;
|
||||
|
||||
entry = SLLocate(list, key, update);
|
||||
|
||||
if (entry && entry->key == key) {
|
||||
*value = entry;
|
||||
return 0;
|
||||
}
|
||||
*value = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int N(SLLookupNeighbors)(void *l, unsigned long key,
|
||||
unsigned long *prev_key, void **prev_value,
|
||||
unsigned long *next_key, void **next_value)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
SLEntryPtr update[SL_MAX_LEVEL + 1];
|
||||
SLEntryPtr entry;
|
||||
int retcode = 0;
|
||||
|
||||
entry = SLLocate(list, key, update);
|
||||
|
||||
*prev_key = *next_key = key;
|
||||
*prev_value = *next_value = NULL;
|
||||
|
||||
if (update[0]) {
|
||||
*prev_key = update[0]->key;
|
||||
*prev_value = update[0]->value;
|
||||
++retcode;
|
||||
if (update[0]->forward[0]) {
|
||||
*next_key = update[0]->forward[0]->key;
|
||||
*next_value = update[0]->forward[0]->value;
|
||||
++retcode;
|
||||
}
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
int N(SLNext)(void *l, unsigned long *key, void **value)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
SLEntryPtr entry;
|
||||
|
||||
if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
entry = list->p0;
|
||||
|
||||
if (entry) {
|
||||
list->p0 = entry->forward[0];
|
||||
*key = entry->key;
|
||||
*value = entry->value;
|
||||
return 1;
|
||||
}
|
||||
list->p0 = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int N(SLFirst)(void *l, unsigned long *key, void **value)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
|
||||
if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
|
||||
|
||||
list->p0 = list->head->forward[0];
|
||||
return N(SLNext)(list, key, value);
|
||||
}
|
||||
|
||||
/* Dump internal data structures for debugging. */
|
||||
void N(SLDump)(void *l)
|
||||
{
|
||||
SkipListPtr list = (SkipListPtr)l;
|
||||
SLEntryPtr entry;
|
||||
int i;
|
||||
|
||||
if (list->magic != SL_LIST_MAGIC) {
|
||||
printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
|
||||
list->magic, SL_LIST_MAGIC);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Level = %d, count = %d\n", list->level, list->count);
|
||||
for (entry = list->head; entry; entry = entry->forward[0]) {
|
||||
if (entry->magic != SL_ENTRY_MAGIC) {
|
||||
printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
|
||||
list->magic, SL_ENTRY_MAGIC);
|
||||
}
|
||||
printf("\nEntry %p <0x%08lx, %p> has %2d levels\n",
|
||||
entry, entry->key, entry->value, entry->levels);
|
||||
for (i = 0; i < entry->levels; i++) {
|
||||
if (entry->forward[i]) {
|
||||
printf(" %2d: %p <0x%08lx, %p>\n",
|
||||
i,
|
||||
entry->forward[i],
|
||||
entry->forward[i]->key,
|
||||
entry->forward[i]->value);
|
||||
} else {
|
||||
printf(" %2d: %p\n", i, entry->forward[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SL_MAIN
|
||||
static void print(SkipListPtr list)
|
||||
{
|
||||
unsigned long key;
|
||||
void *value;
|
||||
|
||||
if (N(SLFirst)(list, &key, &value)) {
|
||||
do {
|
||||
printf("key = %5lu, value = %p\n", key, value);
|
||||
} while (N(SLNext)(list, &key, &value));
|
||||
}
|
||||
}
|
||||
|
||||
static double do_time(int size, int iter)
|
||||
{
|
||||
SkipListPtr list;
|
||||
int i, j;
|
||||
unsigned long keys[1000000];
|
||||
unsigned long previous;
|
||||
unsigned long key;
|
||||
void *value;
|
||||
struct timeval start, stop;
|
||||
double usec;
|
||||
SL_RANDOM_DECL;
|
||||
|
||||
SL_RANDOM_INIT(12345);
|
||||
|
||||
list = N(SLCreate)();
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
keys[i] = SL_RANDOM;
|
||||
N(SLInsert)(list, keys[i], NULL);
|
||||
}
|
||||
|
||||
previous = 0;
|
||||
if (N(SLFirst)(list, &key, &value)) {
|
||||
do {
|
||||
if (key <= previous) {
|
||||
printf( "%lu !< %lu\n", previous, key);
|
||||
}
|
||||
previous = key;
|
||||
} while (N(SLNext)(list, &key, &value));
|
||||
}
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
for (j = 0; j < iter; j++) {
|
||||
for (i = 0; i < size; i++) {
|
||||
if (N(SLLookup)(list, keys[i], &value))
|
||||
printf("Error %lu %d\n", keys[i], i);
|
||||
}
|
||||
}
|
||||
gettimeofday(&stop, NULL);
|
||||
|
||||
usec = (double)(stop.tv_sec * 1000000 + stop.tv_usec
|
||||
- start.tv_sec * 1000000 - start.tv_usec) / (size * iter);
|
||||
|
||||
printf("%0.2f microseconds for list length %d\n", usec, size);
|
||||
|
||||
N(SLDestroy)(list);
|
||||
|
||||
return usec;
|
||||
}
|
||||
|
||||
static void print_neighbors(void *list, unsigned long key)
|
||||
{
|
||||
unsigned long prev_key = 0;
|
||||
unsigned long next_key = 0;
|
||||
void *prev_value;
|
||||
void *next_value;
|
||||
int retval;
|
||||
|
||||
retval = drmSLLookupNeighbors(list, key,
|
||||
&prev_key, &prev_value,
|
||||
&next_key, &next_value);
|
||||
printf("Neighbors of %5lu: %d %5lu %5lu\n",
|
||||
key, retval, prev_key, next_key);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
SkipListPtr list;
|
||||
double usec, usec2, usec3, usec4;
|
||||
|
||||
list = N(SLCreate)();
|
||||
printf( "list at %p\n", list);
|
||||
|
||||
print(list);
|
||||
printf("\n==============================\n\n");
|
||||
|
||||
N(SLInsert)(list, 123, NULL);
|
||||
N(SLInsert)(list, 213, NULL);
|
||||
N(SLInsert)(list, 50, NULL);
|
||||
print(list);
|
||||
printf("\n==============================\n\n");
|
||||
|
||||
print_neighbors(list, 0);
|
||||
print_neighbors(list, 50);
|
||||
print_neighbors(list, 51);
|
||||
print_neighbors(list, 123);
|
||||
print_neighbors(list, 200);
|
||||
print_neighbors(list, 213);
|
||||
print_neighbors(list, 256);
|
||||
printf("\n==============================\n\n");
|
||||
|
||||
N(SLDelete)(list, 50);
|
||||
print(list);
|
||||
printf("\n==============================\n\n");
|
||||
|
||||
N(SLDump)(list);
|
||||
N(SLDestroy)(list);
|
||||
printf("\n==============================\n\n");
|
||||
|
||||
usec = do_time(100, 10000);
|
||||
usec2 = do_time(1000, 500);
|
||||
printf("Table size increased by %0.2f, search time increased by %0.2f\n",
|
||||
1000.0/100.0, usec2 / usec);
|
||||
|
||||
usec3 = do_time(10000, 50);
|
||||
printf("Table size increased by %0.2f, search time increased by %0.2f\n",
|
||||
10000.0/100.0, usec3 / usec);
|
||||
|
||||
usec4 = do_time(100000, 4);
|
||||
printf("Table size increased by %0.2f, search time increased by %0.2f\n",
|
||||
100000.0/100.0, usec4 / usec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -1,637 +0,0 @@
|
|||
/**
|
||||
* \file xf86drm.h
|
||||
* OS-independent header for DRM user-level library interface.
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _XF86DRM_H_
|
||||
#define _XF86DRM_H_
|
||||
|
||||
#include <drm.h>
|
||||
|
||||
/* Defaults, if nothing set in xf86config */
|
||||
#define DRM_DEV_UID 0
|
||||
#define DRM_DEV_GID 0
|
||||
/* Default /dev/dri directory permissions 0755 */
|
||||
#define DRM_DEV_DIRMODE \
|
||||
(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
|
||||
#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
|
||||
|
||||
#define DRM_DIR_NAME "/dev/dri"
|
||||
#define DRM_DEV_NAME "%s/card%d"
|
||||
#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
|
||||
|
||||
#define DRM_ERR_NO_DEVICE (-1001)
|
||||
#define DRM_ERR_NO_ACCESS (-1002)
|
||||
#define DRM_ERR_NOT_ROOT (-1003)
|
||||
#define DRM_ERR_INVALID (-1004)
|
||||
#define DRM_ERR_NO_FD (-1005)
|
||||
|
||||
#define DRM_AGP_NO_HANDLE 0
|
||||
|
||||
typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */
|
||||
typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */
|
||||
|
||||
/**
|
||||
* Driver version information.
|
||||
*
|
||||
* \sa drmGetVersion() and drmSetVersion().
|
||||
*/
|
||||
typedef struct _drmVersion {
|
||||
int version_major; /**< Major version */
|
||||
int version_minor; /**< Minor version */
|
||||
int version_patchlevel; /**< Patch level */
|
||||
int name_len; /**< Length of name buffer */
|
||||
char *name; /**< Name of driver */
|
||||
int date_len; /**< Length of date buffer */
|
||||
char *date; /**< User-space buffer to hold date */
|
||||
int desc_len; /**< Length of desc buffer */
|
||||
char *desc; /**< User-space buffer to hold desc */
|
||||
} drmVersion, *drmVersionPtr;
|
||||
|
||||
typedef struct _drmStats {
|
||||
unsigned long count; /**< Number of data */
|
||||
struct {
|
||||
unsigned long value; /**< Value from kernel */
|
||||
const char *long_format; /**< Suggested format for long_name */
|
||||
const char *long_name; /**< Long name for value */
|
||||
const char *rate_format; /**< Suggested format for rate_name */
|
||||
const char *rate_name; /**< Short name for value per second */
|
||||
int isvalue; /**< True if value (vs. counter) */
|
||||
const char *mult_names; /**< Multiplier names (e.g., "KGM") */
|
||||
int mult; /**< Multiplier value (e.g., 1024) */
|
||||
int verbose; /**< Suggest only in verbose output */
|
||||
} data[15];
|
||||
} drmStatsT;
|
||||
|
||||
|
||||
/* All of these enums *MUST* match with the
|
||||
kernel implementation -- so do *NOT*
|
||||
change them! (The drmlib implementation
|
||||
will just copy the flags instead of
|
||||
translating them.) */
|
||||
typedef enum {
|
||||
DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */
|
||||
DRM_REGISTERS = 1, /**< no caching, no core dump */
|
||||
DRM_SHM = 2, /**< shared, cached */
|
||||
DRM_AGP = 3, /**< AGP/GART */
|
||||
DRM_SCATTER_GATHER = 4, /**< PCI scatter/gather */
|
||||
DRM_CONSISTENT = 5 /**< PCI consistent */
|
||||
} drmMapType;
|
||||
|
||||
typedef enum {
|
||||
DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */
|
||||
DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */
|
||||
DRM_LOCKED = 0x0004, /**< Physical pages locked */
|
||||
DRM_KERNEL = 0x0008, /**< Kernel requires access */
|
||||
DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */
|
||||
DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */
|
||||
DRM_REMOVABLE = 0x0040 /**< Removable mapping */
|
||||
} drmMapFlags;
|
||||
|
||||
/**
|
||||
* \warning These values *MUST* match drm.h
|
||||
*/
|
||||
typedef enum {
|
||||
/** \name Flags for DMA buffer dispatch */
|
||||
/*@{*/
|
||||
DRM_DMA_BLOCK = 0x01, /**<
|
||||
* Block until buffer dispatched.
|
||||
*
|
||||
* \note the buffer may not yet have been
|
||||
* processed by the hardware -- getting a
|
||||
* hardware lock with the hardware quiescent
|
||||
* will ensure that the buffer has been
|
||||
* processed.
|
||||
*/
|
||||
DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
|
||||
DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
|
||||
/*@}*/
|
||||
|
||||
/** \name Flags for DMA buffer request */
|
||||
/*@{*/
|
||||
DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
|
||||
DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
|
||||
DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
|
||||
/*@}*/
|
||||
} drmDMAFlags;
|
||||
|
||||
typedef enum {
|
||||
DRM_PAGE_ALIGN = 0x01,
|
||||
DRM_AGP_BUFFER = 0x02,
|
||||
DRM_SG_BUFFER = 0x04,
|
||||
DRM_FB_BUFFER = 0x08
|
||||
} drmBufDescFlags;
|
||||
|
||||
typedef enum {
|
||||
DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
|
||||
DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
|
||||
DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
|
||||
DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
|
||||
/* These *HALT* flags aren't supported yet
|
||||
-- they will be used to support the
|
||||
full-screen DGA-like mode. */
|
||||
DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
|
||||
DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
|
||||
} drmLockFlags;
|
||||
|
||||
typedef enum {
|
||||
DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and
|
||||
never swapped. */
|
||||
DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */
|
||||
} drm_context_tFlags, *drm_context_tFlagsPtr;
|
||||
|
||||
typedef struct _drmBufDesc {
|
||||
int count; /**< Number of buffers of this size */
|
||||
int size; /**< Size in bytes */
|
||||
int low_mark; /**< Low water mark */
|
||||
int high_mark; /**< High water mark */
|
||||
} drmBufDesc, *drmBufDescPtr;
|
||||
|
||||
typedef struct _drmBufInfo {
|
||||
int count; /**< Number of buffers described in list */
|
||||
drmBufDescPtr list; /**< List of buffer descriptions */
|
||||
} drmBufInfo, *drmBufInfoPtr;
|
||||
|
||||
typedef struct _drmBuf {
|
||||
int idx; /**< Index into the master buffer list */
|
||||
int total; /**< Buffer size */
|
||||
int used; /**< Amount of buffer in use (for DMA) */
|
||||
drmAddress address; /**< Address */
|
||||
} drmBuf, *drmBufPtr;
|
||||
|
||||
/**
|
||||
* Buffer mapping information.
|
||||
*
|
||||
* Used by drmMapBufs() and drmUnmapBufs() to store information about the
|
||||
* mapped buffers.
|
||||
*/
|
||||
typedef struct _drmBufMap {
|
||||
int count; /**< Number of buffers mapped */
|
||||
drmBufPtr list; /**< Buffers */
|
||||
} drmBufMap, *drmBufMapPtr;
|
||||
|
||||
typedef struct _drmLock {
|
||||
volatile unsigned int lock;
|
||||
char padding[60];
|
||||
/* This is big enough for most current (and future?) architectures:
|
||||
DEC Alpha: 32 bytes
|
||||
Intel Merced: ?
|
||||
Intel P5/PPro/PII/PIII: 32 bytes
|
||||
Intel StrongARM: 32 bytes
|
||||
Intel i386/i486: 16 bytes
|
||||
MIPS: 32 bytes (?)
|
||||
Motorola 68k: 16 bytes
|
||||
Motorola PowerPC: 32 bytes
|
||||
Sun SPARC: 32 bytes
|
||||
*/
|
||||
} drmLock, *drmLockPtr;
|
||||
|
||||
/**
|
||||
* Indices here refer to the offset into
|
||||
* list in drmBufInfo
|
||||
*/
|
||||
typedef struct _drmDMAReq {
|
||||
drm_context_t context; /**< Context handle */
|
||||
int send_count; /**< Number of buffers to send */
|
||||
int *send_list; /**< List of handles to buffers */
|
||||
int *send_sizes; /**< Lengths of data to send, in bytes */
|
||||
drmDMAFlags flags; /**< Flags */
|
||||
int request_count; /**< Number of buffers requested */
|
||||
int request_size; /**< Desired size of buffers requested */
|
||||
int *request_list; /**< Buffer information */
|
||||
int *request_sizes; /**< Minimum acceptable sizes */
|
||||
int granted_count; /**< Number of buffers granted at this size */
|
||||
} drmDMAReq, *drmDMAReqPtr;
|
||||
|
||||
typedef struct _drmRegion {
|
||||
drm_handle_t handle;
|
||||
unsigned int offset;
|
||||
drmSize size;
|
||||
drmAddress map;
|
||||
} drmRegion, *drmRegionPtr;
|
||||
|
||||
typedef struct _drmTextureRegion {
|
||||
unsigned char next;
|
||||
unsigned char prev;
|
||||
unsigned char in_use;
|
||||
unsigned char padding; /**< Explicitly pad this out */
|
||||
unsigned int age;
|
||||
} drmTextureRegion, *drmTextureRegionPtr;
|
||||
|
||||
|
||||
typedef enum {
|
||||
DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
|
||||
DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
|
||||
DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */
|
||||
} drmVBlankSeqType;
|
||||
|
||||
typedef struct _drmVBlankReq {
|
||||
drmVBlankSeqType type;
|
||||
unsigned int sequence;
|
||||
unsigned long signal;
|
||||
} drmVBlankReq, *drmVBlankReqPtr;
|
||||
|
||||
typedef struct _drmVBlankReply {
|
||||
drmVBlankSeqType type;
|
||||
unsigned int sequence;
|
||||
long tval_sec;
|
||||
long tval_usec;
|
||||
} drmVBlankReply, *drmVBlankReplyPtr;
|
||||
|
||||
typedef union _drmVBlank {
|
||||
drmVBlankReq request;
|
||||
drmVBlankReply reply;
|
||||
} drmVBlank, *drmVBlankPtr;
|
||||
|
||||
typedef struct _drmSetVersion {
|
||||
int drm_di_major;
|
||||
int drm_di_minor;
|
||||
int drm_dd_major;
|
||||
int drm_dd_minor;
|
||||
} drmSetVersion, *drmSetVersionPtr;
|
||||
|
||||
|
||||
#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)
|
||||
|
||||
#define DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */
|
||||
#define DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 2)
|
||||
# if defined(__i386) || defined(__AMD64__) || defined(__x86_64__) || defined(__amd64__)
|
||||
/* Reflect changes here to drmP.h */
|
||||
#define DRM_CAS(lock,old,new,__ret) \
|
||||
do { \
|
||||
int __dummy; /* Can't mark eax as clobbered */ \
|
||||
__asm__ __volatile__( \
|
||||
"lock ; cmpxchg %4,%1\n\t" \
|
||||
"setnz %0" \
|
||||
: "=d" (__ret), \
|
||||
"=m" (__drm_dummy_lock(lock)), \
|
||||
"=a" (__dummy) \
|
||||
: "2" (old), \
|
||||
"r" (new)); \
|
||||
} while (0)
|
||||
|
||||
#elif defined(__alpha__)
|
||||
|
||||
#define DRM_CAS(lock, old, new, ret) \
|
||||
do { \
|
||||
int old32; \
|
||||
int cur32; \
|
||||
__asm__ __volatile__( \
|
||||
" mb\n" \
|
||||
" zap %4, 0xF0, %0\n" \
|
||||
" ldl_l %1, %2\n" \
|
||||
" zap %1, 0xF0, %1\n" \
|
||||
" cmpeq %0, %1, %1\n" \
|
||||
" beq %1, 1f\n" \
|
||||
" bis %5, %5, %1\n" \
|
||||
" stl_c %1, %2\n" \
|
||||
"1: xor %1, 1, %1\n" \
|
||||
" stl %1, %3" \
|
||||
: "=r" (old32), \
|
||||
"=&r" (cur32), \
|
||||
"=m" (__drm_dummy_lock(lock)),\
|
||||
"=m" (ret) \
|
||||
: "r" (old), \
|
||||
"r" (new)); \
|
||||
} while(0)
|
||||
|
||||
#elif defined(__sparc__)
|
||||
|
||||
#define DRM_CAS(lock,old,new,__ret) \
|
||||
do { register unsigned int __old __asm("o0"); \
|
||||
register unsigned int __new __asm("o1"); \
|
||||
register volatile unsigned int *__lock __asm("o2"); \
|
||||
__old = old; \
|
||||
__new = new; \
|
||||
__lock = (volatile unsigned int *)lock; \
|
||||
__asm__ __volatile__( \
|
||||
/*"cas [%2], %3, %0"*/ \
|
||||
".word 0xd3e29008\n\t" \
|
||||
/*"membar #StoreStore | #StoreLoad"*/ \
|
||||
".word 0x8143e00a" \
|
||||
: "=&r" (__new) \
|
||||
: "0" (__new), \
|
||||
"r" (__lock), \
|
||||
"r" (__old) \
|
||||
: "memory"); \
|
||||
__ret = (__new != __old); \
|
||||
} while(0)
|
||||
|
||||
#elif defined(__ia64__)
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
/* this currently generates bad code (missing stop bits)... */
|
||||
#include <ia64intrin.h>
|
||||
|
||||
#define DRM_CAS(lock,old,new,__ret) \
|
||||
do { \
|
||||
unsigned long __result, __old = (old) & 0xffffffff; \
|
||||
__mf(); \
|
||||
__result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\
|
||||
__ret = (__result) != (__old); \
|
||||
/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \
|
||||
(old), (new)) \
|
||||
!= (old)); */\
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define DRM_CAS(lock,old,new,__ret) \
|
||||
do { \
|
||||
unsigned int __result, __old = (old); \
|
||||
__asm__ __volatile__( \
|
||||
"mf\n" \
|
||||
"mov ar.ccv=%2\n" \
|
||||
";;\n" \
|
||||
"cmpxchg4.acq %0=%1,%3,ar.ccv" \
|
||||
: "=r" (__result), "=m" (__drm_dummy_lock(lock)) \
|
||||
: "r" ((unsigned long)__old), "r" (new) \
|
||||
: "memory"); \
|
||||
__ret = (__result) != (__old); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(__powerpc__)
|
||||
|
||||
#define DRM_CAS(lock,old,new,__ret) \
|
||||
do { \
|
||||
__asm__ __volatile__( \
|
||||
"sync;" \
|
||||
"0: lwarx %0,0,%1;" \
|
||||
" xor. %0,%3,%0;" \
|
||||
" bne 1f;" \
|
||||
" stwcx. %2,0,%1;" \
|
||||
" bne- 0b;" \
|
||||
"1: " \
|
||||
"sync;" \
|
||||
: "=&r"(__ret) \
|
||||
: "r"(lock), "r"(new), "r"(old) \
|
||||
: "cr0", "memory"); \
|
||||
} while (0)
|
||||
|
||||
#endif /* architecture */
|
||||
#endif /* __GNUC__ >= 2 */
|
||||
|
||||
#ifndef DRM_CAS
|
||||
#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
|
||||
#endif
|
||||
|
||||
#if defined(__alpha__) || defined(__powerpc__)
|
||||
#define DRM_CAS_RESULT(_result) int _result
|
||||
#else
|
||||
#define DRM_CAS_RESULT(_result) char _result
|
||||
#endif
|
||||
|
||||
#define DRM_LIGHT_LOCK(fd,lock,context) \
|
||||
do { \
|
||||
DRM_CAS_RESULT(__ret); \
|
||||
DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
|
||||
if (__ret) drmGetLock(fd,context,0); \
|
||||
} while(0)
|
||||
|
||||
/* This one counts fast locks -- for
|
||||
benchmarking only. */
|
||||
#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \
|
||||
do { \
|
||||
DRM_CAS_RESULT(__ret); \
|
||||
DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
|
||||
if (__ret) drmGetLock(fd,context,0); \
|
||||
else ++count; \
|
||||
} while(0)
|
||||
|
||||
#define DRM_LOCK(fd,lock,context,flags) \
|
||||
do { \
|
||||
if (flags) drmGetLock(fd,context,flags); \
|
||||
else DRM_LIGHT_LOCK(fd,lock,context); \
|
||||
} while(0)
|
||||
|
||||
#define DRM_UNLOCK(fd,lock,context) \
|
||||
do { \
|
||||
DRM_CAS_RESULT(__ret); \
|
||||
DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \
|
||||
if (__ret) drmUnlock(fd,context); \
|
||||
} while(0)
|
||||
|
||||
/* Simple spin locks */
|
||||
#define DRM_SPINLOCK(spin,val) \
|
||||
do { \
|
||||
DRM_CAS_RESULT(__ret); \
|
||||
do { \
|
||||
DRM_CAS(spin,0,val,__ret); \
|
||||
if (__ret) while ((spin)->lock); \
|
||||
} while (__ret); \
|
||||
} while(0)
|
||||
|
||||
#define DRM_SPINLOCK_TAKE(spin,val) \
|
||||
do { \
|
||||
DRM_CAS_RESULT(__ret); \
|
||||
int cur; \
|
||||
do { \
|
||||
cur = (*spin).lock; \
|
||||
DRM_CAS(spin,cur,val,__ret); \
|
||||
} while (__ret); \
|
||||
} while(0)
|
||||
|
||||
#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \
|
||||
do { \
|
||||
int __i; \
|
||||
__ret = 1; \
|
||||
for (__i = 0; __ret && __i < count; __i++) { \
|
||||
DRM_CAS(spin,0,val,__ret); \
|
||||
if (__ret) for (;__i < count && (spin)->lock; __i++); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define DRM_SPINUNLOCK(spin,val) \
|
||||
do { \
|
||||
DRM_CAS_RESULT(__ret); \
|
||||
if ((*spin).lock == val) { /* else server stole lock */ \
|
||||
do { \
|
||||
DRM_CAS(spin,val,0,__ret); \
|
||||
} while (__ret); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* General user-level programmer's API: unprivileged */
|
||||
extern int drmAvailable(void);
|
||||
extern int drmOpen(const char *name, const char *busid);
|
||||
extern int drmClose(int fd);
|
||||
extern drmVersionPtr drmGetVersion(int fd);
|
||||
extern drmVersionPtr drmGetLibVersion(int fd);
|
||||
extern void drmFreeVersion(drmVersionPtr);
|
||||
extern int drmGetMagic(int fd, drm_magic_t * magic);
|
||||
extern char *drmGetBusid(int fd);
|
||||
extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum,
|
||||
int funcnum);
|
||||
extern int drmGetMap(int fd, int idx, drm_handle_t *offset,
|
||||
drmSize *size, drmMapType *type,
|
||||
drmMapFlags *flags, drm_handle_t *handle,
|
||||
int *mtrr);
|
||||
extern int drmGetClient(int fd, int idx, int *auth, int *pid,
|
||||
int *uid, unsigned long *magic,
|
||||
unsigned long *iocs);
|
||||
extern int drmGetStats(int fd, drmStatsT *stats);
|
||||
extern int drmSetInterfaceVersion(int fd, drmSetVersion *version);
|
||||
extern int drmCommandNone(int fd, unsigned long drmCommandIndex);
|
||||
extern int drmCommandRead(int fd, unsigned long drmCommandIndex,
|
||||
void *data, unsigned long size);
|
||||
extern int drmCommandWrite(int fd, unsigned long drmCommandIndex,
|
||||
void *data, unsigned long size);
|
||||
extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
|
||||
void *data, unsigned long size);
|
||||
|
||||
/* General user-level programmer's API: X server (root) only */
|
||||
extern void drmFreeBusid(const char *busid);
|
||||
extern int drmSetBusid(int fd, const char *busid);
|
||||
extern int drmAuthMagic(int fd, drm_magic_t magic);
|
||||
extern int drmAddMap(int fd,
|
||||
drm_handle_t offset,
|
||||
drmSize size,
|
||||
drmMapType type,
|
||||
drmMapFlags flags,
|
||||
drm_handle_t * handle);
|
||||
extern int drmRmMap(int fd, drm_handle_t handle);
|
||||
extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
|
||||
drm_handle_t handle);
|
||||
|
||||
extern int drmAddBufs(int fd, int count, int size,
|
||||
drmBufDescFlags flags,
|
||||
int agp_offset);
|
||||
extern int drmMarkBufs(int fd, double low, double high);
|
||||
extern int drmCreateContext(int fd, drm_context_t * handle);
|
||||
extern int drmSetContextFlags(int fd, drm_context_t context,
|
||||
drm_context_tFlags flags);
|
||||
extern int drmGetContextFlags(int fd, drm_context_t context,
|
||||
drm_context_tFlagsPtr flags);
|
||||
extern int drmAddContextTag(int fd, drm_context_t context, void *tag);
|
||||
extern int drmDelContextTag(int fd, drm_context_t context);
|
||||
extern void *drmGetContextTag(int fd, drm_context_t context);
|
||||
extern drm_context_t * drmGetReservedContextList(int fd, int *count);
|
||||
extern void drmFreeReservedContextList(drm_context_t *);
|
||||
extern int drmSwitchToContext(int fd, drm_context_t context);
|
||||
extern int drmDestroyContext(int fd, drm_context_t handle);
|
||||
extern int drmCreateDrawable(int fd, drm_drawable_t * handle);
|
||||
extern int drmDestroyDrawable(int fd, drm_drawable_t handle);
|
||||
extern int drmCtlInstHandler(int fd, int irq);
|
||||
extern int drmCtlUninstHandler(int fd);
|
||||
extern int drmInstallSIGIOHandler(int fd,
|
||||
void (*f)(int fd,
|
||||
void *oldctx,
|
||||
void *newctx));
|
||||
extern int drmRemoveSIGIOHandler(int fd);
|
||||
|
||||
/* General user-level programmer's API: authenticated client and/or X */
|
||||
extern int drmMap(int fd,
|
||||
drm_handle_t handle,
|
||||
drmSize size,
|
||||
drmAddressPtr address);
|
||||
extern int drmUnmap(drmAddress address, drmSize size);
|
||||
extern drmBufInfoPtr drmGetBufInfo(int fd);
|
||||
extern drmBufMapPtr drmMapBufs(int fd);
|
||||
extern int drmUnmapBufs(drmBufMapPtr bufs);
|
||||
extern int drmDMA(int fd, drmDMAReqPtr request);
|
||||
extern int drmFreeBufs(int fd, int count, int *list);
|
||||
extern int drmGetLock(int fd,
|
||||
drm_context_t context,
|
||||
drmLockFlags flags);
|
||||
extern int drmUnlock(int fd, drm_context_t context);
|
||||
extern int drmFinish(int fd, int context, drmLockFlags flags);
|
||||
extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
|
||||
drm_handle_t * handle);
|
||||
|
||||
/* AGP/GART support: X server (root) only */
|
||||
extern int drmAgpAcquire(int fd);
|
||||
extern int drmAgpRelease(int fd);
|
||||
extern int drmAgpEnable(int fd, unsigned long mode);
|
||||
extern int drmAgpAlloc(int fd, unsigned long size,
|
||||
unsigned long type, unsigned long *address,
|
||||
drm_handle_t *handle);
|
||||
extern int drmAgpFree(int fd, drm_handle_t handle);
|
||||
extern int drmAgpBind(int fd, drm_handle_t handle,
|
||||
unsigned long offset);
|
||||
extern int drmAgpUnbind(int fd, drm_handle_t handle);
|
||||
|
||||
/* AGP/GART info: authenticated client and/or X */
|
||||
extern int drmAgpVersionMajor(int fd);
|
||||
extern int drmAgpVersionMinor(int fd);
|
||||
extern unsigned long drmAgpGetMode(int fd);
|
||||
extern unsigned long drmAgpBase(int fd); /* Physical location */
|
||||
extern unsigned long drmAgpSize(int fd); /* Bytes */
|
||||
extern unsigned long drmAgpMemoryUsed(int fd);
|
||||
extern unsigned long drmAgpMemoryAvail(int fd);
|
||||
extern unsigned int drmAgpVendorId(int fd);
|
||||
extern unsigned int drmAgpDeviceId(int fd);
|
||||
|
||||
/* PCI scatter/gather support: X server (root) only */
|
||||
extern int drmScatterGatherAlloc(int fd, unsigned long size,
|
||||
drm_handle_t *handle);
|
||||
extern int drmScatterGatherFree(int fd, drm_handle_t handle);
|
||||
|
||||
extern int drmWaitVBlank(int fd, drmVBlankPtr vbl);
|
||||
|
||||
/* Support routines */
|
||||
extern int drmError(int err, const char *label);
|
||||
extern void *drmMalloc(int size);
|
||||
extern void drmFree(void *pt);
|
||||
|
||||
/* Hash table routines */
|
||||
extern void *drmHashCreate(void);
|
||||
extern int drmHashDestroy(void *t);
|
||||
extern int drmHashLookup(void *t, unsigned long key, void **value);
|
||||
extern int drmHashInsert(void *t, unsigned long key, void *value);
|
||||
extern int drmHashDelete(void *t, unsigned long key);
|
||||
extern int drmHashFirst(void *t, unsigned long *key, void **value);
|
||||
extern int drmHashNext(void *t, unsigned long *key, void **value);
|
||||
|
||||
/* PRNG routines */
|
||||
extern void *drmRandomCreate(unsigned long seed);
|
||||
extern int drmRandomDestroy(void *state);
|
||||
extern unsigned long drmRandom(void *state);
|
||||
extern double drmRandomDouble(void *state);
|
||||
|
||||
/* Skip list routines */
|
||||
|
||||
extern void *drmSLCreate(void);
|
||||
extern int drmSLDestroy(void *l);
|
||||
extern int drmSLLookup(void *l, unsigned long key, void **value);
|
||||
extern int drmSLInsert(void *l, unsigned long key, void *value);
|
||||
extern int drmSLDelete(void *l, unsigned long key);
|
||||
extern int drmSLNext(void *l, unsigned long *key, void **value);
|
||||
extern int drmSLFirst(void *l, unsigned long *key, void **value);
|
||||
extern void drmSLDump(void *l);
|
||||
extern int drmSLLookupNeighbors(void *l, unsigned long key,
|
||||
unsigned long *prev_key, void **prev_value,
|
||||
unsigned long *next_key, void **next_value);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user