/** ** malloc() allocates size bytes and returns a pointer to the allocated memory. The memory is not cleared. If size is 0, then ** malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free(). */ extern void* bitmap_heap_malloc(size_t size) { void* pointer = NULL; if ( size > 0 ) { int32_t blocks = to_blocks(size); int32_t block; /** Search each heap... */ int lvl = caribou_lib_lock(); for(heap_num=0; heap_num < heap_count; heap_num++) { #if defined(CARIBOU_MPU_ENABLED) heap_state->heap_current_thread = caribou_thread_current(); #endif block = locate_free(HEAP_STATE(heap_num),blocks); if ( block >= 0 ) { pointer = allocate(HEAP_STATE(heap_num),block,blocks); break; } } if ( pointer == NULL ) { notify_heap_alloc_failed(size); } caribou_lib_lock_restore(lvl); } #if defined(CARIBOU_CLEAR_HEAP_MALLOC) if ( pointer ) memset(pointer,0,size); #endif return pointer; }
struct sys_timeouts *sys_arch_timeouts(void) { sys_thread_t thread = lwip_system_threads; caribou_thread_t *self = caribou_thread_current(); // Search the threads list for the thread that is currently running for ( ; thread!=NULL; thread=thread->next) { if (thread->thread == self) return thread->timeouts; } // No match, so just return the system-wide default version return &lwip_system_timeouts; }
/** * @brief * @param tmer A pointer to the timer * @patam timerfn The timer callback function * @param arg Arguments to pass to the callback function * @param flags Timer flags * @return A pointer to the timer or NULL if a problem was encountered. */ caribou_timer_t* caribou_timer_init( caribou_timer_t* timer, caribou_timer_callback_fn* timerfn, void* arg, uint8_t flags ) { caribou_thread_t* thread = caribou_thread_current(); if ( timer ) { memset(timer,0,sizeof(caribou_timer_t)); timer->flags = flags & ~CARIBOU_TIMER_F_DYNAMIC; timer->timerfn = timerfn; timer->fnarg = arg; append_timer_node(thread,timer); } return timer; }
/** * @brief Instantiate a new timer on the heap memory, and associate it with the current thread. * @patam timerfn The timer callback function * @param arg Arguments to pass to the callback function * @param flags Timer flags * @return A pointer to the newly allocated caribou_timer_t* structure instance, * or NULL if a problem was encountered. */ caribou_timer_t* caribou_timer_create( caribou_timer_callback_fn* timerfn, void* arg, uint8_t flags ) { caribou_thread_t* thread = caribou_thread_current(); caribou_timer_t* timer = new_timer_node(timerfn,arg); if ( timer ) { timer->flags = flags | CARIBOU_TIMER_F_DYNAMIC; timer->timerfn = timerfn; timer->fnarg = arg; append_timer_node(thread,timer); } return timer; }
/** * @brief Find the starting block for the heap. Taking into account memory which has been * claimed by MPU protected threads. * @param blocks Return the number of blocks. * @return Starting block number. */ static int32_t block_range(heap_state_t* heap_state, int32_t* blocks) { int32_t rc = 0; *blocks = heap_state->heap_blocks; #if defined(CARIBOU_MPU_ENABLED) if ( heap_state->heap_current_thread->mpu_subregion_cnt ) { caribou_thread_t* thread = caribou_thread_current(); if ( thread ) { if ( thread == HEAP_STATE(heap_num)->heap_thread[ thread->mpu_subregion ] ) { uint32_t subregion_size = HEAP_STATE(heap_num)->heap_subregion_size; rc = subregion_size * thread->mpu_subregion; *blocks = subregion_size / HEAP_BLOCK_SIZE; } } } #endif return rc; }
/** ** realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum ** of the old and new sizes; newly allocated memory will be uninitialized. If ptr is NULL, then the call is equivalent to mal‐ ** loc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). ** Unless ptr is NULL, it must have been returned by an earlier call to malloc() or realloc(). If the area pointed to ** was moved, a free(ptr) is done. */ extern void* bitmap_heap_realloc(void* pointer, size_t size) { if (pointer != NULL && size > 0 ) { int32_t blocks = to_blocks(size); int32_t block=(-1); int32_t used; int lvl = caribou_lib_lock(); /** Search each heap... */ for(heap_num=0; heap_num < heap_count; heap_num++) { block = from_pointer(HEAP_STATE(heap_num),pointer); if ( block >= 0 ) break; } if ( block >= 0 ) { used = blocks_used(HEAP_STATE(heap_num),block); if (blocks > used) { if (!extend(HEAP_STATE(heap_num),block,used,blocks-used)) /* attempt to extend existing block */ { int32_t target; deallocate(HEAP_STATE(heap_num),block,used); /* make currently allocated blocks available to be re-allocated.. */ #if defined(CARIBOU_MPU_ENABLED) heap_state->heap_current_thread = caribou_thread_current(); #endif target = locate_free(HEAP_STATE(heap_num),blocks); /* ...then attempts to locate a sequence of free blocks... */ if (target >= 0 ) { void* pTarget = allocate(HEAP_STATE(heap_num),target,blocks); /* allocate the new blocks... */ memmove(pTarget,pointer,used*HEAP_BLOCK_SIZE); /* ...and move the data to the new area. */ pointer = pTarget; } else { /* * The re-allocation failed in the current heap pool. * It may be possible to get a fit in another pool. */ void* pTarget; if ( (pTarget = bitmap_heap_malloc(size)) != NULL ) { memmove(pTarget,pointer,used*HEAP_BLOCK_SIZE); pointer = pTarget; } else { notify_heap_invalid_realloc(pointer,size); pointer = NULL; } } } } else if (blocks < used) { /* shrink the allocation */ deallocate(HEAP_STATE(heap_num),block,used); allocate(HEAP_STATE(heap_num),block,blocks); } } else { notify_heap_invalid_realloc(pointer,size); pointer = NULL; } caribou_lib_lock_restore(lvl); } else if (pointer != NULL && size == 0) { bitmap_heap_free(pointer); pointer=NULL; } else if (pointer == NULL ) { pointer = bitmap_heap_malloc(size); } return pointer; }