/**
* @brief tOS应用示例
* @details
* @author 01课堂 李述铜 http://01ketang.cc
* @date 2017-06-01
* @version 1.0
* @copyright 版权所有,禁止用于商业用途
*/
#include "tinyOS.h"
#include "app.h"
#include "hal.h"
static tTask task1; // 任务1结构
static tTask task2; // 任务2结构
static tTask task3; // 任务3结构
static tTask task4; // 任务4结构
static tTaskStack task1Env[TASK1_ENV_SIZE]; // 任务1的堆栈空间
static tTaskStack task2Env[TASK2_ENV_SIZE]; // 任务2的堆栈空间
static tTaskStack task3Env[TASK3_ENV_SIZE]; // 任务3的堆栈空间
static tTaskStack task4Env[TASK4_ENV_SIZE]; // 任务4的堆栈空间
int task1Flag; // 用于指示任务运行状态的标志变量
int task2Flag; // 用于指示任务运行状态的标志变量
int task3Flag; // 用于指示任务运行状态的标志变量
int task4Flag; // 用于指示任务运行状态的标志变量
static tMutex mutexA;
static tMutex mutexB;
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task1Entry (void *param) {
for (;;) {
tMutexWait(&mutexA, 0);
interruptByOtherTask(); // 中间可能运行了很多代码,被打断
tMutexWait(&mutexB, 0);
task1Flag = 1;
tTaskDelay(1);
task1Flag = 0;
tTaskDelay(1);
tMutexNotify(&mutexB);
tMutexNotify(&mutexA);
task1Flag = 1;
tTaskDelay(1);
task1Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task2Entry (void *param) {
for (;;) {
tMutexWait(&mutexB, 0);
interruptByOtherTask(); // 中间可能运行了很多代码,被打断
tMutexWait(&mutexA, 0);
task2Flag = 1;
tTaskDelay(1);
task2Flag = 0;
tTaskDelay(1);
tMutexNotify(&mutexA);
tMutexNotify(&mutexB);
task2Flag = 1;
tTaskDelay(1);
task2Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task3Entry (void *param) {
for (;;) {
task3Flag = 1;
tTaskDelay(1);
task3Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task4Entry (void *param) {
for (;;) {
task4Flag = 1;
tTaskDelay(1);
task4Flag = 0;
tTaskDelay(1);
}
}
/**
* App的初始化
*/
void tInitApp (void) {
halInit();
tMutexInit(&mutexA);
tMutexInit(&mutexB);
tTaskInit(&task1, task1Entry, (void *) 0x0, TASK1_PRIO, task1Env, sizeof(task1Env));
tTaskInit(&task2, task2Entry, (void *) 0x0, TASK2_PRIO, task2Env, sizeof(task2Env));
tTaskInit(&task3, task3Entry, (void *) 0x0, TASK3_PRIO, task3Env, sizeof(task3Env));
tTaskInit(&task4, task4Entry, (void *) 0x0, TASK4_PRIO, task4Env, sizeof(task4Env));
}
两个或两个以上的任务在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
死锁产生条件:
以上几个条件,其中互斥、非剥夺一般是我们所用RTOS默认支持,其余条件则由实际应用、程序员编写方式决定。
预防死锁:
为了避免死锁产生影响整个系统的运行,有三种方式:
以上几种方式,对我们所用的RTOS而言,一般只能做到预防。而具体的预防措施,其原理在于打破死锁产生的几个条件。根据前面的死锁条件,我们只能对控制"请求保持"、“循环等待” 这两个条件施加影响。
具体解决:
/**
* @brief tOS应用示例
* @details
* @author 01课堂 李述铜 http://01ketang.cc
* @date 2017-06-01
* @version 1.0
* @copyright 版权所有,禁止用于商业用途
*/
#include "tinyOS.h"
#include "app.h"
#include "hal.h"
static tTask task1; // 任务1结构
static tTask task2; // 任务2结构
static tTask task3; // 任务3结构
static tTask task4; // 任务4结构
static tTaskStack task1Env[TASK1_ENV_SIZE]; // 任务1的堆栈空间
static tTaskStack task2Env[TASK2_ENV_SIZE]; // 任务2的堆栈空间
static tTaskStack task3Env[TASK3_ENV_SIZE]; // 任务3的堆栈空间
static tTaskStack task4Env[TASK4_ENV_SIZE]; // 任务4的堆栈空间
int task1Flag; // 用于指示任务运行状态的标志变量
int task2Flag; // 用于指示任务运行状态的标志变量
int task3Flag; // 用于指示任务运行状态的标志变量
int task4Flag; // 用于指示任务运行状态的标志变量
static tMutex mutexA;
static tMutex mutexB;
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task1Entry (void *param) {
for (;;) {
do {
int error = 0;
tMutexWait(&mutexA, 0);
interruptByOtherTask(); // 中间可能运行了很多代码,被打断
error = tMutexWait(&mutexB, 10);
if (error == tErrorNoError) {
break;
}
tMutexNotify(&mutexA);
} while (1);
task1Flag = 1;
tTaskDelay(1);
task1Flag = 0;
tTaskDelay(1);
tMutexNotify(&mutexB);
tMutexNotify(&mutexA);
task1Flag = 1;
tTaskDelay(1);
task1Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task2Entry (void *param) {
for (;;) {
tMutexWait(&mutexB, 0);
interruptByOtherTask(); // 中间可能运行了很多代码,被打断
tMutexWait(&mutexA, 0);
task2Flag = 1;
tTaskDelay(1);
task2Flag = 0;
tTaskDelay(1);
tMutexNotify(&mutexA);
tMutexNotify(&mutexB);
task2Flag = 1;
tTaskDelay(1);
task2Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task3Entry (void *param) {
for (;;) {
task3Flag = 1;
tTaskDelay(1);
task3Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task4Entry (void *param) {
for (;;) {
task4Flag = 1;
tTaskDelay(1);
task4Flag = 0;
tTaskDelay(1);
}
}
/**
* App的初始化
*/
void tInitApp (void) {
halInit();
tMutexInit(&mutexA);
tMutexInit(&mutexB);
tTaskInit(&task1, task1Entry, (void *) 0x0, TASK1_PRIO, task1Env, sizeof(task1Env));
tTaskInit(&task2, task2Entry, (void *) 0x0, TASK2_PRIO, task2Env, sizeof(task2Env));
tTaskInit(&task3, task3Entry, (void *) 0x0, TASK3_PRIO, task3Env, sizeof(task3Env));
tTaskInit(&task4, task4Entry, (void *) 0x0, TASK4_PRIO, task4Env, sizeof(task4Env));
}
/**
* @brief tOS应用示例
* @details
* @author 01课堂 李述铜 http://01ketang.cc
* @date 2017-06-01
* @version 1.0
* @copyright 版权所有,禁止用于商业用途
*/
#include "tinyOS.h"
#include "app.h"
#include "hal.h"
static tTask task1; // 任务1结构
static tTask task2; // 任务2结构
static tTask task3; // 任务3结构
static tTask task4; // 任务4结构
static tTaskStack task1Env[TASK1_ENV_SIZE]; // 任务1的堆栈空间
static tTaskStack task2Env[TASK2_ENV_SIZE]; // 任务2的堆栈空间
static tTaskStack task3Env[TASK3_ENV_SIZE]; // 任务3的堆栈空间
static tTaskStack task4Env[TASK4_ENV_SIZE]; // 任务4的堆栈空间
int task1Flag; // 用于指示任务运行状态的标志变量
int task2Flag; // 用于指示任务运行状态的标志变量
int task3Flag; // 用于指示任务运行状态的标志变量
int task4Flag; // 用于指示任务运行状态的标志变量
static tMutex mutexA;
static tMutex mutexB;
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task1Entry (void *param) {
for (;;) {
tMutexWait(&mutexA, 0);
interruptByOtherTask(); // 中间可能运行了很多代码,被打断
tMutexWait(&mutexB, 0);
task1Flag = 1;
tTaskDelay(1);
task1Flag = 0;
tTaskDelay(1);
tMutexNotify(&mutexB);
tMutexNotify(&mutexA);
task1Flag = 1;
tTaskDelay(1);
task1Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task2Entry (void *param) {
for (;;) {
tMutexWait(&mutexA, 0);
interruptByOtherTask(); // 中间可能运行了很多代码,被打断
tMutexWait(&mutexB, 0);
task2Flag = 1;
tTaskDelay(1);
task2Flag = 0;
tTaskDelay(1);
tMutexNotify(&mutexB);
tMutexNotify(&mutexA);
task2Flag = 1;
tTaskDelay(1);
task2Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task3Entry (void *param) {
for (;;) {
task3Flag = 1;
tTaskDelay(1);
task3Flag = 0;
tTaskDelay(1);
}
}
/**
* 任务的运行代码
* @param param 任务初始运行参数
*/
void task4Entry (void *param) {
for (;;) {
task4Flag = 1;
tTaskDelay(1);
task4Flag = 0;
tTaskDelay(1);
}
}
/**
* App的初始化
*/
void tInitApp (void) {
halInit();
tMutexInit(&mutexA);
tMutexInit(&mutexB);
tTaskInit(&task1, task1Entry, (void *) 0x0, TASK1_PRIO, task1Env, sizeof(task1Env));
tTaskInit(&task2, task2Entry, (void *) 0x0, TASK2_PRIO, task2Env, sizeof(task2Env));
tTaskInit(&task3, task3Entry, (void *) 0x0, TASK3_PRIO, task3Env, sizeof(task3Env));
tTaskInit(&task4, task4Entry, (void *) 0x0, TASK4_PRIO, task4Env, sizeof(task4Env));
}
参考资料: