Search code examples
cmultithreadingx86cpu-registersxv6

Register pointer in creating threads in xv6


I want to create a thread in xv6 by using a system call "clone()", but I am confused about the stack creation, since if I want to create a thread, I need to create the corresponding register pointer such like ebp, esp, eip. But I don't know how to set the value of these register pointer.

Here is a code of clone() in xv6, I don't know why we need to set the value of the register pointer like this.......

int clone(void(*fcn)(void*), void *arg, void*stack){

  int i, pid;
  struct proc *np;
  int *ustack = stack + PGSIZE - sizeof(void*);
  //allocate process.
  if((np=allocproc()) == 0)
    return -1;

  //copy process state from p
  np->pgdir = proc->pgdir;
  np->sz = proc->sz;
  np->parent = 0;
  np->pthread = proc;
  *np->tf = *proc->tf;
  np->ustack = stack;

  //initialize stack variables 
  //void *stackArg, *stackRet;
  //stackRet = stack + PGSIZE -2*sizeof(void*);
  //*(uint *)stackRet = 0xffffffff;

  //stackArg = stack + PGSIZE -sizeof(void*);
  //*(uint *)stackArg = (uint)arg;
  *ustack = (int) arg;
  *(ustack - 1) = 0xffffffff;
  *(ustack - 2) = 0xffffffff;


  //Set stack pinter register
  np->tf->eax = 0;
  np->tf->esp = (int) ustack - sizeof(void*);
  np->tf->ebp = np->tf->esp;
  np->tf->eip = (int)fcn;

  for(i = 0; i < NOFILE; i++) {
    if(proc->ofile[i])
      np->ofile[i] = filedup(proc->ofile[i]);
  }

  np->cwd = idup(proc->cwd);
  np->state = RUNNABLE;
  safestrcpy(np->name, proc->name, sizeof(proc->name));
  pid = np->pid;
  return pid;

}

Solution

  • You don't set these registers -- clone sets them for you. You need to provide a function (which clone uses to initialize ip) and a stack (which clone uses to initialize sp).

    The function pointer is pretty straight-forward (its just a C function pointer), but the stack is trickier. For the clone implementation you show, you need to allocate some memory and provide a pointer PGSIZE below the end of that block. Linux's clone call is similar, but slightly different (you need to provide a pointer to the end of the block). If you want to catch stack overflows, you'll need to do more work (probably allocating a read/write protected guard page below the stack).