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;
Thrown when BlackBoard memory has been corupted This exception is thrown by the memory manager if the...
Fawkes library namespace.
chunk_list_t * next
offset to next element in list
unsigned int size
total size of chunk, including overhanging bytes, excluding header
Chunk lists as stored in BlackBoard shared memory segment.
unsigned int overhang
number of overhanging bytes in this chunk
A NULL pointer was supplied where not allowed.
void * ptr
pointer to data memory
Base class for exceptions in Fawkes.
Thrown if shared memory could not be opened.
Thrown if BlackBoard is not master and master operation has been requested.
Could not attach to shared memory segment.
Iterator for memory chunks.
Mutex mutual exclusion lock.