进程互斥锁的初步实现(中)

问题

在内核中实现互斥锁的功能是必要的吗?

是必要的。

在内核态实现互斥锁功能的考虑

进入内核态之后所有任务均暂停执行

直观的决定当前任务是否能进入临界区(True or False)

  • True:返回用户态,当前任务继续执行
  • False:当前任务进入阻塞状态,调度下一任务执行

内核拥有最高特权级,能够决定任务的生死

互斥锁内核数据结构及接口实现

设计思想:通过内核链表管理 Mutex 变量,只有链表中的 Mutex 变量才能完成任务间的互斥。

创建互斥锁

销毁互斥锁

进入临界区

退出临界区

互斥锁的内核实现

mutex.h


#ifndef MUTEX_H
#define MUTEX_H

#include "type.h"
#include "list.h"

typedef struct
{
	ListNode head;
	uint lock;
} Mutex;

void MutexModInit();
void MutexCallHandler(uint cmd, uint param);

Mutex* SysCreateMutex();
void SysEnterCritical(Mutex* mutex);
void SysExitCritical(Mutex* mutex);
void SysDestroyMutex(Mutex* mutex);


#endif

mutex.c


#include "mutex.h"
#include "memory.h"

static List gMList = {0};

void MutexModInit()
{
	List_Init(&gMList);
}

void MutexCallHandler(uint cmd, uint param)
{
	if(cmd == 0)
	{
		uint* pRet = (uint*)param;
		
		*pRet = (uint)SysCreateMutex();
	}
	else if(cmd == 1)	
	{
		SysEnterCritical((Mutex*)param);
	}
	else if(cmd == 2)
	{
		SysExitCritical((Mutex*)param);
	}
	else
	{
		SysDestroyMutex((Mutex*)param);
	}
}

static uint IsMutexValid(Mutex* mutex)
{
	uint ret = 0;
	
	if(mutex)
	{
		ListNode* pos = NULL;
		
		List_ForEach(&gMList, pos)
		{
			if(IsEqual(pos, mutex))
			{
				ret = 1;
				
				break;
			}
		}
	}
	
	return ret;
}

Mutex* SysCreateMutex()
{
	Mutex* ret = (Mutex*)Malloc(sizeof(Mutex));
	
	if(ret)
	{
		List_Add(&gMList, (ListNode*)ret);
		
		ret->lock = 0;
	}
	
	PrintString("Create Mutex, ID: ");
	PrintIntHex((uint)ret);
	PrintChar('\n');
	
	return ret;
}

void SysDestroyMutex(Mutex* mutex)
{
	if(mutex)
	{
		ListNode* pos = NULL;
		
		List_ForEach(&gMList, pos)
		{
			if(IsEqual(pos, mutex))
			{
				List_DelNode(pos);
				Free(pos);
				
				PrintString("Destroy Mutex, ID: ");
				PrintIntHex((uint)mutex);
				PrintChar('\n');
				
				break;
			}
		}
	}
}

void SysEnterCritical(Mutex* mutex)
{
	if(IsMutexValid(mutex))
	{
		if(mutex->lock)
		{
			PrintString("Move current to waitting status.\n");
		}
		else
		{
            mutex->lock = 1;

			PrintString("Enter critical section, access critical resource.\n");
		}
	}
}

void SysExitCritical(Mutex* mutex)
{
	if(IsMutexValid(mutex))
	{
		mutex->lock = 0;
		
		PrintString("Notify all tasks to run again, critical resource is available.\n");
	}
}

app.c

void TaskA()
{
    int i = 0;
    volatile uint mutex = 0;
    
    SetPrintPos(0, 12);
    
    PrintString(__FUNCTION__);
    
    PrintChar('\n');
    
    mutex = CreateMutex();
    
    PrintString("Mutex ID: ");
    PrintIntHex(mutex);
    PrintChar('\n');
    
    EnterCritical(mutex);
    
    ExitCritical(mutex);
    
    DestroyMutex(mutex);
}

我们用链表作为实现 Mutex 的数据结构,只有在链表中的 Mutex 变量才能完成任务间的互斥。Mutex 中的 lock 成员作为标志位,用来标识此互斥锁是处于空闲状态还是占用状态。

我们在 TaskA 中创建了一个互斥锁,模拟了进入临界区和退出临界区,最后销毁了互斥锁。我们在3个地方打印了互斥锁的 ID 号,一次在内核创建互斥锁的时候,一次在内核销毁互斥锁的时候,一次在应用程序调用 CreateMutex 函数后,它们的 Mutex ID 值都相等,说明应用程序能够正确的使用内核分配出来的互斥锁。

思考

在当前实现下,阻塞的多个任务重新进入执行态,会发生什么?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值