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 task with handle * Here we assume the state has been initialized. * We just need to link to the bin */ static int8_t sched_register_module(sos_module_t *h, mod_header_ptr p, void *init, uint8_t init_size) { HAS_CRITICAL_SECTION; uint8_t num_timers; uint8_t bins = hash_pid(h->pid); if(ker_get_module(h->pid) != NULL) { return -EEXIST; //ker_deregister_module(h->pid); DEBUG("Module %d is already registered\n", h->pid); } //! Read the number of timers to be pre-allocated num_timers = sos_read_header_byte(p, offsetof(mod_header_t, num_timers)); if (num_timers > 0){ //! If there is no memory to pre-allocate the requested timers if (timer_preallocate(h->pid, num_timers) < 0){ return -ENOMEM; } } // link the functions fntable_link(h); ENTER_CRITICAL_SECTION(); /** * here is critical section. * We need to prevent others to search this module */ // add to the bin h->next = mod_bin[bins]; mod_bin[bins] = h; LEAVE_CRITICAL_SECTION(); DEBUG("Register %d, Code ID %d, Handle = %x\n", h->pid, sos_read_header_byte(h, offsetof(mod_header_t, mod_id)), (unsigned int)h); // send an init message to application // XXX : need to check the failure if(post_long(h->pid, KER_SCHED_PID, MSG_INIT, init_size, init, SOS_MSG_RELEASE | SOS_MSG_SYSTEM_PRIORITY) != SOS_OK) { timer_remove_all(h->pid); return -ENOMEM; } return SOS_OK; }
int8_t sched_register_kernel_module(sos_module_t *handle, mod_header_ptr h, void *state_ptr) { sos_pid_t pid; if(h == 0) return -EINVAL; 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; handle->handler_state = state_ptr; handle->pid = pid; handle->header = h; handle->flag = SOS_KER_STATIC_MODULE; handle->next = NULL; return sched_register_module(handle, h, NULL, 0); }
//---------------------------------------------------------- int8_t sfi_get_domain_id(sos_pid_t pid) { #ifdef SFI_DOMS_2 return MOD_DOM_ID; #endif #ifdef SFI_DOMS_8 int8_t retdomid; // Ram - For the time being assign all kernel PIDs to be // KER_DOM_ID sos_module_t* handle; if (pid < APP_MOD_MIN_PID){ retdomid = KER_DOM_ID; } else{ handle = ker_get_module(pid); if (NULL == handle) return -EINVAL; retdomid = sos_read_header_byte(handle->header, offsetof(mod_header_t, dom_id)); } return retdomid; #endif }
int8_t timer_micro_reboot(sos_module_t *handle){ sos_pid_t pid; list_link_t *link; mod_header_ptr hdr; uint8_t num_timers_left; pid = handle->pid; hdr = handle->header; num_timers_left = sos_read_header_byte(hdr, offsetof(mod_header_t, num_timers)); DEBUG("Timer: Pre-alloc timers requested %d \n", num_timers_left); if (num_timers_left > 0){ for (link = prealloc_timer_pool.l_next; link != (&prealloc_timer_pool); link = link->l_next){ sos_timer_t *h = (sos_timer_t*)link; if (h->pid == pid) num_timers_left--; // Assert - This value should NEVER become negative } } DEBUG("Timer: Timers left to pre-allocate %d \n", num_timers_left); //! Stop all timers of pid //! Move timer blocks to the pre-allocated pool //! or free them for (link = deltaq.l_next; link != (&deltaq); link = link->l_next){ sos_timer_t *h = (sos_timer_t*)link; if (h->pid == pid){ link = link->l_prev; timer_remove_timer(h); if (num_timers_left > 0){ num_timers_left--; timer_pre_alloc_block_init(h, pid); DEBUG("Timer: Allocated active timer \n"); } else ker_free(h); } } //! Remove all initialized timers //! Move timer blocks to the pre-allocated pool //! or free them for (link = timer_pool.l_next; link != (&timer_pool); link = link->l_next){ sos_timer_t *h = (sos_timer_t*)link; if (h->pid == pid){ link = link->l_prev; list_remove((list_link_t*)h); if (num_timers_left > 0){ num_timers_left--; timer_pre_alloc_block_init(h, pid); DEBUG("Timer: Allocated an initialzed but non-running timer\n"); } else ker_free(h); } } //! If necessary, allocate memory for the pre-allocated timers if (num_timers_left > 0){ DEBUG("Timer: Alloc more memory for timers\n"); if (timer_preallocate(pid, num_timers_left) != SOS_OK) return -ENOMEM; } return SOS_OK; }
static int8_t handle_fetcher_done( Message *msg ) { fetcher_state_t *f = (fetcher_state_t*) msg->data; if( is_fetcher_succeed( f ) == true ) { //mod_header_ptr p; loader_cam_t *cam; fetcher_commit(f, true); st.blocked = 0; restartInterval( 0 ); cam = ker_cam_lookup( f->map.key ); if( cam->fetcher.fetchtype == FETCHTYPE_DATA) { uint8_t buf[2]; ker_codemem_read( cam->fetcher.cm, KER_DFT_LOADER_PID, buf, 2, 0); post_short(buf[0], KER_DFT_LOADER_PID, MSG_LOADER_DATA_AVAILABLE, buf[1], cam->fetcher.cm, 0); DEBUG_PID(KER_DFT_LOADER_PID, "Data Ready\n" ); #ifdef LOADER_NET_EXPERIMENT ker_led(LED_GREEN_TOGGLE); #endif } else { uint8_t mcu_type; #ifndef SOS_SIM uint8_t plat_type; #endif mod_header_ptr p; #ifdef MINIELF_LOADER // Link and load the module here melf_load_module(cam->fetcher.cm); #endif//MINIELF_LOADER // Get the address of the module header p = ker_codemem_get_header_address( cam->fetcher.cm ); // get processor type and platform type mcu_type = sos_read_header_byte(p, offsetof( mod_header_t, processor_type )); #ifdef SOS_SIM if( (mcu_type == MCU_TYPE) ) // In simulation, we don't check for platform #else plat_type = sos_read_header_byte(p, offsetof( mod_header_t, platform_type )); if( (mcu_type == MCU_TYPE) && ( plat_type == HW_TYPE || plat_type == PLATFORM_ANY) ) #endif { /* * If MCU is matched, this means we are using the same * instruction set. * And if this module is for this *specific* platform or * simply for all platform with the same MCU */ // mark module executable ker_codemem_mark_executable( cam->fetcher.cm ); if (cam->version & 0x80) { #ifdef SOS_SFI #ifdef MINIELF_LOADER sfi_modtable_register(cam->fetcher.cm); if (SOS_OK == ker_verify_module(cam->fetcher.cm)){ sfi_modtable_flash(p); ker_register_module(p); } else sfi_exception(KER_VERIFY_FAIL_EXCEPTION); #else uint16_t init_offset, code_size, handler_addr; uint32_t handler_byte_addr, module_start_byte_addr; uint16_t handler_sfi_addr; handler_sfi_addr = sos_read_header_ptr(p, offsetof(mod_header_t, module_handler)); handler_addr = sfi_modtable_get_real_addr(handler_sfi_addr); handler_byte_addr = (handler_addr * 2); module_start_byte_addr = (p * 2); init_offset = (uint16_t)(handler_byte_addr - module_start_byte_addr); code_size = cam->code_size * LOADER_SIZE_MULTIPLIER; if (SOS_OK == ker_verify_module(cam->fetcher.cm, init_offset, code_size)){ sfi_modtable_flash(p); ker_register_module(p); } else sfi_exception(KER_VERIFY_FAIL_EXCEPTION); #endif //MINIELF_LOADER #else ker_register_module(p); #endif //SOS_SFI } } } process_version_data( st.version_data, st.recent_neighbor); } else { DEBUG_PID( KER_DFT_LOADER_PID, "Fetch failed!, request %d\n", st.recent_neighbor); f = (fetcher_state_t*) ker_msg_take_data(KER_DFT_LOADER_PID, msg); fetcher_restart( f, st.recent_neighbor ); } return SOS_OK; }