我正在为 thrd_stop 函数编写代码。它具有与 xv6 中第 4 章的练习实验室类似的功能,即警报。当调用 thrd_stop 时,启动一个计时器并在计时器到达 inverval 时调用处理程序。我的做法和 xv6 做法的区别在于我需要向处理程序提供参数。我已经将以下内容添加到 proc.
的属性中 int thrdstop_ticks;
int thrdstop_interval;
uint64 threstop_handler;
uint64 thrdstop_handler_args;
struct trapframe thrdstop_context[MAX_THRD_NUM];
int thrdstop_context_used[MAX_THRD_NUM];
int thrdstop_context_id;
int timeFlag;
这是我的第三站:
uint64
sys_thrdstop(void)
{
int delay;
uint64 context_id_ptr;
uint64 handler, handler_arg;
if (argint(0, &delay) < 0)
return -1;
if (argaddr(1, &context_id_ptr) < 0)
return -1;
if (argaddr(2, &handler) < 0)
return -1;
if (argaddr(3, &handler_arg) < 0)
return -1;
struct proc *proc = myproc();
proc->thrdstop_interval = delay;
proc->threstop_handler = handler;
proc->thrdstop_handler_args = handler_arg;
int kernelPtr;
copyin(proc->pagetable, (char *)&kernelPtr, context_id_ptr, sizeof(kernelPtr));
if (kernelPtr == -1)
{
for (int i = 0; i < MAX_THRD_NUM; i++)
{
if (!proc->thrdstop_context_used[i])
{
kernelPtr = i;
copyout(proc->pagetable, context_id_ptr, (char *)&kernelPtr, sizeof(kernelPtr));
proc->thrdstop_context_used[i] = 1;
proc->thrdstop_context_id = i;
break;
}
}
if (kernelPtr == -1)
return -1;
}
proc->thrdstop_context_id = kernelPtr;
return 0;
}
uint64
sys_thrdresume(void)
{
int context_id;
if (argint(0, &context_id) < 0)
return -1;
struct proc *proc = myproc();
if (proc->thrdstop_context_used[context_id] == 0)
return -1;
proc->thrdstop_context_used[context_id] = 0;
proc->thrdstop_interval = 0;
proc->thrdstop_context_id = -1;
// printf("resume\n");
memmove(proc->trapframe, &proc->thrdstop_context[context_id], sizeof(proc->thrdstop_context[context_id]));
proc->timeFlag = 0;
return 0;
}
在 usertrap 和 kerneltrap 中,我做了下面的事情。
if (which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING)
{
if (p->thrdstop_interval == 0 && p->threstop_handler == 0)
goto yield;
if (p->thrdstop_ticks == p->thrdstop_interval)
{
if(!p->timeFlag)
{
// intr_off();
memmove(&p->thrdstop_context[p->thrdstop_context_id],p->trapframe,sizeof(p->thrdstop_context[p->thrdstop_context_id]));
// printf("%d",p->trapframe->a0);
// printf("kernel %d\n",p->thrdstop_context_id);
p->trapframe->a0=p->thrdstop_handler_args;
p->trapframe->epc = p->threstop_handler;
p->thrdstop_ticks = 0;
p->timeFlag=1;
}
}
else
{
p->thrdstop_ticks += 1;
}
yield:
yield();
}
现在的问题是,将a0改成handler_args后,有时会被其他系统调用覆盖,比如其他定时器中断。在这种情况下,当执行处理程序时,它不能使用正确的参数。有没有办法在跳回用户空间之前正确传递参数而不被其他系统调用覆盖?