download skiplist.c
Language: C
License: GPL
Copyright: (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
LOC: 155
Project Info
Mac-on-Mac - Mac-on-Mac(maconmac)
Server: Spider_20090226_inc
Type: filesystem
...‑ALPHA.zip\mol‑bk\src\kmod\
   actions.c
   context.c
   emu.c
   fault.c
   hash.c
   init.c
   misc.c
   mmu.c
   mmu_fb.c
   mmu_io.c
   mmu_tracker.c
   moldbg.c
   mtable.c
   ptaccess.c
   skiplist.c

/* 
 *   Creation Date: <2003/03/03 23:19:47 samuel>
 *   Time-stamp: <2004/02/21 16:24:56 samuel>
 *   
 *	<skiplist.c>
 *	
 *	Skiplist implementation
 *   
 *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
 *   
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation
 *   
 */

#include "archinclude.h"
#include "skiplist.h"
#include "alloc.h"

#define SKIPLIST_END 		INT_MAX		/* this key is reserved */

/*
 *	Skiplist Example:
 *	
 *	level 0   ->   el1   ->   el2	->   el3   -->   el4   --> null_el
 *	level 1        -->        el2   ->   el3   -->   el4   --> null_el
 *	level 2        -->        el2        -->         el4   --> null_el
 *	level 3        -->        el2        ----->                null_el
 *	level 4               ------------>                        null_el
 *	...
 *	SKIPLIST_MAX_HEIGHT-1          ------------>                        null_el
 */

static unsigned int mol_rand_seed = 152;

static inline int
_cntlz( int val ) 
{
	int ret;
	asm volatile("cntlzw %0,%1" : "=r" (ret) : "r"(val) );
	return ret;
}

static unsigned long
mol_random( void )
{
	unsigned int t;
	asm( "mftb %0" : "=r"(t) : );
	mol_rand_seed = mol_rand_seed*69069L+1;
        return mol_rand_seed^t;
}

static void
mol_random_entropy( void )
{
	unsigned int entropy;
	asm( "mftb %0" : "=r" (entropy) : );
        mol_rand_seed ^= entropy;
}

static inline void
set_level_next( skiplist_level_t *level, skiplist_el_t *el )
{
	level->next = el;
#ifdef __darwin__
	level->next_phys = el ? tophys_mol(el) : NULL;
#endif	
}


/************************************************************************/
/*	skiplist operations						*/
/************************************************************************/

int
skiplist_prealloc( skiplist_t *sl, char *buf, unsigned int size, 
		   skiplist_el_callback callback, void *usr1, void *usr2 )
{
	skiplist_el_t *p, *head;
	unsigned int s;
	int n, count;

	head = NULL;
	for( count=0 ;; size -= s, buf += s, count++ ) {
		for( n=0; n<SKIPLIST_MAX_HEIGHT-1 && (mol_random() & 0x40) ; n++ )
			;
		s = sl->datasize + sizeof(skiplist_t) + n*sizeof(skiplist_level_t);
		if( s > size )
			break;
		p = (skiplist_el_t*)(buf + sl->datasize);
		p->key = n;
		set_level_next( &p->level[0], head );
		head = p;
	}

	/* note: the callback is allowed to manipulate the skiplist */
	for( n=0, p=head; p; p=p->level[0].next, n++ ) {
		if( callback )
			(*callback)( (char*)p - sl->datasize, n, count, usr1, usr2 );
		if( !p->level[0].next ) {
			p->level[0] = sl->freelist;
			set_level_next( &sl->freelist, head );
			break;
		}
	}
	return count;
}

char *
skiplist_insert( skiplist_t *sl, int key )
{
	skiplist_el_t *pleft = (skiplist_el_t*)((char*)&sl->root[0] - offsetof(skiplist_el_t, level));
	skiplist_level_t el = sl->freelist;
	skiplist_el_t *p = el.next;
	int n, slev;

	if( !p )
		return NULL;
	sl->freelist = p->level[0];
	n = p->key;
	p->key = key;

	/* pick a good search level (the -3 is benchmarked) */
	sl->nel++;
	slev = 31 - _cntlz(sl->nel) - 3;
	if( slev > SKIPLIST_MAX_HEIGHT-1 )
		slev = SKIPLIST_MAX_HEIGHT-1;
	else if( slev < 0 )
		slev = 0;
	sl->slevel = slev;

	/* insert element */
	if( slev < n )
		slev = n;
	for( ; slev >= 0; slev-- ) {
		for( ; pleft->level[slev].next->key < key ; pleft=pleft->level[slev].next )
			;
		if( slev <= n ) {
			p->level[slev] = pleft->level[slev];
			pleft->level[slev] = el;
		}
	}

	return (char*)p - sl->datasize;
}

char *
skiplist_delete( skiplist_t *sl, int key )
{
	skiplist_el_t *p = (skiplist_el_t*)((char*)&sl->root[0] - offsetof(skiplist_el_t, level));
	skiplist_level_t delptr;
	int n, level = -1;

	for( n=SKIPLIST_MAX_HEIGHT-1; n>=0; n-- ) {
		for( ; p->level[n].next->key < key ; p=p->level[n].next )
			;
		if( p->level[n].next->key != key )
			continue;

		if( level < 0 ) {
			delptr = p->level[n];
			level = n;
		}
		p->level[n] = delptr.next->level[n];
	}
	if( level < 0 )
		return NULL;
	
	/* put on freelist */
	p = delptr.next;
	p->key = level;
	p->level[0] = sl->freelist;
	sl->freelist = delptr;
	sl->nel--;

	return (char*)p - sl->datasize;
}

char *
skiplist_lookup( skiplist_t *sl, int key )
{
	skiplist_el_t *p = (skiplist_el_t*)((char*)&sl->root[0] - offsetof(skiplist_el_t, level));
	int n = sl->slevel;

	for( ;; ) {
		if( p->level[n].next->key < key ) {
			p = p->level[n].next;
			continue;
		}
		if( p->level[n].next->key > key ) {
			if( --n < 0 )
				break;
			continue;
		}
		return (char*)p->level[n].next - sl->datasize;
	}
	return NULL;
}

void
skiplist_init( skiplist_t *sl, int datasize )
{
	skiplist_level_t nilptr;
	int i;

	mol_random_entropy();

	memset( sl, 0, sizeof(*sl) );
	
	sl->nil_el.key = SKIPLIST_END;
	sl->datasize = datasize;

	/* remember: the nil element is of level 0 */
	set_level_next( &nilptr, &sl->nil_el );
	sl->nil_el.level[0] = nilptr;

	for( i=0; i < SKIPLIST_MAX_HEIGHT ; i++ )
		sl->root[i] = nilptr;
}

About Koders | Resources | Downloads | Support | Black Duck | Submit Project | Terms of Service | DMCA | Privacy Policy | Site Map| Contact Us