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