@ -53,310 +53,73 @@
# include <string.h>
# include <search.h>
# include <unistd.h>
# include <stdint.h>
# include "tr/memory.h"
# include "tr/tree_macros.h"
struct memSegment
{
size_t ref_count ;
size_t size ;
int idx ;
void * ptr ;
TR_rbColor color ;
struct memSegment * data ;
struct memSegment * next ;
struct memSegment * last ;
struct memSegment * parent ;
struct memSegment * left ;
struct memSegment * right ;
} ;
static
struct memSegment *
newElement ( size_t size )
newElement ( size_t size , int idx )
{
struct memSegment * element = malloc ( size ) ;
element - > ref_count = 1 ;
element - > size = size ;
element - > idx = idx ;
element - > ptr = ( void * ) element + sizeof ( struct memSegment ) ;
element - > data = element ;
element - > next = NULL ;
element - > last = NULL ;
element - > color = rbRed ;
element - > parent = NULL ;
element - > left = NULL ;
element - > right = NULL ;
return element ;
}
# ifdef MEM_OPT
static
int
_memSegmentFindCompare ( const void * a , const void * b )
{
struct memSegment * _a = ( struct memSegment * ) a ;
size_t _b = * ( size_t * ) b ;
/*
* find the smallest bigger or equal size segment
*/
return _a - > size < _b ? - 1
: _a - > size > _b & & _a - > left & & _a - > left - > size > = _b ? 1 : 0 ;
}
static
int
_memSegmentCompare ( const void * a , const void * b )
{
size_t _a = ( ( struct memSegment * ) a ) - > size ;
size_t _b = ( ( struct memSegment * ) b ) - > size ;
return _a < _b ? - 1 : _a > _b ? 1 : 0 ;
}
/**
* insert element in tree
*/
static
inline
struct memSegment *
insertElement ( struct memSegment * * tree , struct memSegment * element )
insertElement ( struct memSegment * * stack , struct memSegment * element )
{
struct memSegment * node = * tree ;
struct memSegment * new_node = NULL ;
int found ;
element - > next = NULL ;
element - > last = NULL ;
element - > color = rbRed ;
element - > parent = NULL ;
element - > left = NULL ;
element - > right = NULL ;
TR_TREE_FIND ( node , element , found , _memSegmentCompare ) ;
/ / if tree is empty it ' s simple . . . : )
if ( NULL = = node ) {
* tree = node = new_node = element ;
} else {
/ / normal binary tree add . . . .
if ( found = = 0 ) {
if ( NULL = = node - > next ) {
node - > next = element ;
node - > last = element ;
} else {
node - > last - > next = element ;
node - > last = element ;
}
return node ;
} else {
if ( 0 < found ) {
node - > left = element ;
node - > left - > parent = node ;
new_node = node = node - > left ;
} else {
node - > right = element ;
node - > right - > parent = node ;
new_node = node = node - > right ;
element - > next = * stack ;
* stack = element ;
}
}
}
/*
* handle reballancing rb style
*/
TR_TREE_BALANCE_INSERT ( tree , node ) ;
return new_node ;
return element ;
}
static
inline
struct memSegment *
deleteElement ( struct memSegment * * tree , size_t size )
deleteElement ( struct memSegment * * stack )
{
struct memSegment * node = * tree ;
struct memSegment * del_node ;
struct memSegment * child ;
struct memSegment * s ;
int found ;
/ / find the relevant node and it ' s parent
TR_TREE_FIND ( node , & size , found , _memSegmentFindCompare ) ;
struct memSegment * del_node = * stack ;
/ / while ( node ) {
if ( found ! = 0 ) {
return NULL ;
} else {
if ( NULL ! = node - > next ) {
if ( NULL ! = node - > parent ) {
if ( node = = node - > parent - > left ) {
node - > parent - > left = node - > next ;
} else {
node - > parent - > right = node - > next ;
}
} else {
* tree = node - > next ;
}
if ( NULL ! = node - > left ) {
node - > left - > parent = node - > next ;
}
if ( NULL ! = node - > right ) {
node - > right - > parent = node - > next ;
}
node - > next - > last = node - > last ;
node - > next - > color = node - > color ;
node - > next - > parent = node - > parent ;
node - > next - > left = node - > left ;
node - > next - > right = node - > right ;
return node ;
}
if ( * stack ) {
* stack = ( * stack ) - > next ;
}
del_node = node ;
/ / now our cases follows . . . the first one is the same as with
/ / simple binary search trees . Two non null children .
/ / case 1 : two children
if ( NULL ! = node - > left & & NULL ! = node - > right ) {
struct memSegment * successor ;
struct memSegment * tmpparent ;
struct memSegment * tmpleft ;
struct memSegment * tmpright ;
TR_rbColor tmpcolor ;
TR_TREE_INORDER_SUCC ( node , successor ) ;
tmpparent = successor - > parent ;
tmpleft = successor - > left ;
tmpright = successor - > right ;
tmpcolor = successor - > color ;
TR_TREE_REPLACE_NODE ( tree , node , successor ) ;
successor - > color = node - > color ;
successor - > left = node - > left ;
successor - > left - > parent = successor ;
/ / the right one might be successor . . .
if ( node - > right = = successor ) {
successor - > right = node ;
node - > parent = successor ;
} else {
successor - > right = node - > right ;
node - > right - > parent = successor ;
node - > parent = tmpparent ;
tmpparent - > left = node ;
}
node - > color = tmpcolor ;
node - > left = tmpleft ;
node - > right = tmpright ;
}
/ / Precondition : n has at most one non - null child .
child = ( NULL = = node - > right ) ? node - > left : node - > right ;
TR_TREE_REPLACE_NODE ( tree , node , child ) ;
/ / delete one child case
/ / TODO this is overly complex as simply derived from the function . . .
/ / maybe this can be simplified . Maybe not . . . check .
if ( node - > color = = rbBlack ) {
if ( NULL ! = child & & child - > color = = rbRed ) {
child - > color = rbBlack ;
/ / done despite modifying tree itself if neccessary . .
return del_node ;
} else {
if ( NULL ! = child ) {
node = child ;
} else {
node - > color = rbBlack ;
node - > left = NULL ;
node - > right = NULL ;
}
}
} else {
return del_node ;
}
TR_TREE_BALANCE_DELETE ( tree , node , s ) ;
return del_node ;
return del_node ;
}
static
void
post ( struct memSegment * tree , void ( * cb ) ( struct memSegment * , int ) )
{
struct memSegment * previous = tree ;
struct memSegment * node = tree ;
int depth = 1 ;
/*
* I think this has something like O ( n + log ( n ) ) on a ballanced
* tree because I have to traverse back the rightmost leaf to
* the root to get a break condition .
*/
while ( node ) {
/*
* If we come from the right so nothing and go to our
* next parent .
*/
if ( ( ( NULL = = node - > left | | previous = = node - > left )
& & NULL = = node - > right )
| | previous = = node - > right ) {
struct memSegment * parent = node - > parent ;
cb ( node , depth ) ;
previous = node ;
node = parent ;
depth - - ;
continue ;
}
# define TR_MAX_MEM_IDX 1024
if ( ( NULL = = node - > left | | previous = = node - > left ) ) {
/*
* If there are no more elements to the left or we
* came from the left , process data .
*/
previous = node ;
if ( NULL ! = node - > right ) {
node = node - > right ;
depth + + ;
} else {
node = node - > parent ;
depth - - ;
}
} else {
/*
* if there are more elements to the left go there .
*/
previous = node ;
node = node - > left ;
depth + + ;
}
}
}
struct memSegment * segments = NULL ;
struct memSegment * segments [ TR_MAX_MEM_IDX ] = { } ;
pthread_mutex_t TR_memop_lock = PTHREAD_MUTEX_INITIALIZER ;
static
inline
void
segmentFree ( struct memSegment * segment , int depth )
{
@ -378,8 +141,6 @@ TR_reference(void * mem)
return mem ;
}
pthread_mutex_t TR_memop_lock = PTHREAD_MUTEX_INITIALIZER ;
/*
* This tries to reflect the memory management behaviour of the
* GNU version of malloc . For other versions this might need
@ -410,41 +171,60 @@ pthread_mutex_t TR_memop_lock = PTHREAD_MUTEX_INITIALIZER;
void *
TR_malloc ( size_t size )
{
struct memSegment * seg = NULL ;
long psize = sysconf ( _SC_PAGESIZE ) ;
struct memSegment * seg = NULL ;
long psize = sysconf ( _SC_PAGESIZE ) ;
static int psize_width = 0 ;
int idx ;
if ( psize_width = = 0 ) psize_width = bitwidth ( psize ) ;
size + = sizeof ( struct memSegment ) ;
if ( size > psize ) {
if ( 0 ! = ( size % psize ) ) {
/ / size if not a multiple of pagesize so bring it to one .
size = ( ( size / psize ) + 1 ) * psize ;
}
} else {
if ( size < 8 ) {
size = 8 ;
} else {
size_t check = size > > 4 ;
size_t mask = 0x1F ;
# define MIN_BITS 8
while ( check > > = 1 ) {
mask = ( mask < < 1 ) | 1 ;
}
if ( size > = psize ) {
idx = size / psize ;
if ( size ! = ( size & ~ ( mask > > 1 ) ) ) {
size = ( size < < 1 ) & ~ mask ;
}
}
}
if ( 0 ! = ( size % psize ) ) {
/ / size if not a multiple of pagesize so bring it to one .
size = ( idx + 1 ) * psize ;
idx + + ;
}
idx + = psize_width - MIN_BITS ;
} else {
if ( size < = 1 < < ( MIN_BITS - 1 ) ) {
size = 1 < < ( MIN_BITS - 1 ) ;
idx = 0 ;
} else {
size_t mask ;
idx = bitwidth ( size ) ;
mask = ( 1 < < ( idx + 1 ) ) - 1 ;
idx - = ( MIN_BITS - 1 ) ;
if ( size ! = ( size & ~ ( mask > > 1 ) ) ) {
size = ( size < < 1 ) & ~ mask ;
idx + + ;
}
}
}
# undef MIN_BITS
# ifdef MEM_OPT
pthread_mutex_lock ( & TR_memop_lock ) ;
seg = deleteElement ( & segments , size ) ;
pthread_mutex_unlock ( & TR_memop_lock ) ;
if ( idx < TR_MAX_MEM_IDX ) {
pthread_mutex_lock ( & TR_memop_lock ) ;
seg = deleteElement ( & ( segments [ idx ] ) ) ;
pthread_mutex_unlock ( & TR_memop_lock ) ;
} else
# endif
{
idx = - 1 ;
}
if ( NULL = = seg ) {
seg = newElement ( size ) ;
seg = newElement ( size , idx ) ;
}
return seg - > ptr ;
@ -479,12 +259,15 @@ TR_free(void ** mem)
seg - > ref_count - - ;
} else {
# ifdef MEM_OPT
pthread_mutex_lock ( & TR_memop_lock ) ;
insertElement ( & segments , seg ) ;
pthread_mutex_unlock ( & TR_memop_lock ) ;
# else
free ( seg ) ;
if ( - 1 ! = seg - > idx ) {
pthread_mutex_lock ( & TR_memop_lock ) ;
insertElement ( & ( segments [ seg - > idx ] ) , seg ) ;
pthread_mutex_unlock ( & TR_memop_lock ) ;
} else
# endif
{
free ( seg ) ;
}
}
* mem = NULL ;
@ -508,7 +291,15 @@ void
TR_cleanup ( )
{
# ifdef MEM_OPT
post ( segments , segmentFree ) ;
int i ;
for ( i = 0 ; i < TR_MAX_MEM_IDX ; i + + ) {
while ( segments [ i ] ) {
struct memSegment * next = segments [ i ] - > next ;
free ( segments [ i ] ) ;
segments [ i ] = next ;
}
}
# endif
}