24 #include <blackboard/internal/memory_manager.h>
25 #include <blackboard/exceptions.h>
26 #include <blackboard/shmem/header.h>
28 #include <core/exception.h>
29 #include <core/exceptions/software.h>
30 #include <core/exceptions/system.h>
31 #include <core/threading/mutex.h>
33 #include <utils/ipc/shm.h>
34 #include <utils/ipc/shm_exceptions.h>
47 #define BBMM_MIN_FREE_CHUNK_SIZE sizeof(chunk_list_t)
50 #define chunk_ptr(a) (__shmem ? (chunk_list_t *)__shmem->ptr(a) : a)
51 #define chunk_addr(a) (__shmem ? (chunk_list_t *)__shmem->addr(a) : a)
107 BlackBoardMemoryManager::BlackBoardMemoryManager(
size_t memsize)
110 __shmem_header = NULL;
112 __memory = malloc(memsize);
113 __mutex =
new Mutex();
117 mlock(__memory, __memsize);
125 __free_list_head = f;
126 __alloc_list_head = NULL;
140 BlackBoardMemoryManager::BlackBoardMemoryManager(
size_t memsize,
141 unsigned int version,
143 const char *shmem_token)
158 __shmem_header->set_shared_memory(__shmem);
160 delete __shmem_header;
164 if ( ! __shmem->is_valid() ) {
165 __shmem->set_destroy_on_delete(
false);
167 delete __shmem_header;
171 if ( master && ! __shmem->is_creator() ) {
174 __shmem->set_destroy_on_delete(
false);
176 delete __shmem_header;
185 __shmem->add_semaphore();
189 __shmem->set_swapable(
false);
197 __shmem_header->set_free_list_head(f);
198 __shmem_header->set_alloc_list_head(NULL);
201 __mutex =
new Mutex();
206 BlackBoardMemoryManager::~BlackBoardMemoryManager()
210 delete __shmem_header;
228 BlackBoardMemoryManager::alloc_nolock(
unsigned int num_bytes)
231 chunk_list_t *l = __shmem ? __shmem_header->free_list_head() : __free_list_head;
236 if ( (l->
size >= num_bytes) &&
237 ( (f == NULL) || (l->
size < f->
size) ) ) {
240 l = chunk_ptr(l->
next);
245 throw OutOfMemoryException(
"BlackBoard ran out of memory");
250 __shmem_header->set_free_list_head( list_remove(__shmem_header->free_list_head(), f) );
252 __free_list_head = list_remove(__free_list_head, f);
268 if ( f->
size >= (num_bytes + BBMM_MIN_FREE_CHUNK_SIZE +
sizeof(chunk_list_t)) ) {
270 chunk_list_t *nfc = (chunk_list_t *)((
char *)f +
sizeof(chunk_list_t) + num_bytes);
271 nfc->ptr = __shmem ? __shmem->addr((
char *)nfc +
sizeof(chunk_list_t)) : (
char *)nfc +
sizeof(chunk_list_t);
272 nfc->size = f->
size - num_bytes -
sizeof(chunk_list_t);
276 __shmem_header->set_free_list_head( list_add(__shmem_header->free_list_head(), nfc) );
278 __free_list_head = list_add(__free_list_head, nfc);
291 __shmem_header->set_alloc_list_head( list_add(__shmem_header->alloc_list_head(), f) );
292 return __shmem->ptr(f->
ptr);
294 __alloc_list_head = list_add(__alloc_list_head, f);
310 BlackBoardMemoryManager::alloc(
unsigned int num_bytes)
314 if (__shmem) __shmem->lock_for_write();
316 ptr = alloc_nolock(num_bytes);
318 if (__shmem) __shmem->unlock();
322 if (__shmem) __shmem->unlock();
339 BlackBoardMemoryManager::free(
void *ptr)
343 __shmem->lock_for_write();
346 chunk_list_t *ac = list_find_ptr(__shmem_header->alloc_list_head(), chunk_addr(ptr));
352 __shmem_header->set_alloc_list_head( list_remove(__shmem_header->alloc_list_head(), ac) );
356 __shmem_header->set_free_list_head( list_add(__shmem_header->free_list_head(), ac) );
359 cleanup_free_chunks();
364 chunk_list_t *ac = list_find_ptr(__alloc_list_head, ptr);
370 __alloc_list_head = list_remove(__alloc_list_head, ac);
374 __free_list_head = list_add(__free_list_head, ac);
377 cleanup_free_chunks();
392 BlackBoardMemoryManager::check()
394 chunk_list_t *f = __shmem ? __shmem_header->free_list_head() : __free_list_head;
395 chunk_list_t *a = __shmem ? __shmem_header->alloc_list_head() : __alloc_list_head;
398 unsigned int mem = 0;
405 t = chunk_ptr(a->
next);
409 if ( next != t->
ptr ) {
414 }
else if ( a == NULL ) {
416 t = chunk_ptr(f->
next);
420 if ( next != t->
ptr ) {
425 }
else if ( f->
ptr == a->
ptr ) {
427 }
else if ( f->
ptr < a->
ptr ) {
429 void *next = (
char *)f->
ptr + f->
size;
430 t = chunk_ptr(f->
next);
431 if ( (next != t) && (next != a) ) {
437 void *next = (
char *)a->
ptr + a->
size;
438 t = chunk_ptr(a->
next);
439 if ( (next != t) && (next != f) ) {
446 if ( mem != __memsize ) {
457 BlackBoardMemoryManager::is_master()
const
467 BlackBoardMemoryManager::print_free_chunks_info()
const
469 list_print_info( __shmem ? __shmem_header->free_list_head() : __free_list_head );
477 BlackBoardMemoryManager::print_allocated_chunks_info()
const
479 list_print_info( __shmem ? __shmem_header->alloc_list_head() : __alloc_list_head );
489 BlackBoardMemoryManager::print_performance_info()
const
491 printf(
"free chunks: %6u, alloc chunks: %6u, max free: %10u, max alloc: %10u, overhang: %10u\n",
492 list_length( __shmem ? __shmem_header->free_list_head() : __free_list_head),
493 list_length( __shmem ? __shmem_header->alloc_list_head() : __alloc_list_head),
494 max_free_size(), max_allocated_size(), overhang_size());
504 BlackBoardMemoryManager::max_free_size()
const
506 chunk_list_t *m = list_get_biggest( __shmem ? __shmem_header->free_list_head() : __free_list_head );
523 BlackBoardMemoryManager::free_size()
const
525 unsigned int free_size = 0;
526 chunk_list_t *l = __shmem ? __shmem_header->free_list_head() : __free_list_head;
528 free_size += l->
size;
529 l = chunk_ptr(l->
next);
540 BlackBoardMemoryManager::allocated_size()
const
542 unsigned int alloc_size = 0;
543 chunk_list_t *l = __shmem ? __shmem_header->alloc_list_head() : __alloc_list_head;
545 alloc_size += l->
size;
546 l = chunk_ptr(l->
next);
556 BlackBoardMemoryManager::num_allocated_chunks()
const
558 return list_length( __shmem ? __shmem_header->alloc_list_head() : __alloc_list_head );
566 BlackBoardMemoryManager::num_free_chunks()
const
568 return list_length( __shmem ? __shmem_header->free_list_head() : __free_list_head );
577 BlackBoardMemoryManager::memory_size()
const
587 BlackBoardMemoryManager::version()
const
589 return __shmem ? __shmem_header->version() : 0;
598 BlackBoardMemoryManager::lock()
601 if (__shmem) __shmem->lock_for_write();
612 BlackBoardMemoryManager::try_lock()
614 if ( __mutex->try_lock() ) {
616 if ( __shmem->try_lock_for_write() ) {
634 BlackBoardMemoryManager::unlock()
636 if (__shmem) __shmem->unlock();
647 BlackBoardMemoryManager::max_allocated_size()
const
649 chunk_list_t *m = list_get_biggest( __shmem ? __shmem_header->alloc_list_head() : __alloc_list_head);
664 BlackBoardMemoryManager::overhang_size()
const
666 unsigned int overhang = 0;
667 chunk_list_t *a = __shmem ? __shmem_header->alloc_list_head() : __alloc_list_head;
670 a = chunk_ptr(a->
next);
681 BlackBoardMemoryManager::cleanup_free_chunks()
683 bool modified =
true;
689 l = __shmem ? __shmem_header->free_list_head() : __free_list_head;
690 n = chunk_ptr(l->
next);
699 n = chunk_ptr(l->
next);
712 BlackBoardMemoryManager::list_remove(chunk_list_t *list, chunk_list_t *rmel)
715 throw NullPointerException(
"BlackBoardMemoryManager::list_remove: list == NULL");
717 throw NullPointerException(
"BlackBoardMemoryManager::list_remove: rmel == NULL");
720 chunk_list_t *new_head = list;
721 chunk_list_t *l = list;
722 chunk_list_t *p = NULL;
732 new_head = chunk_ptr(l->next);
737 l = chunk_ptr(l->next);
751 BlackBoardMemoryManager::list_add(chunk_list_t *list, chunk_list_t *addel)
754 throw NullPointerException(
"BlackBoardMemoryManager::list_add: addel == NULL");
756 chunk_list_t *new_head = list;
757 chunk_list_t *l = list;
758 chunk_list_t *p = NULL;
761 if ( addel->ptr < l->ptr ) {
763 addel->next = chunk_addr(l);
767 p->next = chunk_addr(addel);
776 l = chunk_ptr(l->next);
785 p->next = chunk_addr(addel);
801 BlackBoardMemoryManager::list_find_ptr(chunk_list_t *list,
void *ptr)
803 chunk_list_t *l = list;
805 if ( l->ptr == ptr ) {
809 l = chunk_ptr(l->next);
822 BlackBoardMemoryManager::list_print_info(
const chunk_list_t *list)
const
824 chunk_list_t *l = (chunk_list_t *)list;
828 printf(
"Chunk %3u: 0x%x size=%10u bytes overhang=%10u bytes\n",
829 ++i, (
unsigned int)(
size_t)l->ptr, l->size, l->overhang);
830 l = chunk_ptr(l->next);
841 BlackBoardMemoryManager::list_length(
const chunk_list_t *list)
const
846 list = chunk_ptr(list->next);
857 BlackBoardMemoryManager::list_get_biggest(
const chunk_list_t *list)
const
859 chunk_list_t *b = (chunk_list_t *)list;
860 chunk_list_t *l = (chunk_list_t *)list;
862 if ( l->size > b->size ) {
865 l = chunk_ptr(l->next);
874 BlackBoardMemoryManager::ChunkIterator
875 BlackBoardMemoryManager::begin()
890 BlackBoardMemoryManager::end()
905 BlackBoardMemoryManager::ChunkIterator::ChunkIterator()
915 BlackBoardMemoryManager::ChunkIterator::ChunkIterator(
SharedMemory *shmem,
926 BlackBoardMemoryManager::ChunkIterator::ChunkIterator(
chunk_list_t *cur)
936 BlackBoardMemoryManager::ChunkIterator::ChunkIterator(
const ChunkIterator &it)
938 __shmem = it.__shmem;
954 BlackBoardMemoryManager::ChunkIterator::operator++()
956 if ( __cur != NULL ) __cur = chunk_ptr(__cur->next);
978 BlackBoardMemoryManager::ChunkIterator::operator++(
int inc)
981 if ( __cur != NULL ) __cur = chunk_ptr(__cur->next);
996 BlackBoardMemoryManager::ChunkIterator::operator+(
unsigned int i)
998 for (
unsigned int j = 0; (__cur != NULL) && (j < i); ++j) {
999 if ( __cur != NULL ) __cur = chunk_ptr(__cur->next);
1012 BlackBoardMemoryManager::ChunkIterator::operator+=(
unsigned int i)
1014 for (
unsigned int j = 0; (__cur != NULL) && (j < i); ++j) {
1015 if ( __cur != NULL ) __cur = chunk_ptr(__cur->next);
1027 BlackBoardMemoryManager::ChunkIterator::operator==(
const ChunkIterator & c)
const
1029 return (__cur == c.__cur);
1039 BlackBoardMemoryManager::ChunkIterator::operator!=(
const ChunkIterator & c)
const
1041 return (__cur != c.__cur);
1051 BlackBoardMemoryManager::ChunkIterator::operator*()
const
1053 if ( __cur == NULL )
return NULL;
1055 if (__shmem)
return __shmem->ptr(__cur->ptr);
1056 else return __cur->ptr;
1068 __shmem = c.__shmem;
1079 BlackBoardMemoryManager::ChunkIterator::size()
const
1081 return ( __cur != NULL ) ? __cur->
size : 0;
1091 BlackBoardMemoryManager::ChunkIterator::overhang()
const
1093 return ( __cur != NULL ) ? __cur->overhang : 0;