int8_t ker_slab_init( sos_pid_t pid, slab_t *slab, uint8_t item_size, uint8_t items_per_pool, uint8_t flag ) { uint8_t i; if( items_per_pool > 8 ) { return -EINVAL; } // // build empty vector // slab->head = NULL; slab->num_items_per_pool = items_per_pool; slab->empty_vector = 0; slab->item_size = item_size; slab->flag = flag; for( i = 0; i < items_per_pool; i++ ) { slab->empty_vector <<= 1; slab->empty_vector |= 0x01; } if( slab->flag & SLAB_LONGTERM ) { slab->head = malloc_longterm( sizeof( slab_item_t ) + items_per_pool * item_size, pid ); } else { slab->head = ker_malloc( sizeof( slab_item_t ) + items_per_pool * item_size, pid ); } if( slab->head == NULL ) { return -ENOMEM; } slab->head->next = NULL; slab->head->alloc = 0; slab->head->gc_mark = 0; return SOS_OK; }
/** * @brief Pre-allocate timers for a module at load time */ int8_t timer_preallocate(sos_pid_t pid, uint8_t num_timers) { // We have already checked if num_timer > 0 and pid is not NULL_PID uint8_t i, j; sos_timer_t* tt[MAX_PRE_ALLOCATED_TIMERS]; //! We cannot allow a single module to pre allocate a lot of timers if (num_timers > MAX_PRE_ALLOCATED_TIMERS) return -EINVAL; //! First try to safely allocate memory blocks for all the pre-allocated timers for (i = 0; i < num_timers; i++){ tt[i] = (sos_timer_t*)malloc_longterm(sizeof(sos_timer_t), TIMER_PID); if (tt[i] == NULL){ for (j = 0; j < i; j++){ ker_free(tt[j]); } return -ENOMEM; } } //! If we get here then we have all the memory allocated //! Now initialize all the data structures and just add them to the timer pool for (i = 0; i < num_timers; i++){ timer_pre_alloc_block_init(tt[i], pid); } return SOS_OK; }
void* ker_slab_alloc( slab_t *slab, sos_pid_t pid ) { slab_item_t *itr = slab->head; slab_item_t *prev = slab->head; while( itr != NULL ) { DEBUG(" itr->alloc = %x\n", itr->alloc); if( itr->alloc != slab->empty_vector ) { break; } prev = itr; itr = itr->next; } if( itr == NULL ) { // // The pool is exhausted, create a new one // DEBUG("pool exhausted\n"); if( slab->flag & SLAB_LONGTERM ) { prev->next = malloc_longterm( sizeof( slab_item_t ) + slab->num_items_per_pool * slab->item_size, pid ); } else { prev->next = ker_malloc( sizeof( slab_item_t ) + slab->num_items_per_pool * slab->item_size, pid ); } if( prev->next == NULL ) { DEBUG("alloc NULL\n"); return NULL; } itr = prev->next; itr->next = NULL; itr->alloc = 0x01; itr->gc_mark = 0; return itr->mem; } else { uint8_t i; uint8_t mask = 0x01; DEBUG("find free slot in pool\n"); for( i = 0; i < slab->num_items_per_pool; i++, mask<<=1 ) { if( (itr->alloc & mask) == 0 ) { itr->alloc |= mask; return itr->mem + (i * slab->item_size); } } } return NULL; }
static int8_t do_register_module(mod_header_ptr h, sos_module_t *handle, void *init, uint8_t init_size, uint8_t flag) { sos_pid_t pid; uint8_t st_size; int8_t ret; // Disallow usage of NULL_PID if (flag == SOS_CREATE_THREAD) { pid = sched_get_pid_from_pool(); if (pid == NULL_PID) return -ENOMEM; } else { pid = sos_read_header_byte(h, offsetof(mod_header_t, mod_id)); /* * Disallow the usage of thread ID */ if (pid > APP_MOD_MAX_PID) return -EINVAL; } // Read the state size and allocate a separate memory block for it st_size = sos_read_header_byte(h, offsetof(mod_header_t, state_size)); //DEBUG("registering module pid %d with size %d\n", pid, st_size); if (st_size){ //handle->handler_state = (uint8_t*)ker_malloc(st_size, pid); handle->handler_state = (uint8_t*)malloc_longterm(st_size, KER_SCHED_PID); // If there is no memory to store the state of the module if (handle->handler_state == NULL){ return -ENOMEM; } } else { handle->handler_state = NULL; } // Initialize the data structure handle->header = h; handle->pid = pid; handle->flag = 0; handle->next = NULL; // add to the bin ret = sched_register_module(handle, h, init, init_size); if(ret != SOS_OK) { ker_free(handle->handler_state); //! Free the memory block to hold module state return ret; } return SOS_OK; }
/** * @brief register new module * NOTE: this function cannot be called in the interrupt handler * That is, the function is not thread safe * NOTE: h is stored in program memory, which can be different from RAM * special access function is needed. */ int8_t ker_register_module(mod_header_ptr h) { sos_module_t *handle; int8_t ret; if(h == 0) return -EINVAL; handle = (sos_module_t*)malloc_longterm(sizeof(sos_module_t), KER_SCHED_PID); if (handle == NULL) { return -ENOMEM; } ret = do_register_module(h, handle, NULL, 0, 0); if(ret != SOS_OK) { ker_free(handle); } ker_change_own(handle->handler_state, handle->pid); return ret; }
sos_pid_t ker_spawn_module(mod_header_ptr h, void *init, uint8_t init_size, uint8_t flag) { sos_module_t *handle; if(h == 0) return NULL_PID; // Allocate a memory block to hold the module list entry //handle = (sos_module_t*)ker_malloc(sizeof(sos_module_t), KER_SCHED_PID); handle = (sos_module_t*)malloc_longterm(sizeof(sos_module_t), KER_SCHED_PID); if (handle == NULL) { return NULL_PID; } if( do_register_module(h, handle, init, init_size, flag) != SOS_OK) { ker_free(handle); return NULL_PID; } return handle->pid; }
//! Assumption - This function is never called from an interrupt context int8_t ker_timer_init(sos_pid_t pid, uint8_t tid, uint8_t type) { sos_timer_t* tt; tt = find_timer_in_periodic_pool(pid, tid); if (tt != NULL) { tt->type = type; list_insert_tail(&timer_pool, (list_link_t*)tt); return SOS_OK; } //! re-initialize an existing timer by stoping it and updating the type tt = find_timer_block(pid, tid); if (tt != NULL){ ker_timer_stop(pid,tid); tt->type = type; return SOS_OK; } //! Search if pre-initialized timer exists tt = alloc_from_timer_pool(pid, tid); //! Look for pre-allocated timers or try to get dynamic memory if (tt == NULL){ tt = alloc_from_preallocated_timer_pool(pid); if (tt == NULL){ tt = (sos_timer_t*)malloc_longterm(sizeof(sos_timer_t), TIMER_PID); } //! Init will fail if the system does not have sufficient resources if (tt == NULL) return -ENOMEM; } //! Fill up the data structure and insert into the timer pool tt->pid = pid; tt->tid = tid; tt->type = type; list_insert_tail(&timer_pool, (list_link_t*)tt); return SOS_OK; }