122944501Smrg/* xf86drmSL.c -- Skip list support
222944501Smrg * Created: Mon May 10 09:28:13 1999 by faith@precisioninsight.com
322944501Smrg *
422944501Smrg * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
522944501Smrg * All Rights Reserved.
622944501Smrg *
722944501Smrg * Permission is hereby granted, free of charge, to any person obtaining a
822944501Smrg * copy of this software and associated documentation files (the "Software"),
922944501Smrg * to deal in the Software without restriction, including without limitation
1022944501Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1122944501Smrg * and/or sell copies of the Software, and to permit persons to whom the
1222944501Smrg * Software is furnished to do so, subject to the following conditions:
1322944501Smrg *
1422944501Smrg * The above copyright notice and this permission notice (including the next
1522944501Smrg * paragraph) shall be included in all copies or substantial portions of the
1622944501Smrg * Software.
1722944501Smrg *
1822944501Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1922944501Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2022944501Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2122944501Smrg * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2222944501Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2322944501Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2422944501Smrg * DEALINGS IN THE SOFTWARE.
2522944501Smrg *
2622944501Smrg * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
2722944501Smrg *
2822944501Smrg * DESCRIPTION
2922944501Smrg *
3022944501Smrg * This file contains a straightforward skip list implementation.n
3122944501Smrg *
3222944501Smrg * FUTURE ENHANCEMENTS
3322944501Smrg *
3422944501Smrg * REFERENCES
3522944501Smrg *
3622944501Smrg * [Pugh90] William Pugh.  Skip Lists: A Probabilistic Alternative to
3722944501Smrg * Balanced Trees. CACM 33(6), June 1990, pp. 668-676.
3822944501Smrg *
3922944501Smrg */
4022944501Smrg
4122944501Smrg#include <stdio.h>
4222944501Smrg#include <stdlib.h>
4322944501Smrg
447cdc0497Smrg#include "libdrm_macros.h"
45e6188e58Smrg#include "xf86drm.h"
4622944501Smrg
4722944501Smrg#define SL_LIST_MAGIC  0xfacade00LU
4822944501Smrg#define SL_ENTRY_MAGIC 0x00fab1edLU
4922944501Smrg#define SL_FREED_MAGIC 0xdecea5edLU
5022944501Smrg#define SL_MAX_LEVEL   16
5122944501Smrg#define SL_RANDOM_SEED 0xc01055a1LU
5222944501Smrg
5322944501Smrg#define SL_RANDOM_DECL        static void *state = NULL
5422944501Smrg#define SL_RANDOM_INIT(seed)  if (!state) state = drmRandomCreate(seed)
5522944501Smrg#define SL_RANDOM             drmRandom(state)
5622944501Smrg
5722944501Smrgtypedef struct SLEntry {
5822944501Smrg    unsigned long     magic;	   /* SL_ENTRY_MAGIC */
5922944501Smrg    unsigned long     key;
6022944501Smrg    void              *value;
6122944501Smrg    int               levels;
6222944501Smrg    struct SLEntry    *forward[1]; /* variable sized array */
6322944501Smrg} SLEntry, *SLEntryPtr;
6422944501Smrg
6522944501Smrgtypedef struct SkipList {
6622944501Smrg    unsigned long    magic;	/* SL_LIST_MAGIC */
6722944501Smrg    int              level;
6822944501Smrg    int              count;
6922944501Smrg    SLEntryPtr       head;
7022944501Smrg    SLEntryPtr       p0;	/* Position for iteration */
7122944501Smrg} SkipList, *SkipListPtr;
7222944501Smrg
7322944501Smrgstatic SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value)
7422944501Smrg{
7522944501Smrg    SLEntryPtr entry;
7622944501Smrg
7722944501Smrg    if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL;
7822944501Smrg
79e6188e58Smrg    entry         = drmMalloc(sizeof(*entry)
8022944501Smrg			     + (max_level + 1) * sizeof(entry->forward[0]));
8122944501Smrg    if (!entry) return NULL;
8222944501Smrg    entry->magic  = SL_ENTRY_MAGIC;
8322944501Smrg    entry->key    = key;
8422944501Smrg    entry->value  = value;
8522944501Smrg    entry->levels = max_level + 1;
8622944501Smrg
8722944501Smrg    return entry;
8822944501Smrg}
8922944501Smrg
9022944501Smrgstatic int SLRandomLevel(void)
9122944501Smrg{
9222944501Smrg    int level = 1;
9322944501Smrg    SL_RANDOM_DECL;
9422944501Smrg
9522944501Smrg    SL_RANDOM_INIT(SL_RANDOM_SEED);
9622944501Smrg
9722944501Smrg    while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level;
9822944501Smrg    return level;
9922944501Smrg}
10022944501Smrg
1017cdc0497Smrgdrm_public void *drmSLCreate(void)
10222944501Smrg{
10322944501Smrg    SkipListPtr  list;
10422944501Smrg    int          i;
10522944501Smrg
106e6188e58Smrg    list           = drmMalloc(sizeof(*list));
10722944501Smrg    if (!list) return NULL;
10822944501Smrg    list->magic    = SL_LIST_MAGIC;
10922944501Smrg    list->level    = 0;
11022944501Smrg    list->head     = SLCreateEntry(SL_MAX_LEVEL, 0, NULL);
11122944501Smrg    list->count    = 0;
11222944501Smrg
11322944501Smrg    for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL;
11422944501Smrg
11522944501Smrg    return list;
11622944501Smrg}
11722944501Smrg
1187cdc0497Smrgdrm_public int drmSLDestroy(void *l)
11922944501Smrg{
12022944501Smrg    SkipListPtr   list  = (SkipListPtr)l;
12122944501Smrg    SLEntryPtr    entry;
12222944501Smrg    SLEntryPtr    next;
12322944501Smrg
12422944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
12522944501Smrg
12622944501Smrg    for (entry = list->head; entry; entry = next) {
12722944501Smrg	if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */
12822944501Smrg	next         = entry->forward[0];
12922944501Smrg	entry->magic = SL_FREED_MAGIC;
130e6188e58Smrg	drmFree(entry);
13122944501Smrg    }
13222944501Smrg
13322944501Smrg    list->magic = SL_FREED_MAGIC;
134e6188e58Smrg    drmFree(list);
13522944501Smrg    return 0;
13622944501Smrg}
13722944501Smrg
13822944501Smrgstatic SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update)
13922944501Smrg{
14022944501Smrg    SkipListPtr   list  = (SkipListPtr)l;
14122944501Smrg    SLEntryPtr    entry;
14222944501Smrg    int           i;
14322944501Smrg
14422944501Smrg    if (list->magic != SL_LIST_MAGIC) return NULL;
14522944501Smrg
14622944501Smrg    for (i = list->level, entry = list->head; i >= 0; i--) {
14722944501Smrg	while (entry->forward[i] && entry->forward[i]->key < key)
14822944501Smrg	    entry = entry->forward[i];
14922944501Smrg	update[i] = entry;
15022944501Smrg    }
15122944501Smrg
15222944501Smrg    return entry->forward[0];
15322944501Smrg}
15422944501Smrg
1557cdc0497Smrgdrm_public int drmSLInsert(void *l, unsigned long key, void *value)
15622944501Smrg{
15722944501Smrg    SkipListPtr   list  = (SkipListPtr)l;
15822944501Smrg    SLEntryPtr    entry;
15922944501Smrg    SLEntryPtr    update[SL_MAX_LEVEL + 1];
16022944501Smrg    int           level;
16122944501Smrg    int           i;
16222944501Smrg
16322944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
16422944501Smrg
16522944501Smrg    entry = SLLocate(list, key, update);
16622944501Smrg
16722944501Smrg    if (entry && entry->key == key) return 1; /* Already in list */
16822944501Smrg
16922944501Smrg
17022944501Smrg    level = SLRandomLevel();
17122944501Smrg    if (level > list->level) {
17222944501Smrg	level = ++list->level;
17322944501Smrg	update[level] = list->head;
17422944501Smrg    }
17522944501Smrg
17622944501Smrg    entry = SLCreateEntry(level, key, value);
17722944501Smrg
17822944501Smrg				/* Fix up forward pointers */
17922944501Smrg    for (i = 0; i <= level; i++) {
18022944501Smrg	entry->forward[i]     = update[i]->forward[i];
18122944501Smrg	update[i]->forward[i] = entry;
18222944501Smrg    }
18322944501Smrg
18422944501Smrg    ++list->count;
18522944501Smrg    return 0;			/* Added to table */
18622944501Smrg}
18722944501Smrg
1887cdc0497Smrgdrm_public int drmSLDelete(void *l, unsigned long key)
18922944501Smrg{
19022944501Smrg    SkipListPtr   list = (SkipListPtr)l;
19122944501Smrg    SLEntryPtr    update[SL_MAX_LEVEL + 1];
19222944501Smrg    SLEntryPtr    entry;
19322944501Smrg    int           i;
19422944501Smrg
19522944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
19622944501Smrg
19722944501Smrg    entry = SLLocate(list, key, update);
19822944501Smrg
19922944501Smrg    if (!entry || entry->key != key) return 1; /* Not found */
20022944501Smrg
20122944501Smrg				/* Fix up forward pointers */
20222944501Smrg    for (i = 0; i <= list->level; i++) {
20322944501Smrg	if (update[i]->forward[i] == entry)
20422944501Smrg	    update[i]->forward[i] = entry->forward[i];
20522944501Smrg    }
20622944501Smrg
20722944501Smrg    entry->magic = SL_FREED_MAGIC;
208e6188e58Smrg    drmFree(entry);
20922944501Smrg
21022944501Smrg    while (list->level && !list->head->forward[list->level]) --list->level;
21122944501Smrg    --list->count;
21222944501Smrg    return 0;
21322944501Smrg}
21422944501Smrg
2157cdc0497Smrgdrm_public int drmSLLookup(void *l, unsigned long key, void **value)
21622944501Smrg{
21722944501Smrg    SkipListPtr   list = (SkipListPtr)l;
21822944501Smrg    SLEntryPtr    update[SL_MAX_LEVEL + 1];
21922944501Smrg    SLEntryPtr    entry;
22022944501Smrg
22122944501Smrg    entry = SLLocate(list, key, update);
22222944501Smrg
22322944501Smrg    if (entry && entry->key == key) {
22422944501Smrg	*value = entry;
22522944501Smrg	return 0;
22622944501Smrg    }
22722944501Smrg    *value = NULL;
22822944501Smrg    return -1;
22922944501Smrg}
23022944501Smrg
2317cdc0497Smrgdrm_public int drmSLLookupNeighbors(void *l, unsigned long key,
2327cdc0497Smrg                                    unsigned long *prev_key, void **prev_value,
2337cdc0497Smrg                                    unsigned long *next_key, void **next_value)
23422944501Smrg{
23522944501Smrg    SkipListPtr   list = (SkipListPtr)l;
236e6188e58Smrg    SLEntryPtr    update[SL_MAX_LEVEL + 1] = {0};
23722944501Smrg    int           retcode = 0;
23822944501Smrg
239e6188e58Smrg    SLLocate(list, key, update);
240e6188e58Smrg
24122944501Smrg    *prev_key   = *next_key   = key;
24222944501Smrg    *prev_value = *next_value = NULL;
243e6188e58Smrg
24422944501Smrg    if (update[0]) {
24522944501Smrg	*prev_key   = update[0]->key;
24622944501Smrg	*prev_value = update[0]->value;
24722944501Smrg	++retcode;
24822944501Smrg	if (update[0]->forward[0]) {
24922944501Smrg	    *next_key   = update[0]->forward[0]->key;
25022944501Smrg	    *next_value = update[0]->forward[0]->value;
25122944501Smrg	    ++retcode;
25222944501Smrg	}
25322944501Smrg    }
25422944501Smrg    return retcode;
25522944501Smrg}
25622944501Smrg
2577cdc0497Smrgdrm_public int drmSLNext(void *l, unsigned long *key, void **value)
25822944501Smrg{
25922944501Smrg    SkipListPtr   list = (SkipListPtr)l;
26022944501Smrg    SLEntryPtr    entry;
26122944501Smrg
26222944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
26322944501Smrg
26422944501Smrg    entry    = list->p0;
26522944501Smrg
26622944501Smrg    if (entry) {
26722944501Smrg	list->p0 = entry->forward[0];
26822944501Smrg	*key     = entry->key;
26922944501Smrg	*value   = entry->value;
27022944501Smrg	return 1;
27122944501Smrg    }
27222944501Smrg    list->p0 = NULL;
27322944501Smrg    return 0;
27422944501Smrg}
27522944501Smrg
2767cdc0497Smrgdrm_public int drmSLFirst(void *l, unsigned long *key, void **value)
27722944501Smrg{
27822944501Smrg    SkipListPtr   list = (SkipListPtr)l;
27922944501Smrg
28022944501Smrg    if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
28122944501Smrg
28222944501Smrg    list->p0 = list->head->forward[0];
28322944501Smrg    return drmSLNext(list, key, value);
28422944501Smrg}
28522944501Smrg
28622944501Smrg/* Dump internal data structures for debugging. */
2877cdc0497Smrgdrm_public void drmSLDump(void *l)
28822944501Smrg{
28922944501Smrg    SkipListPtr   list = (SkipListPtr)l;
29022944501Smrg    SLEntryPtr    entry;
29122944501Smrg    int           i;
29222944501Smrg
29322944501Smrg    if (list->magic != SL_LIST_MAGIC) {
29422944501Smrg	printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
29522944501Smrg	       list->magic, SL_LIST_MAGIC);
29622944501Smrg	return;
29722944501Smrg    }
29822944501Smrg
29922944501Smrg    printf("Level = %d, count = %d\n", list->level, list->count);
30022944501Smrg    for (entry = list->head; entry; entry = entry->forward[0]) {
30122944501Smrg	if (entry->magic != SL_ENTRY_MAGIC) {
30222944501Smrg	    printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
30322944501Smrg		   list->magic, SL_ENTRY_MAGIC);
30422944501Smrg	}
30522944501Smrg	printf("\nEntry %p <0x%08lx, %p> has %2d levels\n",
30622944501Smrg	       entry, entry->key, entry->value, entry->levels);
30722944501Smrg	for (i = 0; i < entry->levels; i++) {
30822944501Smrg	    if (entry->forward[i]) {
30922944501Smrg		printf("   %2d: %p <0x%08lx, %p>\n",
31022944501Smrg		       i,
31122944501Smrg		       entry->forward[i],
31222944501Smrg		       entry->forward[i]->key,
31322944501Smrg		       entry->forward[i]->value);
31422944501Smrg	    } else {
31522944501Smrg		printf("   %2d: %p\n", i, entry->forward[i]);
31622944501Smrg	    }
31722944501Smrg	}
31822944501Smrg    }
31922944501Smrg}
320