summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netpfil/ipfw/dn_heap.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-10-07 15:10:20 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-01-10 09:53:31 +0100
commitc40e45b75eb76d79a05c7fa85c1fa9b5c728a12f (patch)
treead4f2519067709f00ab98b3c591186c26dc3a21f /freebsd/sys/netpfil/ipfw/dn_heap.c
parentuserspace-header-gen.py: Simplify program ports (diff)
downloadrtems-libbsd-c40e45b75eb76d79a05c7fa85c1fa9b5c728a12f.tar.bz2
Update to FreeBSD head 2016-08-23
Git mirror commit 9fe7c416e6abb28b1398fd3e5687099846800cfd.
Diffstat (limited to 'freebsd/sys/netpfil/ipfw/dn_heap.c')
-rw-r--r--freebsd/sys/netpfil/ipfw/dn_heap.c554
1 files changed, 0 insertions, 554 deletions
diff --git a/freebsd/sys/netpfil/ipfw/dn_heap.c b/freebsd/sys/netpfil/ipfw/dn_heap.c
deleted file mode 100644
index 15e2870d..00000000
--- a/freebsd/sys/netpfil/ipfw/dn_heap.c
+++ /dev/null
@@ -1,554 +0,0 @@
-#include <machine/rtems-bsd-kernel-space.h>
-
-/*-
- * Copyright (c) 1998-2002,2010 Luigi Rizzo, Universita` di Pisa
- * All rights reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Binary heap and hash tables, used in dummynet
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-#include <rtems/bsd/sys/param.h>
-#ifdef _KERNEL
-__FBSDID("$FreeBSD$");
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <netpfil/ipfw/dn_heap.h>
-#ifndef log
-#define log(x, arg...)
-#endif
-
-#else /* !_KERNEL */
-
-#include <stdio.h>
-#include <dn_test.h>
-#include <strings.h>
-#include <stdlib.h>
-
-#include "dn_heap.h"
-#define log(x, arg...) fprintf(stderr, ## arg)
-#define panic(x...) fprintf(stderr, ## x), exit(1)
-#define MALLOC_DEFINE(a, b, c)
-static void *my_malloc(int s) { return malloc(s); }
-static void my_free(void *p) { free(p); }
-#define malloc(s, t, w) my_malloc(s)
-#define free(p, t) my_free(p)
-#endif /* !_KERNEL */
-
-MALLOC_DEFINE(M_DN_HEAP, "dummynet", "dummynet heap");
-
-/*
- * Heap management functions.
- *
- * In the heap, first node is element 0. Children of i are 2i+1 and 2i+2.
- * Some macros help finding parent/children so we can optimize them.
- *
- * heap_init() is called to expand the heap when needed.
- * Increment size in blocks of 16 entries.
- * Returns 1 on error, 0 on success
- */
-#define HEAP_FATHER(x) ( ( (x) - 1 ) / 2 )
-#define HEAP_LEFT(x) ( (x)+(x) + 1 )
-#define HEAP_SWAP(a, b, buffer) { buffer = a ; a = b ; b = buffer ; }
-#define HEAP_INCREMENT 15
-
-static int
-heap_resize(struct dn_heap *h, unsigned int new_size)
-{
- struct dn_heap_entry *p;
-
- if (h->size >= new_size ) /* have enough room */
- return 0;
-#if 1 /* round to the next power of 2 */
- new_size |= new_size >> 1;
- new_size |= new_size >> 2;
- new_size |= new_size >> 4;
- new_size |= new_size >> 8;
- new_size |= new_size >> 16;
-#else
- new_size = (new_size + HEAP_INCREMENT ) & ~HEAP_INCREMENT;
-#endif
- p = malloc(new_size * sizeof(*p), M_DN_HEAP, M_NOWAIT);
- if (p == NULL) {
- printf("--- %s, resize %d failed\n", __func__, new_size );
- return 1; /* error */
- }
- if (h->size > 0) {
- bcopy(h->p, p, h->size * sizeof(*p) );
- free(h->p, M_DN_HEAP);
- }
- h->p = p;
- h->size = new_size;
- return 0;
-}
-
-int
-heap_init(struct dn_heap *h, int size, int ofs)
-{
- if (heap_resize(h, size))
- return 1;
- h->elements = 0;
- h->ofs = ofs;
- return 0;
-}
-
-/*
- * Insert element in heap. Normally, p != NULL, we insert p in
- * a new position and bubble up. If p == NULL, then the element is
- * already in place, and key is the position where to start the
- * bubble-up.
- * Returns 1 on failure (cannot allocate new heap entry)
- *
- * If ofs > 0 the position (index, int) of the element in the heap is
- * also stored in the element itself at the given offset in bytes.
- */
-#define SET_OFFSET(h, i) do { \
- if (h->ofs > 0) \
- *((int32_t *)((char *)(h->p[i].object) + h->ofs)) = i; \
- } while (0)
-/*
- * RESET_OFFSET is used for sanity checks. It sets ofs
- * to an invalid value.
- */
-#define RESET_OFFSET(h, i) do { \
- if (h->ofs > 0) \
- *((int32_t *)((char *)(h->p[i].object) + h->ofs)) = -16; \
- } while (0)
-
-int
-heap_insert(struct dn_heap *h, uint64_t key1, void *p)
-{
- int son = h->elements;
-
- //log("%s key %llu p %p\n", __FUNCTION__, key1, p);
- if (p == NULL) { /* data already there, set starting point */
- son = key1;
- } else { /* insert new element at the end, possibly resize */
- son = h->elements;
- if (son == h->size) /* need resize... */
- // XXX expand by 16 or so
- if (heap_resize(h, h->elements+16) )
- return 1; /* failure... */
- h->p[son].object = p;
- h->p[son].key = key1;
- h->elements++;
- }
- /* make sure that son >= father along the path */
- while (son > 0) {
- int father = HEAP_FATHER(son);
- struct dn_heap_entry tmp;
-
- if (DN_KEY_LT( h->p[father].key, h->p[son].key ) )
- break; /* found right position */
- /* son smaller than father, swap and repeat */
- HEAP_SWAP(h->p[son], h->p[father], tmp);
- SET_OFFSET(h, son);
- son = father;
- }
- SET_OFFSET(h, son);
- return 0;
-}
-
-/*
- * remove top element from heap, or obj if obj != NULL
- */
-void
-heap_extract(struct dn_heap *h, void *obj)
-{
- int child, father, max = h->elements - 1;
-
- if (max < 0) {
- printf("--- %s: empty heap 0x%p\n", __FUNCTION__, h);
- return;
- }
- if (obj == NULL)
- father = 0; /* default: move up smallest child */
- else { /* extract specific element, index is at offset */
- if (h->ofs <= 0)
- panic("%s: extract from middle not set on %p\n",
- __FUNCTION__, h);
- father = *((int *)((char *)obj + h->ofs));
- if (father < 0 || father >= h->elements) {
- panic("%s: father %d out of bound 0..%d\n",
- __FUNCTION__, father, h->elements);
- }
- }
- /*
- * below, father is the index of the empty element, which
- * we replace at each step with the smallest child until we
- * reach the bottom level.
- */
- // XXX why removing RESET_OFFSET increases runtime by 10% ?
- RESET_OFFSET(h, father);
- while ( (child = HEAP_LEFT(father)) <= max ) {
- if (child != max &&
- DN_KEY_LT(h->p[child+1].key, h->p[child].key) )
- child++; /* take right child, otherwise left */
- h->p[father] = h->p[child];
- SET_OFFSET(h, father);
- father = child;
- }
- h->elements--;
- if (father != max) {
- /*
- * Fill hole with last entry and bubble up,
- * reusing the insert code
- */
- h->p[father] = h->p[max];
- heap_insert(h, father, NULL);
- }
-}
-
-#if 0
-/*
- * change object position and update references
- * XXX this one is never used!
- */
-static void
-heap_move(struct dn_heap *h, uint64_t new_key, void *object)
-{
- int temp, i, max = h->elements-1;
- struct dn_heap_entry *p, buf;
-
- if (h->ofs <= 0)
- panic("cannot move items on this heap");
- p = h->p; /* shortcut */
-
- i = *((int *)((char *)object + h->ofs));
- if (DN_KEY_LT(new_key, p[i].key) ) { /* must move up */
- p[i].key = new_key;
- for (; i>0 &&
- DN_KEY_LT(new_key, p[(temp = HEAP_FATHER(i))].key);
- i = temp ) { /* bubble up */
- HEAP_SWAP(p[i], p[temp], buf);
- SET_OFFSET(h, i);
- }
- } else { /* must move down */
- p[i].key = new_key;
- while ( (temp = HEAP_LEFT(i)) <= max ) {
- /* found left child */
- if (temp != max &&
- DN_KEY_LT(p[temp+1].key, p[temp].key))
- temp++; /* select child with min key */
- if (DN_KEY_LT(>p[temp].key, new_key)) {
- /* go down */
- HEAP_SWAP(p[i], p[temp], buf);
- SET_OFFSET(h, i);
- } else
- break;
- i = temp;
- }
- }
- SET_OFFSET(h, i);
-}
-#endif /* heap_move, unused */
-
-/*
- * heapify() will reorganize data inside an array to maintain the
- * heap property. It is needed when we delete a bunch of entries.
- */
-static void
-heapify(struct dn_heap *h)
-{
- int i;
-
- for (i = 0; i < h->elements; i++ )
- heap_insert(h, i , NULL);
-}
-
-int
-heap_scan(struct dn_heap *h, int (*fn)(void *, uintptr_t),
- uintptr_t arg)
-{
- int i, ret, found;
-
- for (i = found = 0 ; i < h->elements ;) {
- ret = fn(h->p[i].object, arg);
- if (ret & HEAP_SCAN_DEL) {
- h->elements-- ;
- h->p[i] = h->p[h->elements] ;
- found++ ;
- } else
- i++ ;
- if (ret & HEAP_SCAN_END)
- break;
- }
- if (found)
- heapify(h);
- return found;
-}
-
-/*
- * cleanup the heap and free data structure
- */
-void
-heap_free(struct dn_heap *h)
-{
- if (h->size >0 )
- free(h->p, M_DN_HEAP);
- bzero(h, sizeof(*h) );
-}
-
-/*
- * hash table support.
- */
-
-struct dn_ht {
- int buckets; /* how many buckets, really buckets - 1*/
- int entries; /* how many entries */
- int ofs; /* offset of link field */
- uint32_t (*hash)(uintptr_t, int, void *arg);
- int (*match)(void *_el, uintptr_t key, int, void *);
- void *(*newh)(uintptr_t, int, void *);
- void **ht; /* bucket heads */
-};
-/*
- * Initialize, allocating bucket pointers inline.
- * Recycle previous record if possible.
- * If the 'newh' function is not supplied, we assume that the
- * key passed to ht_find is the same object to be stored in.
- */
-struct dn_ht *
-dn_ht_init(struct dn_ht *ht, int buckets, int ofs,
- uint32_t (*h)(uintptr_t, int, void *),
- int (*match)(void *, uintptr_t, int, void *),
- void *(*newh)(uintptr_t, int, void *))
-{
- int l;
-
- /*
- * Notes about rounding bucket size to a power of two.
- * Given the original bucket size, we compute the nearest lower and
- * higher power of two, minus 1 (respectively b_min and b_max) because
- * this value will be used to do an AND with the index returned
- * by hash function.
- * To choice between these two values, the original bucket size is
- * compared with b_min. If the original size is greater than 4/3 b_min,
- * we round the bucket size to b_max, else to b_min.
- * This ratio try to round to the nearest power of two, advantaging
- * the greater size if the different between two power is relatively
- * big.
- * Rounding the bucket size to a power of two avoid the use of
- * module when calculating the correct bucket.
- * The ht->buckets variable store the bucket size - 1 to simply
- * do an AND between the index returned by hash function and ht->bucket
- * instead of a module.
- */
- int b_min; /* min buckets */
- int b_max; /* max buckets */
- int b_ori; /* original buckets */
-
- if (h == NULL || match == NULL) {
- printf("--- missing hash or match function");
- return NULL;
- }
- if (buckets < 1 || buckets > 65536)
- return NULL;
-
- b_ori = buckets;
- /* calculate next power of 2, - 1*/
- buckets |= buckets >> 1;
- buckets |= buckets >> 2;
- buckets |= buckets >> 4;
- buckets |= buckets >> 8;
- buckets |= buckets >> 16;
-
- b_max = buckets; /* Next power */
- b_min = buckets >> 1; /* Previous power */
-
- /* Calculate the 'nearest' bucket size */
- if (b_min * 4000 / 3000 < b_ori)
- buckets = b_max;
- else
- buckets = b_min;
-
- if (ht) { /* see if we can reuse */
- if (buckets <= ht->buckets) {
- ht->buckets = buckets;
- } else {
- /* free pointers if not allocated inline */
- if (ht->ht != (void *)(ht + 1))
- free(ht->ht, M_DN_HEAP);
- free(ht, M_DN_HEAP);
- ht = NULL;
- }
- }
- if (ht == NULL) {
- /* Allocate buckets + 1 entries because buckets is use to
- * do the AND with the index returned by hash function
- */
- l = sizeof(*ht) + (buckets + 1) * sizeof(void **);
- ht = malloc(l, M_DN_HEAP, M_NOWAIT | M_ZERO);
- }
- if (ht) {
- ht->ht = (void **)(ht + 1);
- ht->buckets = buckets;
- ht->ofs = ofs;
- ht->hash = h;
- ht->match = match;
- ht->newh = newh;
- }
- return ht;
-}
-
-/* dummy callback for dn_ht_free to unlink all */
-static int
-do_del(void *obj, void *arg)
-{
- return DNHT_SCAN_DEL;
-}
-
-void
-dn_ht_free(struct dn_ht *ht, int flags)
-{
- if (ht == NULL)
- return;
- if (flags & DNHT_REMOVE) {
- (void)dn_ht_scan(ht, do_del, NULL);
- } else {
- if (ht->ht && ht->ht != (void *)(ht + 1))
- free(ht->ht, M_DN_HEAP);
- free(ht, M_DN_HEAP);
- }
-}
-
-int
-dn_ht_entries(struct dn_ht *ht)
-{
- return ht ? ht->entries : 0;
-}
-
-/* lookup and optionally create or delete element */
-void *
-dn_ht_find(struct dn_ht *ht, uintptr_t key, int flags, void *arg)
-{
- int i;
- void **pp, *p;
-
- if (ht == NULL) /* easy on an empty hash */
- return NULL;
- i = (ht->buckets == 1) ? 0 :
- (ht->hash(key, flags, arg) & ht->buckets);
-
- for (pp = &ht->ht[i]; (p = *pp); pp = (void **)((char *)p + ht->ofs)) {
- if (flags & DNHT_MATCH_PTR) {
- if (key == (uintptr_t)p)
- break;
- } else if (ht->match(p, key, flags, arg)) /* found match */
- break;
- }
- if (p) {
- if (flags & DNHT_REMOVE) {
- /* link in the next element */
- *pp = *(void **)((char *)p + ht->ofs);
- *(void **)((char *)p + ht->ofs) = NULL;
- ht->entries--;
- }
- } else if (flags & DNHT_INSERT) {
- // printf("%s before calling new, bucket %d ofs %d\n",
- // __FUNCTION__, i, ht->ofs);
- p = ht->newh ? ht->newh(key, flags, arg) : (void *)key;
- // printf("%s newh returns %p\n", __FUNCTION__, p);
- if (p) {
- ht->entries++;
- *(void **)((char *)p + ht->ofs) = ht->ht[i];
- ht->ht[i] = p;
- }
- }
- return p;
-}
-
-/*
- * do a scan with the option to delete the object. Extract next before
- * running the callback because the element may be destroyed there.
- */
-int
-dn_ht_scan(struct dn_ht *ht, int (*fn)(void *, void *), void *arg)
-{
- int i, ret, found = 0;
- void **curp, *cur, *next;
-
- if (ht == NULL || fn == NULL)
- return 0;
- for (i = 0; i <= ht->buckets; i++) {
- curp = &ht->ht[i];
- while ( (cur = *curp) != NULL) {
- next = *(void **)((char *)cur + ht->ofs);
- ret = fn(cur, arg);
- if (ret & DNHT_SCAN_DEL) {
- found++;
- ht->entries--;
- *curp = next;
- } else {
- curp = (void **)((char *)cur + ht->ofs);
- }
- if (ret & DNHT_SCAN_END)
- return found;
- }
- }
- return found;
-}
-
-/*
- * Similar to dn_ht_scan(), except that the scan is performed only
- * in the bucket 'bucket'. The function returns a correct bucket number if
- * the original is invalid.
- * If the callback returns DNHT_SCAN_END, the function move the ht->ht[i]
- * pointer to the last entry processed. Moreover, the bucket number passed
- * by caller is decremented, because usually the caller increment it.
- */
-int
-dn_ht_scan_bucket(struct dn_ht *ht, int *bucket, int (*fn)(void *, void *),
- void *arg)
-{
- int i, ret, found = 0;
- void **curp, *cur, *next;
-
- if (ht == NULL || fn == NULL)
- return 0;
- if (*bucket > ht->buckets)
- *bucket = 0;
- i = *bucket;
-
- curp = &ht->ht[i];
- while ( (cur = *curp) != NULL) {
- next = *(void **)((char *)cur + ht->ofs);
- ret = fn(cur, arg);
- if (ret & DNHT_SCAN_DEL) {
- found++;
- ht->entries--;
- *curp = next;
- } else {
- curp = (void **)((char *)cur + ht->ofs);
- }
- if (ret & DNHT_SCAN_END)
- return found;
- }
- return found;
-}