/* * ne_monitor.c -- provide iot-system thread protect operation interface. * * * ORIGINAL AUTHOR: * * Copyright (c) 2018 Netease Corporation */ #include "c_types.h" #include "ne_device.h" #include "user_main.h" #include "cfg.h" #include "log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" #include "freertos/timers.h" #include "ne_monitor.h" static ne_thread_monitor_t ne_thread_monitor; /* * system get ticks. */ uint32 ne_os_ticks_ms(uint32 ticks) { return (ticks) * (portTICK_RATE_MS); } /* * system thread monitor check name. */ static int32 ne_thread_monitor_check_name(uint8 *name, ne_thread_monitor_t *ctx) { int i; for(i=0;ithread_handle[i].is_valid) continue; if(strcmp(ctx->thread_handle[i].name, name)) continue; return i; } return -ERR_FAIL; } /* * system thread monitor unregister. */ int32 ne_thread_monitor_unregister(uint8 *name) { int32 index; ne_thread_monitor_t *ctx = NE_THREAD_MONITOR_CTX; /* lock and check name whether exist */ xSemaphoreTake(ctx->sema, portMAX_DELAY); index = ne_thread_monitor_check_name(name, ctx); if (index < 0) { LOG_EX(LOG_Error, "not found!\r\n"); /* unlock */ xSemaphoreGive(ctx->sema); return -ERR_FAIL; } /* unregistered */ memset(&ctx->thread_handle[index], 0, sizeof(ne_thread_handle_t)); /* unlock */ xSemaphoreGive(ctx->sema); return ERR_OK; } /* * system thread monitor register. */ int32 ne_thread_monitor_register(void *thread_name, uint32 check_interval, int32 (* is_sick)(uint32 cmsec)) { int32 i,ret; ne_thread_monitor_t *ctx = NE_THREAD_MONITOR_CTX; if(thread_name == NULL || is_sick == NULL) return -ERR_FAIL; /* lock and check name whether registered */ xSemaphoreTake(ctx->sema, portMAX_DELAY); ret = ne_thread_monitor_check_name(thread_name, ctx); if(ret >= 0){ LOG_EX(LOG_Error, "already exit!\r\n"); } /* register */ for(i=0;ithread_handle[i].is_valid){ ctx->thread_handle[i].is_valid = 1; memcpy(ctx->thread_handle[i].name, thread_name, strlen(thread_name)); ctx->thread_handle[i].check_interval = check_interval; ctx->thread_handle[i].is_sick = is_sick; break; } } /* unlock */ xSemaphoreGive(ctx->sema); if(i >= NE_THREAD_MONITOR_MAX){ LOG_EX(LOG_Error, "register fail!\r\n"); return -ERR_FAIL; } return ERR_OK; } /* * system thread monitor loop work. */ static void ne_thread_monitor_loop(void *arg) { int32 i,ret; uint32 cmsec; ne_thread_monitor_t *ctx = NE_THREAD_MONITOR_CTX; ctx->run_flag = 1; while(ctx->run_flag){ xSemaphoreTake(ctx->sema, portMAX_DELAY); for(i=0;ithread_handle[i].is_valid){ continue; } if(cmsec < ctx->thread_handle[i].lmsec + ctx->thread_handle[i].check_interval * 1000){ continue; } if(ctx->thread_handle[i].is_sick){ /* check thread */ ctx->thread_handle[i].is_sick(cmsec); ctx->thread_handle[i].lmsec = cmsec; } } xSemaphoreGive(ctx->sema); vTaskDelay(100 / portTICK_RATE_MS); } } /* * system thread monitor start. */ int32 ne_thread_monitor_start(void) { ne_thread_monitor_t *ctx = NE_THREAD_MONITOR_CTX; if(!ctx->init_flag) return -ERR_FAIL; if(ctx->start_flag) return ERR_OK; if(xTaskCreate(ne_thread_monitor_loop, "thread_manage", 256, NULL, 5, NULL) !=pdPASS){ LOG_EX(LOG_Error, "start error!\r\n"); return -ERR_FAIL; } ctx->start_flag = 1; return ERR_OK; } /* * system thread monitor init. */ int32 ne_thread_monitor_init(void) { int32 ret; ne_thread_monitor_t *ctx = NE_THREAD_MONITOR_CTX; if(ctx->init_flag) return ERR_OK; ctx->sema = xSemaphoreCreateMutex(); if (ctx->sema == NULL) { LOG_EX(LOG_Info, "init fail!\r\n"); return -ERR_FAIL; } ctx->init_flag = 1; return ERR_OK; }