xf86drmSL.c revision e6188e58
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 44e6188e58Smrg#include "xf86drm.h" 4522944501Smrg 4622944501Smrg#define SL_LIST_MAGIC 0xfacade00LU 4722944501Smrg#define SL_ENTRY_MAGIC 0x00fab1edLU 4822944501Smrg#define SL_FREED_MAGIC 0xdecea5edLU 4922944501Smrg#define SL_MAX_LEVEL 16 5022944501Smrg#define SL_RANDOM_SEED 0xc01055a1LU 5122944501Smrg 5222944501Smrg#define SL_RANDOM_DECL static void *state = NULL 5322944501Smrg#define SL_RANDOM_INIT(seed) if (!state) state = drmRandomCreate(seed) 5422944501Smrg#define SL_RANDOM drmRandom(state) 5522944501Smrg 5622944501Smrgtypedef struct SLEntry { 5722944501Smrg unsigned long magic; /* SL_ENTRY_MAGIC */ 5822944501Smrg unsigned long key; 5922944501Smrg void *value; 6022944501Smrg int levels; 6122944501Smrg struct SLEntry *forward[1]; /* variable sized array */ 6222944501Smrg} SLEntry, *SLEntryPtr; 6322944501Smrg 6422944501Smrgtypedef struct SkipList { 6522944501Smrg unsigned long magic; /* SL_LIST_MAGIC */ 6622944501Smrg int level; 6722944501Smrg int count; 6822944501Smrg SLEntryPtr head; 6922944501Smrg SLEntryPtr p0; /* Position for iteration */ 7022944501Smrg} SkipList, *SkipListPtr; 7122944501Smrg 7222944501Smrgstatic SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value) 7322944501Smrg{ 7422944501Smrg SLEntryPtr entry; 7522944501Smrg 7622944501Smrg if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL; 7722944501Smrg 78e6188e58Smrg entry = drmMalloc(sizeof(*entry) 7922944501Smrg + (max_level + 1) * sizeof(entry->forward[0])); 8022944501Smrg if (!entry) return NULL; 8122944501Smrg entry->magic = SL_ENTRY_MAGIC; 8222944501Smrg entry->key = key; 8322944501Smrg entry->value = value; 8422944501Smrg entry->levels = max_level + 1; 8522944501Smrg 8622944501Smrg return entry; 8722944501Smrg} 8822944501Smrg 8922944501Smrgstatic int SLRandomLevel(void) 9022944501Smrg{ 9122944501Smrg int level = 1; 9222944501Smrg SL_RANDOM_DECL; 9322944501Smrg 9422944501Smrg SL_RANDOM_INIT(SL_RANDOM_SEED); 9522944501Smrg 9622944501Smrg while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level; 9722944501Smrg return level; 9822944501Smrg} 9922944501Smrg 10022944501Smrgvoid *drmSLCreate(void) 10122944501Smrg{ 10222944501Smrg SkipListPtr list; 10322944501Smrg int i; 10422944501Smrg 105e6188e58Smrg list = drmMalloc(sizeof(*list)); 10622944501Smrg if (!list) return NULL; 10722944501Smrg list->magic = SL_LIST_MAGIC; 10822944501Smrg list->level = 0; 10922944501Smrg list->head = SLCreateEntry(SL_MAX_LEVEL, 0, NULL); 11022944501Smrg list->count = 0; 11122944501Smrg 11222944501Smrg for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL; 11322944501Smrg 11422944501Smrg return list; 11522944501Smrg} 11622944501Smrg 11722944501Smrgint drmSLDestroy(void *l) 11822944501Smrg{ 11922944501Smrg SkipListPtr list = (SkipListPtr)l; 12022944501Smrg SLEntryPtr entry; 12122944501Smrg SLEntryPtr next; 12222944501Smrg 12322944501Smrg if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ 12422944501Smrg 12522944501Smrg for (entry = list->head; entry; entry = next) { 12622944501Smrg if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */ 12722944501Smrg next = entry->forward[0]; 12822944501Smrg entry->magic = SL_FREED_MAGIC; 129e6188e58Smrg drmFree(entry); 13022944501Smrg } 13122944501Smrg 13222944501Smrg list->magic = SL_FREED_MAGIC; 133e6188e58Smrg drmFree(list); 13422944501Smrg return 0; 13522944501Smrg} 13622944501Smrg 13722944501Smrgstatic SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update) 13822944501Smrg{ 13922944501Smrg SkipListPtr list = (SkipListPtr)l; 14022944501Smrg SLEntryPtr entry; 14122944501Smrg int i; 14222944501Smrg 14322944501Smrg if (list->magic != SL_LIST_MAGIC) return NULL; 14422944501Smrg 14522944501Smrg for (i = list->level, entry = list->head; i >= 0; i--) { 14622944501Smrg while (entry->forward[i] && entry->forward[i]->key < key) 14722944501Smrg entry = entry->forward[i]; 14822944501Smrg update[i] = entry; 14922944501Smrg } 15022944501Smrg 15122944501Smrg return entry->forward[0]; 15222944501Smrg} 15322944501Smrg 15422944501Smrgint drmSLInsert(void *l, unsigned long key, void *value) 15522944501Smrg{ 15622944501Smrg SkipListPtr list = (SkipListPtr)l; 15722944501Smrg SLEntryPtr entry; 15822944501Smrg SLEntryPtr update[SL_MAX_LEVEL + 1]; 15922944501Smrg int level; 16022944501Smrg int i; 16122944501Smrg 16222944501Smrg if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ 16322944501Smrg 16422944501Smrg entry = SLLocate(list, key, update); 16522944501Smrg 16622944501Smrg if (entry && entry->key == key) return 1; /* Already in list */ 16722944501Smrg 16822944501Smrg 16922944501Smrg level = SLRandomLevel(); 17022944501Smrg if (level > list->level) { 17122944501Smrg level = ++list->level; 17222944501Smrg update[level] = list->head; 17322944501Smrg } 17422944501Smrg 17522944501Smrg entry = SLCreateEntry(level, key, value); 17622944501Smrg 17722944501Smrg /* Fix up forward pointers */ 17822944501Smrg for (i = 0; i <= level; i++) { 17922944501Smrg entry->forward[i] = update[i]->forward[i]; 18022944501Smrg update[i]->forward[i] = entry; 18122944501Smrg } 18222944501Smrg 18322944501Smrg ++list->count; 18422944501Smrg return 0; /* Added to table */ 18522944501Smrg} 18622944501Smrg 18722944501Smrgint drmSLDelete(void *l, unsigned long key) 18822944501Smrg{ 18922944501Smrg SkipListPtr list = (SkipListPtr)l; 19022944501Smrg SLEntryPtr update[SL_MAX_LEVEL + 1]; 19122944501Smrg SLEntryPtr entry; 19222944501Smrg int i; 19322944501Smrg 19422944501Smrg if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ 19522944501Smrg 19622944501Smrg entry = SLLocate(list, key, update); 19722944501Smrg 19822944501Smrg if (!entry || entry->key != key) return 1; /* Not found */ 19922944501Smrg 20022944501Smrg /* Fix up forward pointers */ 20122944501Smrg for (i = 0; i <= list->level; i++) { 20222944501Smrg if (update[i]->forward[i] == entry) 20322944501Smrg update[i]->forward[i] = entry->forward[i]; 20422944501Smrg } 20522944501Smrg 20622944501Smrg entry->magic = SL_FREED_MAGIC; 207e6188e58Smrg drmFree(entry); 20822944501Smrg 20922944501Smrg while (list->level && !list->head->forward[list->level]) --list->level; 21022944501Smrg --list->count; 21122944501Smrg return 0; 21222944501Smrg} 21322944501Smrg 21422944501Smrgint drmSLLookup(void *l, unsigned long key, void **value) 21522944501Smrg{ 21622944501Smrg SkipListPtr list = (SkipListPtr)l; 21722944501Smrg SLEntryPtr update[SL_MAX_LEVEL + 1]; 21822944501Smrg SLEntryPtr entry; 21922944501Smrg 22022944501Smrg entry = SLLocate(list, key, update); 22122944501Smrg 22222944501Smrg if (entry && entry->key == key) { 22322944501Smrg *value = entry; 22422944501Smrg return 0; 22522944501Smrg } 22622944501Smrg *value = NULL; 22722944501Smrg return -1; 22822944501Smrg} 22922944501Smrg 23022944501Smrgint drmSLLookupNeighbors(void *l, unsigned long key, 23122944501Smrg unsigned long *prev_key, void **prev_value, 23222944501Smrg unsigned long *next_key, void **next_value) 23322944501Smrg{ 23422944501Smrg SkipListPtr list = (SkipListPtr)l; 235e6188e58Smrg SLEntryPtr update[SL_MAX_LEVEL + 1] = {0}; 23622944501Smrg int retcode = 0; 23722944501Smrg 238e6188e58Smrg SLLocate(list, key, update); 239e6188e58Smrg 24022944501Smrg *prev_key = *next_key = key; 24122944501Smrg *prev_value = *next_value = NULL; 242e6188e58Smrg 24322944501Smrg if (update[0]) { 24422944501Smrg *prev_key = update[0]->key; 24522944501Smrg *prev_value = update[0]->value; 24622944501Smrg ++retcode; 24722944501Smrg if (update[0]->forward[0]) { 24822944501Smrg *next_key = update[0]->forward[0]->key; 24922944501Smrg *next_value = update[0]->forward[0]->value; 25022944501Smrg ++retcode; 25122944501Smrg } 25222944501Smrg } 25322944501Smrg return retcode; 25422944501Smrg} 25522944501Smrg 25622944501Smrgint drmSLNext(void *l, unsigned long *key, void **value) 25722944501Smrg{ 25822944501Smrg SkipListPtr list = (SkipListPtr)l; 25922944501Smrg SLEntryPtr entry; 26022944501Smrg 26122944501Smrg if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ 26222944501Smrg 26322944501Smrg entry = list->p0; 26422944501Smrg 26522944501Smrg if (entry) { 26622944501Smrg list->p0 = entry->forward[0]; 26722944501Smrg *key = entry->key; 26822944501Smrg *value = entry->value; 26922944501Smrg return 1; 27022944501Smrg } 27122944501Smrg list->p0 = NULL; 27222944501Smrg return 0; 27322944501Smrg} 27422944501Smrg 27522944501Smrgint drmSLFirst(void *l, unsigned long *key, void **value) 27622944501Smrg{ 27722944501Smrg SkipListPtr list = (SkipListPtr)l; 27822944501Smrg 27922944501Smrg if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */ 28022944501Smrg 28122944501Smrg list->p0 = list->head->forward[0]; 28222944501Smrg return drmSLNext(list, key, value); 28322944501Smrg} 28422944501Smrg 28522944501Smrg/* Dump internal data structures for debugging. */ 28622944501Smrgvoid drmSLDump(void *l) 28722944501Smrg{ 28822944501Smrg SkipListPtr list = (SkipListPtr)l; 28922944501Smrg SLEntryPtr entry; 29022944501Smrg int i; 29122944501Smrg 29222944501Smrg if (list->magic != SL_LIST_MAGIC) { 29322944501Smrg printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", 29422944501Smrg list->magic, SL_LIST_MAGIC); 29522944501Smrg return; 29622944501Smrg } 29722944501Smrg 29822944501Smrg printf("Level = %d, count = %d\n", list->level, list->count); 29922944501Smrg for (entry = list->head; entry; entry = entry->forward[0]) { 30022944501Smrg if (entry->magic != SL_ENTRY_MAGIC) { 30122944501Smrg printf("Bad magic: 0x%08lx (expected 0x%08lx)\n", 30222944501Smrg list->magic, SL_ENTRY_MAGIC); 30322944501Smrg } 30422944501Smrg printf("\nEntry %p <0x%08lx, %p> has %2d levels\n", 30522944501Smrg entry, entry->key, entry->value, entry->levels); 30622944501Smrg for (i = 0; i < entry->levels; i++) { 30722944501Smrg if (entry->forward[i]) { 30822944501Smrg printf(" %2d: %p <0x%08lx, %p>\n", 30922944501Smrg i, 31022944501Smrg entry->forward[i], 31122944501Smrg entry->forward[i]->key, 31222944501Smrg entry->forward[i]->value); 31322944501Smrg } else { 31422944501Smrg printf(" %2d: %p\n", i, entry->forward[i]); 31522944501Smrg } 31622944501Smrg } 31722944501Smrg } 31822944501Smrg} 319