/* * Returns an object describing the free memory. * * sysfree: free system heap bytes * jssize: size of JS heap in bytes * jsfree: free JS heap bytes * strres: size of reserved string heap in bytes * struse: portion of string heap with used data * objnfree: number of free object slots in js heap * propnfree: number of free property slots in js heap * funcnfree: number of free function slots in js heap */ SJ_PRIVATE enum v7_err GC_stat(struct v7 *v7, v7_val_t *res) { /* take a snapshot of the stats that would change as we populate the result */ size_t sysfree = sj_get_free_heap_size(); size_t jssize = v7_heap_stat(v7, V7_HEAP_STAT_HEAP_SIZE); size_t jsfree = jssize - v7_heap_stat(v7, V7_HEAP_STAT_HEAP_USED); size_t strres = v7_heap_stat(v7, V7_HEAP_STAT_STRING_HEAP_RESERVED); size_t struse = v7_heap_stat(v7, V7_HEAP_STAT_STRING_HEAP_USED); size_t objfree = v7_heap_stat(v7, V7_HEAP_STAT_OBJ_HEAP_FREE); size_t propnfree = v7_heap_stat(v7, V7_HEAP_STAT_PROP_HEAP_FREE); *res = v7_mk_object(v7); v7_set(v7, *res, "sysfree", ~0, v7_mk_number(sysfree)); v7_set(v7, *res, "jssize", ~0, v7_mk_number(jssize)); v7_set(v7, *res, "jsfree", ~0, v7_mk_number(jsfree)); v7_set(v7, *res, "strres", ~0, v7_mk_number(strres)); v7_set(v7, *res, "struse", ~0, v7_mk_number(struse)); v7_set(v7, *res, "objfree", ~0, v7_mk_number(objfree)); v7_set(v7, *res, "objncell", ~0, v7_mk_number(v7_heap_stat(v7, V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE))); v7_set(v7, *res, "propnfree", ~0, v7_mk_number(propnfree)); v7_set(v7, *res, "propncell", ~0, v7_mk_number(v7_heap_stat(v7, V7_HEAP_STAT_PROP_HEAP_CELL_SIZE))); v7_set(v7, *res, "funcnfree", ~0, v7_mk_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_HEAP_FREE))); v7_set(v7, *res, "funcncell", ~0, v7_mk_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE))); v7_set(v7, *res, "astsize", ~0, v7_mk_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_AST_SIZE))); v7_set(v7, *res, "owned", ~0, v7_mk_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_OWNED))); v7_set(v7, *res, "owned_max", ~0, v7_mk_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_OWNED_MAX))); return V7_OK; }
static enum v7_err Sys_prof(struct v7 *v7, v7_val_t *res) { *res = v7_mk_object(v7); v7_set(v7, *res, "sysfree", 7, v7_mk_number(sj_get_free_heap_size())); v7_set(v7, *res, "used_by_js", 10, v7_mk_number(v7_heap_stat(v7, V7_HEAP_STAT_HEAP_USED))); v7_set(v7, *res, "used_by_fs", 10, v7_mk_number(sj_get_fs_memory_usage())); return V7_OK; }
static void show_prompt(void) { /* * Flashnchips relies on prompt ending with "$ " to detect when it's okay * to send the next line during file upload. */ printf("smartjs %u/%d$ ", sj_get_free_heap_size(), v7_heap_stat(s_sjp.v7, V7_HEAP_STAT_HEAP_SIZE) - v7_heap_stat(s_sjp.v7, V7_HEAP_STAT_HEAP_USED)); s_sjp.pos = 0; s_sjp.char_processor = process_prompt_char; }
static v7_val_t OS_prof(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t result = v7_create_object(v7); v7_own(v7, &result); v7_set(v7, result, "sysfree", 7, 0, v7_create_number(sj_get_free_heap_size())); v7_set(v7, result, "used_by_js", 10, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_HEAP_USED))); v7_set(v7, result, "used_by_fs", 10, 0, v7_create_number(sj_get_fs_memory_usage())); v7_disown(v7, &result); return result; }
static void show_prompt(void) { /* * Flashnchips relies on prompt ending with "$ " to detect when it's okay * to send the next line during file upload. */ /* TODO RTOS(alashkin): RTOS printf doesn't support %lu */ printf("smartjs %u/%d$ ", (unsigned int) sj_get_free_heap_size(), (int) v7_heap_stat(s_sjp.v7, V7_HEAP_STAT_HEAP_SIZE) - (int) v7_heap_stat(s_sjp.v7, V7_HEAP_STAT_HEAP_USED)); fflush(stdout); s_sjp.pos = 0; s_sjp.char_processor = process_prompt_char; }
/* * Returns an object describing the free memory. * * sysfree: free system heap bytes * jssize: size of JS heap in bytes * jsfree: free JS heap bytes * strres: size of reserved string heap in bytes * struse: portion of string heap with used data * objnfree: number of free object slots in js heap * propnfree: number of free property slots in js heap * funcnfree: number of free function slots in js heap */ static v7_val_t GC_stat(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { /* take a snapshot of the stats that would change as we populate the result */ size_t sysfree = sj_get_free_heap_size(); size_t jssize = v7_heap_stat(v7, V7_HEAP_STAT_HEAP_SIZE); size_t jsfree = jssize - v7_heap_stat(v7, V7_HEAP_STAT_HEAP_USED); size_t strres = v7_heap_stat(v7, V7_HEAP_STAT_STRING_HEAP_RESERVED); size_t struse = v7_heap_stat(v7, V7_HEAP_STAT_STRING_HEAP_USED); size_t objfree = v7_heap_stat(v7, V7_HEAP_STAT_OBJ_HEAP_FREE); size_t propnfree = v7_heap_stat(v7, V7_HEAP_STAT_PROP_HEAP_FREE); v7_val_t f = v7_create_undefined(); v7_own(v7, &f); f = v7_create_object(v7); v7_set(v7, f, "sysfree", ~0, 0, v7_create_number(sysfree)); v7_set(v7, f, "jssize", ~0, 0, v7_create_number(jssize)); v7_set(v7, f, "jsfree", ~0, 0, v7_create_number(jsfree)); v7_set(v7, f, "strres", ~0, 0, v7_create_number(strres)); v7_set(v7, f, "struse", ~0, 0, v7_create_number(struse)); v7_set(v7, f, "objfree", ~0, 0, v7_create_number(objfree)); v7_set(v7, f, "objncell", ~0, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE))); v7_set(v7, f, "propnfree", ~0, 0, v7_create_number(propnfree)); v7_set(v7, f, "propncell", ~0, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_PROP_HEAP_CELL_SIZE))); v7_set(v7, f, "funcnfree", ~0, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_HEAP_FREE))); v7_set(v7, f, "funcncell", ~0, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE))); v7_set(v7, f, "astsize", ~0, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_AST_SIZE))); v7_set(v7, f, "owned", ~0, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_OWNED))); v7_set(v7, f, "owned_max", ~0, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_FUNC_OWNED_MAX))); v7_disown(v7, &f); return f; }
static int sj_init() { struct v7 *v7 = s_v7; LOG(LL_INFO, ("Mongoose IoT Firmware %s", build_id)); LOG(LL_INFO, ("RAM: %d total, %d free", sj_get_heap_size(), sj_get_free_heap_size())); int r = start_nwp(); if (r < 0) { LOG(LL_ERROR, ("Failed to start NWP: %d", r)); return 0; } int boot_cfg_idx = get_active_boot_cfg_idx(); if (boot_cfg_idx < 0) return 0; struct boot_cfg boot_cfg; if (read_boot_cfg(boot_cfg_idx, &boot_cfg) < 0) return 0; LOG(LL_INFO, ("Boot cfg %d: 0x%llx, 0x%u, %s @ 0x%08x, %s", boot_cfg_idx, boot_cfg.seq, boot_cfg.flags, boot_cfg.app_image_file, boot_cfg.app_load_addr, boot_cfg.fs_container_prefix)); uint64_t saved_seq = 0; if (boot_cfg.flags & BOOT_F_FIRST_BOOT) { /* Tombstone the current config. If anything goes wrong between now and * commit, next boot will use the old one. */ saved_seq = boot_cfg.seq; boot_cfg.seq = BOOT_CFG_TOMBSTONE_SEQ; write_boot_cfg(&boot_cfg, boot_cfg_idx); } r = init_fs(boot_cfg.fs_container_prefix); if (r < 0) { LOG(LL_ERROR, ("FS init error: %d", r)); if (boot_cfg.flags & BOOT_F_FIRST_BOOT) { revert_update(boot_cfg_idx, &boot_cfg); } return 0; } if (boot_cfg.flags & BOOT_F_FIRST_BOOT) { LOG(LL_INFO, ("Applying update")); if (apply_update(boot_cfg_idx, &boot_cfg) < 0) { revert_update(boot_cfg_idx, &boot_cfg); } } mongoose_init(); #ifndef CS_DISABLE_JS v7 = s_v7 = init_v7(&v7); /* Disable GC during JS API initialization. */ v7_set_gc_enabled(v7, 0); sj_gpio_api_setup(v7); sj_i2c_api_setup(v7); sj_wifi_api_setup(v7); sj_timers_api_setup(v7); #endif sj_v7_ext_api_setup(v7); sj_init_sys(v7); sj_wifi_init(v7); #ifndef DISABLE_C_CLUBBY sj_clubby_init(); #endif sj_http_api_setup(v7); #if !defined(DISABLE_C_CLUBBY) && !defined(CS_DISABLE_JS) sj_clubby_api_setup(v7); #endif /* Common config infrastructure. Mongoose & v7 must be initialized. */ init_device(v7); sj_updater_post_init(v7); #ifndef DISABLE_C_CLUBBY init_updater_clubby(v7); #endif #ifndef CS_DISABLE_JS /* SJS initialized, enable GC back, and trigger it */ v7_set_gc_enabled(v7, 1); v7_gc(v7, 1); v7_val_t res; if (v7_exec_file(v7, "sys_init.js", &res) != V7_OK) { fprintf(stderr, "Error: "); v7_fprint(stderr, v7, res); } #endif LOG(LL_INFO, ("%s init done, RAM: %d free", "Sys", sj_get_free_heap_size())); if (!sj_app_init(v7)) { LOG(LL_ERROR, ("App init failed")); abort(); } LOG(LL_INFO, ("%s init done, RAM: %d free", "App", sj_get_free_heap_size())); if (boot_cfg.flags & BOOT_F_FIRST_BOOT) { boot_cfg.seq = saved_seq; commit_update(boot_cfg_idx, &boot_cfg); clubby_updater_finish(0); } else { /* * If there is no update reply state, this will just be ignored. * But if there is, then update was rolled back and reply will be sent. */ clubby_updater_finish(-1); } #ifndef CS_DISABLE_JS sj_prompt_init(v7); #endif return 1; }