// Create a new kernel event container BSP_DECLARE(BSP_EVENT_CONTAINER *) bsp_new_event_container() { BSP_EVENT_CONTAINER *ec = bsp_calloc(1, sizeof(BSP_EVENT_CONTAINER)); if (!ec) { bsp_trace_message(BSP_TRACE_EMERGENCY, _tag_, "Create event container failed"); return NULL; } int epoll_fd = epoll_create(_BSP_MAX_EVENTS); if (0 > epoll_fd) { switch (errno) { case ENFILE : bsp_trace_message(BSP_TRACE_CRITICAL, _tag_, "Cannot open another file descriptor"); break; case ENOMEM : bsp_trace_message(BSP_TRACE_EMERGENCY, _tag_, "Kernel memory full"); break; case EINVAL : default : bsp_trace_message(BSP_TRACE_ERROR, _tag_, "Cannot create event container"); break; } bsp_free(ec); return NULL; } struct epoll_event *list = bsp_calloc(_BSP_MAX_EVENTS, sizeof(struct epoll_event)); if (!list) { bsp_free(ec); return NULL; } ec->epoll_fd = epoll_fd; ec->event_list = list; bsp_trace_message(BSP_TRACE_INFORMATIONAL, _tag_, "Create new event container %d with Epoll", epoll_fd); // Create event fd #ifdef EFD_NONBLOCK ec->notify_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); #else ec->notify_fd = eventfd(0, 0); bsp_set_blocking(ec->notify_fd, BSP_FD_NONBLOCK); #endif BSP_EVENT ev; ev.data.fd = ec->notify_fd; ev.data.fd_type = BSP_FD_EVENT; ev.data.associate.buff = 0; ev.events = BSP_EVENT_EVENT; bsp_add_event(ec, &ev); bsp_trace_message(BSP_TRACE_DEBUG, _tag_, "Create notification event of container %d", epoll_fd); return ec; }
// Close event container BSP_DECLARE(int) bsp_del_event_container(BSP_EVENT_CONTAINER *ec) { if (ec) { close(ec->epoll_fd); bsp_free(ec->event_list); bsp_free(ec); bsp_trace_message(BSP_TRACE_WARNING, _tag_, "Event container closed, BSP_EVENT_DATA leak should be occured"); return BSP_RTN_SUCCESS; } return BSP_RTN_INVALID; }
/* Mempool freer */ BSP_PRIVATE(void) _buffer_free(void *item) { BSP_BUFFER *b = (BSP_BUFFER *) item; if (b) { if (B_DATA(b) && !B_ISCONST(b)) { bsp_free(B_DATA(b)); } bsp_free(b); } return; }
/***************************************************************************** * 函 数 名 : BSP_Free * * 功能描述 : BSP 动态内存释放(Debug接口) * * 输入参数 : pMem: 动态内存指针 * pFileName: 使用的源文件 * u32Line: 所在文件的行号 * * 输出参数 : 无 * 返 回 值 : 无 *****************************************************************************/ void bsp_free_dbg(void* pMem, u8* pFileName, u32 u32Line) { #ifdef __BSP_MEM_DEBUG__ /* 检查当前内存是否有效 */ if (bsp_ptr_invalid(pMem)) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_MEM, "invalid mem block, ptr:0x%x, line:%d\n", pMem, __LINE__); return; } if (MEM_FREE == MEM_ITEM_STATUS(pMem) || MEM_NORM_DDR_POOL != MEM_ITEM_FLAGS(pMem)) { bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_MEM, "warning! ptr:0x%x, may free twice, or wrong mem flags line:%d\n", pMem, __LINE__); return; } #endif bsp_free(pMem); #ifdef __BSP_MEM_DEBUG__ /* 更新MGR Debug信息 */ MEM_ITEM_LINE(pMem) = u32Line; MEM_ITEM_FILE_NAME(pMem) = (u32)pFileName; #endif return; }
// Set const data to en empty buffer BSP_DECLARE(size_t) bsp_buffer_set_const(BSP_BUFFER *b, const char *data, ssize_t len) { if (!b || !data || B_ISCONST(b)) { return 0; } if (len < 0) { len = strnlen(data, _BSP_MAX_UNSIZED_STRLEN); } if (B_DATA(b)) { bsp_free(B_DATA(b)); } B_DATA(b) = (char *) data; B_SIZE(b) = 0; B_LEN(b) = len; // Set to const b->is_const = BSP_TRUE; return len; }
// Cancellation a buffer BSP_DECLARE(void) bsp_del_buffer(BSP_BUFFER *b) { if (b) { if (!B_ISCONST(b)) { if (_BSP_BUFFER_HIGHWATER < B_SIZE(b)) { // Buffer too big, just clean bsp_free(B_DATA(b)); B_DATA(b) = NULL; B_SIZE(b) = 0; B_LEN(b) = 0; B_NOW(b) = 0; } if (_BSP_BUFFER_UNSATURATION < (B_SIZE(b) - B_LEN(b))) { _shrink_buffer(b); } } else { B_DATA(b) = NULL; B_SIZE(b) = 0; } bsp_mempool_free(mp_buffer, (void *) b); } return; }
/***************************************************************************** * 函 数 名 : BSP_Free * * 功能描述 : BSP 动态内存释放(Debug接口) * * 输入参数 : pMem: 动态内存指针 * pFileName: 使用的源文件 * u32Line: 所在文件的行号 * * 输出参数 : 无 * 返 回 值 : 无 *****************************************************************************/ void bsp_free_dbg(void* pMem, u8* pFileName, u32 u32Line) { /* coverity[USE_AFTER_FREE] */ #ifdef __BSP_MEM_DEBUG__ /* 检查当前内存是否有效 */ if (bsp_ptr_invalid(pMem)) { printk("invalid mem block, ptr:0x%x, line:%d\n", (unsigned int)pMem, __LINE__); return; } if (MEM_FREE == MEM_ITEM_STATUS(pMem) || MEM_NORM_DDR_POOL != MEM_ITEM_FLAGS(pMem)) { printk("warning! ptr:0x%x, may free twice, or wrong mem flags line:%d\n", (unsigned int)pMem, __LINE__); return; } #endif /* coverity[freed_arg] */ bsp_free(pMem); #ifdef __BSP_MEM_DEBUG__ /* 更新MGR Debug信息 */ /* coverity[use_after_free] */ MEM_ITEM_LINE(pMem) = u32Line; MEM_ITEM_FILE_NAME(pMem) = (u32)pFileName; #endif return; }
static int del_word_filter(lua_State *s) { if (!s || lua_gettop(s) < 1 || !lua_islightuserdata(s, -1)) { return 0; } struct word_filter_t *flt = (struct word_filter_t *) lua_touserdata(s, -1); if (!flt) { return 0; } // Clean all block bsp_free(flt); return 0; }
static void buf_handler(int argc, char** argv, uint8_t port) { #ifdef UNIT_TESTS if (argc > 2 && stricmp(argv[1],"test") == 0) { int n = strtoul(argv[2],0,10); if (n == 1) { for (uint16_t size=1; size < 1024; size++) { bsp_termios_printf(port, "malloc %d\r\n", size); uint8_t* buf = (uint8_t*) bsp_malloc(size); memset(buf,0xaa,size); bsp_free(buf); if ((size&0x7f) == 0) OSTimeDly(1); } } else if (n == 2) { for (int i=1; ; i++) { bsp_termios_printf("malloc %d\r\n", i); bsp_malloc(16); if ((i&0x7f) == 0) OSTimeDly(1); } } else if (n == 3) { bsp_malloc(0); } else if (n == 4) { uint8_t* buf = (uint8_t*) bsp_malloc(16); memset(buf,0xaa,17); bsp_free(buf); } else if (n == 5) { uint8_t* buf = (uint8_t*) bsp_malloc(16); memset(buf-1,0xaa,17); bsp_free(buf); } else if (n == 6) { uint8_t* buf = (uint8_t*) bsp_malloc(16); bsp_free(buf); bsp_free(buf); } else if (n == 7) { bsp_free((uint8_t*) 0x12345678); } else if (n == 8) { bsp_free(0); } } #endif bsp_buffer_dump(port); }
// Start main loop int core_loop(void (* server_event)(BSP_CALLBACK *)) { BSP_THREAD *t = get_thread(MAIN_THREAD); if (!t) { trigger_exit(BSP_RTN_FATAL, "Main thread lost!"); } // Servers BSP_VALUE *val = object_get_hash_str(runtime_settings, "servers"); BSP_OBJECT *vobj = value_get_object(val); BSP_STRING *vstr = NULL; if (vobj && OBJECT_TYPE_ARRAY == vobj->type) { struct bsp_conf_server_t srv; BSP_OBJECT *vsrv = NULL; size_t varr_size = object_size(vobj), i; reset_object(vobj); for (i = 0; i < varr_size; i ++) { val = object_get_array(vobj, i); vsrv = value_get_object(val); if (vsrv && OBJECT_TYPE_HASH == vsrv->type) { // Default value memset(&srv, 0, sizeof(struct bsp_conf_server_t)); srv.server_inet = INET_TYPE_ANY; srv.server_sock = SOCK_TYPE_ANY; srv.def_client_type = CLIENT_TYPE_DATA; srv.def_data_type = DATA_TYPE_PACKET; val = object_get_hash_str(vsrv, "name"); vstr = value_get_string(val); srv.server_name = bsp_strndup(STR_STR(vstr), STR_LEN(vstr)); val = object_get_hash_str(vsrv, "inet"); vstr = value_get_string(val); if (vstr) { if (0 == strncasecmp(STR_STR(vstr), "ipv6", 4)) { srv.server_inet = INET_TYPE_IPV6; } else if (0 == strncasecmp(STR_STR(vstr), "ipv4", 4)) { srv.server_inet = INET_TYPE_IPV4; } else if (0 == strncasecmp(STR_STR(vstr), "local", 5)) { srv.server_inet = INET_TYPE_LOCAL; } } val = object_get_hash_str(vsrv, "sock"); vstr = value_get_string(val); if (vstr) { if (0 == strncasecmp(STR_STR(vstr), "tcp", 3)) { srv.server_sock = SOCK_TYPE_TCP; } else if (0 == strncasecmp(STR_STR(vstr), "udp", 3)) { srv.server_sock = SOCK_TYPE_UDP; } } val = object_get_hash_str(vsrv, "addr"); vstr = value_get_string(val); srv.server_addr = bsp_strndup(STR_STR(vstr), STR_LEN(vstr)); val = object_get_hash_str(vsrv, "port"); srv.server_port = (int) value_get_int(val); val = object_get_hash_str(vsrv, "heartbeat_check"); srv.heartbeat_check = (int) value_get_int(val); val = object_get_hash_str(vsrv, "debug_input"); srv.debug_hex_input = value_get_boolean(val); val = object_get_hash_str(vsrv, "debug_output"); srv.debug_hex_input = value_get_boolean(val); val = object_get_hash_str(vsrv, "max_clients"); srv.max_clients = (int) value_get_int(val); val = object_get_hash_str(vsrv, "max_packet_length"); srv.max_packet_length = (size_t) value_get_int(val); val = object_get_hash_str(vsrv, "websocket"); if (value_get_boolean(val)) { srv.def_client_type = CLIENT_TYPE_WEBSOCKET_HANDSHAKE; } val = object_get_hash_str(vsrv, "data_type"); vstr = value_get_string(val); if (vstr && 0 == strncasecmp(STR_STR(vstr), "stream", 6)) { srv.def_data_type = DATA_TYPE_STREAM; } // Add server BSP_SERVER *s; int srv_fds[MAX_SERVER_PER_CREATION], srv_ct, fd_type; int nfds = MAX_SERVER_PER_CREATION; nfds = new_server(srv.server_addr, srv.server_port, srv.server_inet, srv.server_sock, srv_fds, &nfds); for (srv_ct = 0; srv_ct < nfds; srv_ct ++) { fd_type = FD_TYPE_SOCKET_SERVER; s = (BSP_SERVER *) get_fd(srv_fds[srv_ct], &fd_type); if (s) { s->name = srv.server_name; s->heartbeat_check = srv.heartbeat_check; s->def_client_type = srv.def_client_type; s->def_data_type = srv.def_data_type; s->max_packet_length = srv.max_packet_length; s->max_clients = srv.max_clients; s->debug_hex_input = srv.debug_hex_input; s->debug_hex_output = srv.debug_hex_output; add_server(s); } else { bsp_free(srv.server_name); } } } } } // Server event if (server_event) { core_settings.on_srv_events = server_event; } // Create 1 Hz clock BSP_TIMER *tmr = new_timer(BASE_CLOCK_SEC, BASE_CLOCK_USEC, -1); tmr->on_timer = base_timer; core_settings.main_timer = tmr; dispatch_to_thread(tmr->fd, MAIN_THREAD); start_timer(tmr); // Let's go load_bootstrap(); trace_msg(TRACE_LEVEL_CORE, "Core : Main thread loop started"); thread_process((void *) t); return BSP_RTN_SUCCESS; }