linux 多线程看门狗,一个看门狗保护多线程的简单方案

#include "daemon.h"

static uint32_t daemon_wd_flag_get(struct daemon_object *daemon);

static void daemon_watchdog_init(struct daemon_object *daemon);

static void daemon_wd_feed(struct daemon_object *daemon);

static struct daemon_register_thread* daemon_find_thread(struct daemon_object *daemon, uint8_t index);

static inline uint32_t daemon_wd_flag_clear(struct daemon_object *daemon);

void daemon_thread_entry(void * param){

uint32_t threadFlag = 0;

struct daemon_object *daemon = (struct daemon_object *)param;

uint32_t time = daemon->wdtTimeout*1000;;

while(1){

threadFlag = daemon_wd_flag_get(daemon);

if(threadFlag !=0){

rt_err_t err = rt_event_recv(&daemon->event, threadFlag,

RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,

time, RT_NULL);

if (err == RT_EOK){

daemon_wd_flag_clear(daemon);

LOG_D("All threads are running, feed the watch dog");

daemon_wd_feed(daemon);

rt_thread_mdelay(1000);

}else if(err == -RT_ETIMEOUT){

daemon->threadFlag = ~daemon->threadFlag;

for(uint8_t i=0; i < daemon->daemonNum; i++){

if(daemon->threadFlag & 0x01){

struct daemon_register_thread* temp = daemon_find_thread(daemon, i);

if(temp != RT_NULL)

LOG_E("Thread [%s] is not running", temp->thread->name);

}

daemon->threadFlag >>=1;

}

daemon_wd_flag_clear(daemon);

LOG_E("Wait watch dog reset the mcu");

while(1){

rt_thread_mdelay(1000);

}

}else{

LOG_E("Event recv err:%d", err);

rt_thread_mdelay(100);

}

}else{

LOG_D("No thread register..");

daemon_wd_feed(daemon);

rt_thread_mdelay(1000);

}

}

}

static uint32_t daemon_wd_flag_get(struct daemon_object *daemon){

uint32_t flag = 0;

for(uint8_t i=0; idaemonNum; i++){

flag <<= 1;

flag |= 0x01;

}

return flag;

}

static inline uint32_t daemon_wd_flag_clear(struct daemon_object *daemon){

daemon->threadFlag = 0;

}

APP_ErrType daemon_init(struct daemon_object *daemon, const char *wd_device_name, uint32_t timeout){

APP_ErrType err = APP_OK;

rt_err_t result;

rt_slist_init(&daemon->threadHead);

daemon->daemonNum = 0;

daemon->threadFlag = 0;

daemon->iwgDevice = rt_device_find(wd_device_name);

if(daemon->iwgDevice == RT_NULL){

LOG_D("Cant find watch dog device");

return APP_ERR;

}

daemon->wdtTimeout = timeout;

daemon_watchdog_init(daemon);

result = rt_event_init(&daemon->event, "wd_event", RT_IPC_FLAG_FIFO);

if (result != RT_EOK){

err = APP_ERR;

goto errend;

}

daemon->daemonThread = rt_thread_create("daemon", daemon_thread_entry, daemon, 1024, 3, 40);

if(daemon->daemonThread == RT_NULL)

err = APP_OUT_OF_MEM;

rt_thread_startup(daemon->daemonThread);

errend:

return err;

}

uint32_t daemon_thread_register(struct daemon_object *daemon, rt_thread_t tid){

uint32_t flag = 0;

if(daemon->daemonNum < 32){

struct daemon_register_thread *temp = rt_malloc(sizeof(struct daemon_register_thread));

if(temp != RT_NULL){

daemon->daemonNum ++;

temp->thread = tid;

rt_slist_append(&daemon->threadHead, &temp->list);

flag = (1

}

}

return flag;

}

void daemon_fd_wd(struct daemon_object *daemon, uint32_t flag){

rt_event_send(&daemon->event, flag);

daemon->threadFlag |= flag;

}

static struct daemon_register_thread* daemon_find_thread(struct daemon_object *daemon, uint8_t index){

struct daemon_register_thread* thread = RT_NULL;

rt_slist_t *temp_list;

if(index < daemon->daemonNum){

temp_list = rt_slist_next(&daemon->threadHead);

for(uint8_t i=0; i < index; i++){

if(temp_list != RT_NULL)

temp_list = rt_slist_next(temp_list);

else

break;

}

if(temp_list != RT_NULL)

thread = rt_slist_entry(temp_list, struct daemon_register_thread, list);

}

return thread;

}

static void daemon_watchdog_init(struct daemon_object *daemon){

rt_device_t iwgDevice;

iwgDevice = daemon->iwgDevice;

rt_err_t ret = rt_device_init(iwgDevice);

if (ret != RT_EOK){

LOG_E("Init wdt failed!\n");

return;

}

ret = rt_device_control(iwgDevice, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &daemon->wdtTimeout + 3);

if (ret != RT_EOK){

LOG_E("Set wdt timeout failed!\n");

return;

}

ret = rt_device_control(iwgDevice, RT_DEVICE_CTRL_WDT_START, RT_NULL);

if (ret != RT_EOK){

LOG_E("start wdt failed!\n");

return;

}

}

static void daemon_wd_feed(struct daemon_object *daemon){

rt_device_control(daemon->iwgDevice, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值