diff --git a/headers/private/kernel/util/datastore.h b/headers/private/kernel/util/datastore.h deleted file mode 100755 index 222b585dee..0000000000 --- a/headers/private/kernel/util/datastore.h +++ /dev/null @@ -1,27 +0,0 @@ -/* General data region of fixed size data blocks - * - * Copyright 2006, Haiku, Inc. All Rights Reserved - * Distributed under the terms of the MIT liscence. - * - * Authors: - * Andrew Galante, haiku.galante@gmail.com - */ - -struct datastore { - void *store; // ptr to data region - size_t blocksize; // size of the blocks in the datastore - size_t blockcount; // total number of blocks in the datastore - int32 *refcounts; // array containing refcounts for each block. a refcount of 0 is a free block - int lastfreed; // index of last freed block - int nextfree; // index of next free block -}; - -status_t init_datastore(struct datastore *store, size_t blocksize, int blockcount); // initializes the datastore -status_t uninit_datastore(struct datastore *store); // frees the memory used by the datastore -void *get_datablock(struct datastore *store); // returns a ptr to the first found free block, and increments its refcount -void *get_datablock(struct datastore *store, void *block); // increments the refcount of the specified block -status_t put_datablock(struct datastore *store, void *block); // decrements the refcount of the specified block - -// not thread safe - for amusement purposes only: -int is_empty_datastore(struct datastore *store); // returns nonzero if all refcounts are zero -int is_full_datastore(struct datastore *store); // returns nonzero if all refcounts are greater than zero diff --git a/src/add-ons/kernel/network/stack/net_buffer.cpp b/src/add-ons/kernel/network/stack/net_buffer.cpp index 0ac9b28e6a..eef21ee27d 100644 --- a/src/add-ons/kernel/network/stack/net_buffer.cpp +++ b/src/add-ons/kernel/network/stack/net_buffer.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -33,6 +32,15 @@ #define MAX_BUFFERS 2048 +struct datastore { + void *store; // ptr to data region + size_t blocksize; // size of the blocks in the datastore + size_t blockcount; // total number of blocks in the datastore + int32 *refcounts; // array containing refcounts for each block. a refcount of 0 is a free block + int lastfreed; // index of last freed block + int nextfree; // index of next free block +}; + struct data_node { struct data_node *next; struct data_node *previous; @@ -53,7 +61,181 @@ struct net_buffer_private : net_buffer { typedef struct net_buffer_private net_buffer_private; -static struct datastore sDatastore; // The structure that manages all the storage space +static struct datastore sDatastore; + // The structure that manages all the storage space + + +// #pragma mark - + + +/*! + Creates a new datastore with \a blockcount datablocks of \a blocksize size + \return B_NO_MEMORY if there is not enough memory to allocate to the datastore + \return B_BAD_VALUE if blockcount is negative +*/ +status_t +init_datastore(struct datastore *store, size_t blocksize, int blockcount) +{ + if (blockcount < 1) + return B_BAD_VALUE; + + store->blocksize = blocksize; + store->blockcount = blockcount; + + store->store = malloc(blocksize * blockcount); + if (store->store == NULL) + return B_NO_MEMORY; + + store->refcounts = (int32 *)calloc(blockcount, sizeof(uint32)); + if (store->refcounts == NULL) + return B_NO_MEMORY; + + store->lastfreed = -1; + store->nextfree = 0; + + return B_OK; +} + + +/*! + * Frees all memory occupied by the datastore, except for the datastore structure itself + */ +status_t +uninit_datastore(struct datastore *store) +{ + store->blocksize = 0; + store->blockcount = 0; + + free(store->store); + store->store = NULL; + free(store->refcounts); + store->refcounts = NULL; + + store->lastfreed = -1; + store->nextfree = 0; + + return B_OK; +} + + +/*! + * Searches the datastore for a free datablock. If none are free, + * continues search until one is freed. + * \return a pointer to the datablock + * \return NULL if the datastore has not been properly initialized + */ +void * +get_datablock(struct datastore *store) +{ + void *block = NULL; + if (store->store == NULL) + return NULL; + + int index = store->lastfreed; + // first check lastfreed index, as that's most likely to be free + if (index >= 0) { + if (atomic_add(&store->refcounts[index], 1) == 0) { + block = (void *)(index * store->blocksize + (uint8 *)store->store); + store->lastfreed = -1; + return block; + } else + atomic_add(&store->refcounts[index], -1); + } + // otherwise start at the "next free" block and search + index = store->nextfree; + while (1) { + if(atomic_add(&store->refcounts[index], 1) == 0) { + // found a free block + block = (void *)(index * store->blocksize + (uint8 *)store->store); + store->nextfree = (index + 1) % store->blockcount; + break; + } else + atomic_add(&store->refcounts[index], -1); + index = (index + 1) % store->blockcount; + } + + return block; +} + + +/*! + * Increments the refcount of the specified block + * \return a reference to the block on success + * \return NULL if there was an error + */ +void * +get_datablock(struct datastore *store, void *block) +{ + if (block == NULL + || block < store->store + || block > (uint8 *)store->store + (store->blocksize * store->blockcount)) + return NULL; + size_t i = ((uint8 *)block - (uint8 *)store->store) / store->blocksize; + + if (atomic_add(&store->refcounts[i], 1) < 0) { + atomic_add(&store->refcounts[i], -1); + return NULL; + } + return block; +} + + +/*! + * Decrements the refcount of the specified block + * \return B_OK on success + * \return B_BAD_VALUE if \a block is not in the datastore \a store + */ +status_t +put_datablock(struct datastore *store, void *block) +{ + if (block == NULL + || block < store->store + || block > (uint8 *)store->store + (store->blocksize * store->blockcount)) + return B_BAD_VALUE; + size_t i = ((uint8 *)block - (uint8 *)store->store) / store->blocksize; + + if (store->refcounts[i] == 0) + return B_OK; + if (atomic_add(&store->refcounts[i], -1) == 1) + if ((store->nextfree - 1) % store->blockcount == i) + store->nextfree = i; + else + store->lastfreed = i; + return B_OK; +} + + +/*! + * Checks if the datastore is empty. + * Not guaranteed to be thread safe! + * \return nonzero if all blocks are free + * \return zero otherwise + */ +int +is_empty_datastore(struct datastore *store) +{ + size_t i; + for (i = 0; i < store->blockcount; i++) + if (store->refcounts[i] != 0) + return 0; + return 1; +} + + +/*! + * Checks if the datastore is occupied + * Not guaranteed to be thread safe! + * \return nonzero if no blocks are free + * \return zero otherwise + */ +int is_full_datastore(struct datastore *store) +{ + size_t i; + for (i = 0; i < store->blockcount; i++) + if (store->refcounts[i] == 0) + return 0; + return 1; +} // #pragma mark - diff --git a/src/system/kernel/util/Jamfile b/src/system/kernel/util/Jamfile index 00d5d91157..b62ff5724d 100644 --- a/src/system/kernel/util/Jamfile +++ b/src/system/kernel/util/Jamfile @@ -4,7 +4,6 @@ UsePrivateHeaders [ FDirName kernel util ] ; KernelMergeObject kernel_util.o : cbuf.c - datastore.cpp kernel_cpp.cpp khash.c list.c diff --git a/src/system/kernel/util/datastore.cpp b/src/system/kernel/util/datastore.cpp deleted file mode 100644 index 24dbad3f9e..0000000000 --- a/src/system/kernel/util/datastore.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* General data region of fixed size data blocks - * - * Copyright 2006, Haiku, Inc. All Rights Reserved - * Distributed under the terms of the MIT liscence. - * - * Authors: - * Andrew Galante : haiku.galante@gmail.com - */ - -#include -#include -#include -#include -#include -#include - -/*! - * Creates a new datastore with \a blockcount datablocks of \a blocksize size - * \return B_NO_MEMORY if there is not enough memory to allocate to the datastore - * \return B_BAD_VALUE if blockcount is negative - */ -status_t -init_datastore(struct datastore *store, size_t blocksize, int blockcount) -{ - if (blockcount < 1) - return B_BAD_VALUE; - - store->blocksize = blocksize; - store->blockcount = blockcount; - - store->store = malloc(blocksize * blockcount); - if (store->store == NULL) - return B_NO_MEMORY; - - store->refcounts = (int32 *)calloc(blockcount, sizeof(uint32)); - if (store->refcounts == NULL) - return B_NO_MEMORY; - - store->lastfreed = -1; - store->nextfree = 0; - - return B_OK; -} - - -/*! - * Frees all memory occupied by the datastore, except for the datastore structure itself - */ -status_t -uninit_datastore(struct datastore *store) -{ - store->blocksize = 0; - store->blockcount = 0; - - free(store->store); - store->store = NULL; - free(store->refcounts); - store->refcounts = NULL; - - store->lastfreed = -1; - store->nextfree = 0; - - return B_OK; -} - - -/*! - * Searches the datastore for a free datablock. If none are free, - * continues search until one is freed. - * \return a pointer to the datablock - * \return NULL if the datastore has not been properly initialized - */ -void * -get_datablock(struct datastore *store) -{ - void *block = NULL; - if (store->store == NULL) - return NULL; - - int index = store->lastfreed; - // first check lastfreed index, as that's most likely to be free - if (index >= 0) { - if (atomic_add(&store->refcounts[index], 1) == 0) { - block = (void *)(index * store->blocksize + (uint8 *)store->store); - store->lastfreed = -1; - return block; - } else - atomic_add(&store->refcounts[index], -1); - } - // otherwise start at the "next free" block and search - index = store->nextfree; - while (1) { - if(atomic_add(&store->refcounts[index], 1) == 0) { - // found a free block - block = (void *)(index * store->blocksize + (uint8 *)store->store); - store->nextfree = (index + 1) % store->blockcount; - break; - } else - atomic_add(&store->refcounts[index], -1); - index = (index + 1) % store->blockcount; - } - - return block; -} - - -/*! - * Increments the refcount of the specified block - * \return a reference to the block on success - * \return NULL if there was an error - */ -void * -get_datablock(struct datastore *store, void *block) -{ - if (block == NULL - || block < store->store - || block > (uint8 *)store->store + (store->blocksize * store->blockcount)) - return NULL; - size_t i = ((uint8 *)block - (uint8 *)store->store) / store->blocksize; - - if (atomic_add(&store->refcounts[i], 1) < 0) { - atomic_add(&store->refcounts[i], -1); - return NULL; - } - return block; -} - - -/*! - * Decrements the refcount of the specified block - * \return B_OK on success - * \return B_BAD_VALUE if \a block is not in the datastore \a store - */ -status_t -put_datablock(struct datastore *store, void *block) -{ - if (block == NULL - || block < store->store - || block > (uint8 *)store->store + (store->blocksize * store->blockcount)) - return B_BAD_VALUE; - size_t i = ((uint8 *)block - (uint8 *)store->store) / store->blocksize; - - if (store->refcounts[i] == 0) - return B_OK; - if (atomic_add(&store->refcounts[i], -1) == 1) - if ((store->nextfree - 1) % store->blockcount == i) - store->nextfree = i; - else - store->lastfreed = i; - return B_OK; -} - - -/*! - * Checks if the datastore is empty. - * Not guaranteed to be thread safe! - * \return nonzero if all blocks are free - * \return zero otherwise - */ -int -is_empty_datastore(struct datastore *store) -{ - size_t i; - for (i = 0; i < store->blockcount; i++) - if (store->refcounts[i] != 0) - return 0; - return 1; -} - - -/*! - * Checks if the datastore is occupied - * Not guaranteed to be thread safe! - * \return nonzero if no blocks are free - * \return zero otherwise - */ -int is_full_datastore(struct datastore *store) -{ - size_t i; - for (i = 0; i < store->blockcount; i++) - if (store->refcounts[i] == 0) - return 0; - return 1; -}