Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ns_monitor.c
00001 /* 00002 * Copyright (c) 2019, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /** 00019 * \file ns_monitor.c 00020 * \brief Utility functions for nanostack maintenance 00021 * 00022 * This module tracks stack current heap usage and triggers GC if heap usage is too high. 00023 * GC is triggered by: 00024 * 1. Heap usage is above HEAP_USAGE_HIGH 00025 * 2. Heap usage is above HEAP_USAGE_CRITICAL 00026 * 3. If nsdynmemLIB memory allocation has failed since last check 00027 */ 00028 00029 #include "nsconfig.h" 00030 #include "ns_types.h" 00031 #define HAVE_DEBUG 00032 #include "ns_trace.h" 00033 #include "nsdynmemLIB.h" 00034 #include "ipv6_stack/ipv6_routing_table.h" 00035 #include "NWK_INTERFACE/Include/protocol.h" 00036 #include "6LoWPAN/ws/ws_pae_controller.h" 00037 #include "NWK_INTERFACE/Include/protocol.h" 00038 00039 #define TRACE_GROUP "mntr" 00040 00041 typedef enum { 00042 NS_MONITOR_STATE_HEAP_GC_IDLE = 0, 00043 NS_MONITOR_STATE_HEAP_GC_HIGH, 00044 NS_MONITOR_STATE_GC_CRITICAL 00045 } ns_monitor_state_e; 00046 00047 #define DEFAULT_HEAP_PERCENTAGE_THRESHOLD_HIGH 95 00048 #define DEFAULT_HEAP_PERCENTAGE_THRESHOLD_CRITICAL 99 00049 00050 #define SET_WATERMARK(SECTOR_SIZE, THRESHOLD) (SECTOR_SIZE * THRESHOLD / 100) 00051 00052 #define NS_MAINTENANCE_TIMER_INTERVAL 10 // Maintenance interval 00053 00054 typedef struct ns_monitor__s { 00055 ns_mem_heap_size_t heap_high_watermark; 00056 ns_mem_heap_size_t heap_critical_watermark; 00057 uint32_t prev_heap_alloc_fail_cnt; 00058 ns_monitor_state_e ns_monitor_heap_gc_state; 00059 const mem_stat_t *mem_stats; 00060 uint16_t ns_maintenance_timer; 00061 } ns_monitor_t; 00062 00063 static ns_monitor_t *ns_monitor_ptr = NULL; 00064 00065 typedef void (ns_maintenance_gc_cb)(bool full_gc); 00066 00067 /* 00068 * Garbage collection functions. 00069 * Add more GC performing functions to the table 00070 * 00071 */ 00072 static ns_maintenance_gc_cb *ns_maintenance_gc_functions[] = { 00073 ipv6_destination_cache_forced_gc, 00074 ws_pae_controller_forced_gc 00075 }; 00076 00077 static void ns_monitor_heap_gc(bool full_gc) 00078 { 00079 (void) full_gc; 00080 00081 for (unsigned int i = 0; i < sizeof(ns_maintenance_gc_functions) / sizeof(ns_maintenance_gc_functions[0]); i++) { 00082 if (ns_maintenance_gc_functions[i]) { 00083 (ns_maintenance_gc_functions[i])(full_gc); 00084 } 00085 } 00086 } 00087 00088 static void ns_monitor_periodic_heap_health_check(void) 00089 { 00090 if (ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes > ns_monitor_ptr->heap_critical_watermark) { 00091 // Heap usage above CRITICAL 00092 if (ns_monitor_ptr->ns_monitor_heap_gc_state != NS_MONITOR_STATE_GC_CRITICAL) { 00093 ns_mem_heap_size_t prev_heap_sector_allocated_bytes = ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes; 00094 tr_debug("heap %lu/%lu", (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size); 00095 ns_monitor_heap_gc(true); 00096 ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_GC_CRITICAL; 00097 tr_info("Stack GC critical: freed %lu bytes", (unsigned long)(prev_heap_sector_allocated_bytes - ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes)); 00098 } 00099 } else if (ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes > ns_monitor_ptr->heap_high_watermark) { 00100 // Heap usage above HIGH 00101 if (ns_monitor_ptr->ns_monitor_heap_gc_state == NS_MONITOR_STATE_HEAP_GC_IDLE) { 00102 ns_mem_heap_size_t prev_heap_sector_allocated_bytes = ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes; 00103 tr_debug("heap %lu/%lu", (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size); 00104 ns_monitor_heap_gc(false); 00105 ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_HEAP_GC_HIGH; 00106 tr_info("Stack GC high: freed %lu bytes", (unsigned long)(prev_heap_sector_allocated_bytes - ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes)); 00107 } 00108 } else if (ns_monitor_ptr->mem_stats->heap_sector_allocated_bytes <= ns_monitor_ptr->heap_high_watermark) { 00109 // Heap usage in normal range 00110 ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_HEAP_GC_IDLE; 00111 } 00112 } 00113 00114 void ns_monitor_timer(uint16_t seconds) 00115 { 00116 if (ns_monitor_ptr) { 00117 ns_monitor_ptr->ns_maintenance_timer += seconds; 00118 00119 if (ns_monitor_ptr->mem_stats->heap_alloc_fail_cnt > ns_monitor_ptr->prev_heap_alloc_fail_cnt) { 00120 // Heap allocation failure occurred since last check 00121 ns_monitor_ptr->prev_heap_alloc_fail_cnt = ns_monitor_ptr->mem_stats->heap_alloc_fail_cnt; 00122 if (ns_monitor_ptr->ns_monitor_heap_gc_state != NS_MONITOR_STATE_GC_CRITICAL) { 00123 ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_GC_CRITICAL; 00124 ns_monitor_heap_gc(true); 00125 ns_monitor_ptr->ns_maintenance_timer = 0; 00126 } 00127 } 00128 00129 if (ns_monitor_ptr->ns_maintenance_timer >= NS_MAINTENANCE_TIMER_INTERVAL) { 00130 ns_monitor_ptr->ns_maintenance_timer -= NS_MAINTENANCE_TIMER_INTERVAL; 00131 ns_monitor_periodic_heap_health_check(); 00132 } 00133 } 00134 } 00135 00136 int ns_monitor_init(void) 00137 { 00138 if (ns_monitor_ptr || !ns_dyn_mem_get_mem_stat()) { 00139 // already initialized or memory statistics not available 00140 return -2; 00141 } 00142 00143 ns_monitor_ptr = ns_dyn_mem_alloc(sizeof(ns_monitor_t)); 00144 00145 if (ns_monitor_ptr) { 00146 ns_monitor_ptr->mem_stats = ns_dyn_mem_get_mem_stat(); 00147 ns_monitor_ptr->heap_high_watermark = SET_WATERMARK( 00148 ns_monitor_ptr->mem_stats->heap_sector_size, 00149 DEFAULT_HEAP_PERCENTAGE_THRESHOLD_HIGH 00150 ); 00151 ns_monitor_ptr->heap_critical_watermark = SET_WATERMARK( 00152 ns_monitor_ptr->mem_stats->heap_sector_size, 00153 DEFAULT_HEAP_PERCENTAGE_THRESHOLD_CRITICAL 00154 ); 00155 ns_monitor_ptr->ns_monitor_heap_gc_state = NS_MONITOR_STATE_HEAP_GC_IDLE; 00156 ns_monitor_ptr->ns_maintenance_timer = 0; 00157 ns_monitor_ptr->prev_heap_alloc_fail_cnt = 0; 00158 return 0; 00159 } 00160 00161 return -1; 00162 } 00163 00164 int ns_monitor_clear(void) 00165 { 00166 if (ns_monitor_ptr) { 00167 ns_dyn_mem_free(ns_monitor_ptr); 00168 ns_monitor_ptr = NULL; 00169 return 0; 00170 } 00171 00172 return -1; 00173 } 00174 00175 int ns_monitor_heap_gc_threshold_set(uint8_t percentage_high, uint8_t percentage_critical) 00176 { 00177 if (ns_monitor_ptr && (percentage_critical <= 100) && (percentage_high < percentage_critical)) { 00178 ns_monitor_ptr->heap_high_watermark = SET_WATERMARK( 00179 ns_monitor_ptr->mem_stats->heap_sector_size, 00180 percentage_high 00181 ); 00182 ns_monitor_ptr->heap_critical_watermark = SET_WATERMARK( 00183 ns_monitor_ptr->mem_stats->heap_sector_size, 00184 percentage_critical 00185 ); 00186 tr_debug("Monitor set high:%lu, critical:%lu total:%lu", (unsigned long)ns_monitor_ptr->heap_high_watermark, (unsigned long)ns_monitor_ptr->heap_critical_watermark, (unsigned long)ns_monitor_ptr->mem_stats->heap_sector_size); 00187 return 0; 00188 } 00189 00190 return -1; 00191 }
Generated on Tue Jul 12 2022 13:54:38 by
