1

I am writing codes on a thrd_stop function. It has similar functionality as the practice lab of chapter 4 in xv6, the alarm. When thrd_stop is called, start a timer and call handler when the timer reaches the inverval. The difference between mine and xv6 practice is that I need to provide arguments to the handler. I've add the below things to attributes of 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;

And here is my thrdstop:

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;
}

And in usertrap and kerneltrap, I do the below things.

    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();
    }

The problem now is that after changing a0 to the handler_args, sometimes it will be overwritten by other system call such as other timer interrupt. In this case, when the handler is executed, it cannot use the correct argument. Is there any way to pass the argument correctly before jumping back to user space without overwritten by other system call?

Adi_Hsiao_0410
  • 111
  • 2
  • 9
  • 1
    AFAIK, `xv6` has processes but _not_ threads. Are you adding thread support? You probably need to create a `struct thread` and put all [most of] the stuff you added to `struct proc` into that. Then, the `proc` struct only needs (e.g.) `struct thread thrd_list[MAX_THRD_NUM];` From a single process, you can't get overwriting of the args because syscalls aren't recursive/reentrant. But, you _can_ get overwrite with _different_ threads of the same process. – Craig Estey May 03 '23 at 01:59
  • 1
    Under linux [for example], each _thread_ has its own "proc" struct (e.g. `struct task`). That is, processes and threads are largely indistinguishable (except for the memory mapping). And, every _thread_ has a _unique_ pid number. But, your thread architecture is _different_ as evidenced by your use of `MAX_THRD_NUM` (e.g.) `struct trapframe thrdstop_context[MAX_THRD_NUM];` – Craig Estey May 03 '23 at 02:04

0 Answers0