问题
Mutex 相关函数接口处于用户态还是内核态?
问题中的问题
Mutex操作可能导致任务状态的切换 (执行态 => 阻塞态),其功能只能由内核实现
通过 0x80 中断从用户态调用内核功能
系统调用重设计
互斥锁系统调用功能设计
整体调用流程
D.T.OS 架构图
互斥锁模块的创建
mutex.h
#ifndef MUTEX_H
#define MUTEX_H
#include "type.h"
typedef void 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"
void MutexModInit()
{
}
void MutexCallHandler(uint cmd, uint param)
{
if(cmd == 0)
{
PrintString("Muetx Create\n");
PrintIntHex(param);
PrintChar('\n');
}
else if(cmd == 1)
{
PrintString("Muetx Enter\n");
}
else if(cmd == 2)
{
PrintString("Muetx Exit\n");
}
else
{
PrintString("Muetx Destroy\n");
}
}
syscall.h
#ifndef SYSCALL_H
#define SYSCALL_H
#include "type.h"
void Exit();
uint CreateMutex();
void EnterCritical(uint mutex);
void ExitCritical(uint mutex);
void DestroyMutex(uint mutex);
#endif
syscall.c
#include "syscall.h"
void Exit()
{
asm volatile(
"movl $0, %eax \n" // type
"int $0x80 \n"
);
}
uint CreateMutex()
{
volatile uint ret = 0;
PrintString("&ret = ");
PrintIntHex(&ret);
asm volatile(
"movl $1, %%eax \n" // type
"movl $0, %%ebx \n" // cmd
"movl %0, %%ecx \n" // param1
"int $0x80 \n"
:
: "r"(&ret)
: "eax", "ebx", "ecx", "edx"
);
return ret;
}
void EnterCritical(uint mutex)
{
asm volatile(
"movl $1, %%eax \n" // type
"movl $1, %%ebx \n" // cmd
"movl %0, %%ecx \n" // param1
"int $0x80 \n"
:
: "r"(mutex)
: "eax", "ebx", "ecx", "edx"
);
}
void ExitCritical(uint mutex)
{
asm volatile(
"movl $1, %%eax \n" // type
"movl $2, %%ebx \n" // cmd
"movl %0, %%ecx \n" // param1
"int $0x80 \n"
:
: "r"(mutex)
: "eax", "ebx", "ecx", "edx"
);
}
void DestroyMutex(uint mutex)
{
asm volatile(
"movl $1, %%eax \n" // type
"movl $3, %%ebx \n" // cmd
"movl %0, %%ecx \n" // param1
"int $0x80 \n"
:
: "r"(mutex)
: "eax", "ebx", "ecx", "edx"
);
}
ihandler.c
void SysCallHandler(uint type, uint cmd, uint param1, uint param2) // __cdcel__
{
switch(type)
{
case 0:
KillTask();
break;
case 1:
MutexCallHandler(cmd, param1);
break;
default:
break;
}
}
kentry.asm
;
;
SysCallHandlerEntry:
BeginISR
push edx
push ecx
push ebx
push eax
call SysCallHandler
pop eax
pop ebx
pop ecx
pop edx
EndISR
task.c
void TaskEntry()
{
if(gCTaskAddr != NULL)
{
gCTaskAddr->tmain();
}
// to destory current task here
asm volatile(
"movl $0, %eax \n"
"int $0x80 \n"
);
while(1); // TODO: schedule next task to run
}
app.c
void TaskA()
{
int i = 0;
volatile uint mutex = 0;
SetPrintPos(0, 12);
PrintString(__FUNCTION__);
PrintChar('\n');
mutex = CreateMutex();
EnterCritical(mutex);
ExitCritical(mutex);
DestroyMutex(mutex);
}
mutex.h 中声明了 4 个 Mutex 的相关函数,这是内核中的函数,应用程序需要通过 0x80 号中断来调用内核函数,在 syscall.h 中实现了给应用程序提供的系统函数接口,利用 type 和 cmd 通过 0x80 号中断来转移特权级,执行相应的内核函数。
修改后的 SysCallHandler 中有4个参数,因为不同特权级对应不同的栈,所以在特权级转移的时候,如若我们想要保存参数,那么相应的参数就不能入栈,而是得保存在寄存器中。
type 为1就会调用 MutexCallHandler 函数, MutexCallHandler 函数根据 cmd 再调用相应的 Mutex函数。
我们通过系统函数接口,可以成功升高特权级去执行内核的函数,并且内核也能成功的接收到应用程序传递过来的参数。
思考
在内核中实现互斥锁的功能是必要的吗?