Search code examples
operating-systemsystem-callsxv6

undefined reference to `sys_getprocs' when getting number of processes in Xv6


I was playing with the Xv6 OS lab and trying to implement a simple syscall getprocs() that returns the number of processes currently running. I finished the work pretty soon but I kept getting the following error message when I was trying to do make qemu:

riscv64-unknown-elf-ld: warning: cannot find entry symbol _entry; defaulting to 0000000080000000
riscv64-unknown-elf-ld: kernel/syscall.o: in function `syscall':
/xv6-labs-2020/kernel/syscall.c:143: undefined reference to `sys_getprocs'
riscv64-unknown-elf-ld: kernel/syscall.o: in function `.LANCHOR0':
syscall.c:(.rodata+0xc8): undefined reference to `sys_getprocs'
make: *** [Makefile:94: kernel/kernel] Error 1

Here's what I did.

  • I declared a user function int getprocs(void); in user/user.h.
  • I then created a new file kernel/getprocs.c, where the system call interface is implemented as the following:
#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "spinlock.h"
#include "proc.h"
#include "defs.h"
#include "syscall.h"

extern int get_procs(void);

uint64
sys_getprocs(void)
{
  return get_procs();
}

  • Following this, I went to kernel/proc.c to add the actual int get_procs(void) that counts all the used processes in the system:
int
get_procs(void)
{
  int num_procs = 0;
  
  struct proc *p;

  for(p = proc; p < &proc[NPROC]; p++) {
    acquire(&p->lock);
    if(p->state != UNUSED) num_procs++;
    release(&p->lock);
  }

  return num_procs;

}
  • I assigned a new syscall number for my new function in kernel/syscall.h like this: #define SYS_getprocs 22.
  • Having assigned a new syscall number, I went to modify the system call table in syscall.c. Here I made two modifications:
  1. add [SYS_getprocs] sys_getprocs, to the static uint64 (*syscalls[])(void). I didn't understand exactly how this work but I added it anyway.
  2. within function void syscall(), I changed it to:
void
syscall(void)
{
  int num;
  struct proc *p = myproc();

  num = p->trapframe->a7;
  if(num == SYS_getprocs) p->trapframe->a0 = sys_getprocs();
  else if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
    p->trapframe->a0 = syscalls[num]();
  } else {
    printf("%d %s: unknown sys call %d\n",
            p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

This should handle the newly added system call.

  • Finally, I added a new mapping in user/usys.pl: entry("getprocs");

I reviewed over and over again, still clueless where it went wrong. Any help would be appreciated!


Solution

  • You just forgot to ask for compilation of getprocs.o into Makefile:

    just add the line $K/getprocs.o in OBJS definition:

    K=kernel
    U=user
    
    OBJS = \
      ...
      $K/main.o \
      $K/vm.o \
      $K/proc.o \
      $K/getprocs.o \ <-- just here, Warning, you not must add any character after '\' but a new line.
      $K/swtch.o \
      ...