diff -u xv6-public/defs.h xv6/defs.h
--- xv6-public/defs.h	2021-08-25 16:24:12.000000000 -0400
+++ xv6/defs.h	2021-10-20 17:14:39.763163191 -0400
@@ -120,6 +120,7 @@
 int             wait(void);
 void            wakeup(void*);
 void            yield(void);
+int             setpriority(int, int);
 
 // swtch.S
 void            swtch(struct context**, struct context*);
Only in xv6: .edit
Common subdirectories: xv6-public/.git and xv6/.git
diff -u xv6-public/Makefile xv6/Makefile
--- xv6-public/Makefile	2021-08-27 12:53:33.000000000 -0400
+++ xv6/Makefile	2021-10-20 17:06:54.810141196 -0400
@@ -183,6 +183,7 @@
 	_usertests\
 	_wc\
 	_zombie\
+	_nice\
 
 fs.img: mkfs README $(UPROGS)
 	./mkfs fs.img README $(UPROGS)
Only in xv6: nice.c
diff -u xv6-public/proc.c xv6/proc.c
--- xv6-public/proc.c	2021-08-25 16:24:12.000000000 -0400
+++ xv6/proc.c	2021-10-20 17:12:50.747158034 -0400
@@ -112,6 +112,8 @@
   memset(p->context, 0, sizeof *p->context);
   p->context->eip = (uint)forkret;
 
+  p->priority = p->schedtick = 0;
+
   return p;
 }
 
@@ -336,6 +338,10 @@
       if(p->state != RUNNABLE)
         continue;
 
+      if (p->schedtick < 0) {
+	p->schedtick++;
+	continue;
+      }
       // Switch to chosen process.  It is the process's job
       // to release ptable.lock and then reacquire it
       // before jumping back to us.
@@ -348,6 +354,7 @@
 
       // Process is done running for now.
       // It should have changed its p->state before coming back.
+      p->schedtick = p->priority;
       c->proc = 0;
     }
     release(&ptable.lock);
@@ -385,9 +392,13 @@
 void
 yield(void)
 {
+  struct proc *p = myproc();
+
   acquire(&ptable.lock);  //DOC: yieldlock
-  myproc()->state = RUNNABLE;
-  sched();
+  if (p->schedtick-- < 0) {
+    p->state = RUNNABLE;
+    sched();
+  }
   release(&ptable.lock);
 }
 
@@ -438,6 +449,7 @@
   // Go to sleep.
   p->chan = chan;
   p->state = SLEEPING;
+  p->schedtick = 0;
 
   sched();
 
@@ -460,8 +472,10 @@
   struct proc *p;
 
   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
-    if(p->state == SLEEPING && p->chan == chan)
+    if(p->state == SLEEPING && p->chan == chan) {
       p->state = RUNNABLE;
+      p->schedtick = p->priority;
+    }
 }
 
 // Wake up all processes sleeping on chan.
@@ -496,6 +510,23 @@
   return -1;
 }
 
+int
+setpriority(int pid, int pri)
+{
+  struct proc *p;
+
+  acquire(&ptable.lock);
+  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
+    if(p->pid == pid){
+      p->priority = pri;
+      release(&ptable.lock);
+      return 0;
+    }
+  }
+  release(&ptable.lock);
+  return -1;
+}
+
 //PAGEBREAK: 36
 // Print a process listing to console.  For debugging.
 // Runs when user types ^P on console.
@@ -523,7 +554,7 @@
       state = states[p->state];
     else
       state = "???";
-    cprintf("%d %s %s", p->pid, state, p->name);
+    cprintf("%d %s %s [%d]", p->pid, state, p->name, p->priority);
     if(p->state == SLEEPING){
       getcallerpcs((uint*)p->context->ebp+2, pc);
       for(i=0; i<10 && pc[i] != 0; i++)
diff -u xv6-public/proc.h xv6/proc.h
--- xv6-public/proc.h	2021-08-25 16:24:12.000000000 -0400
+++ xv6/proc.h	2021-10-20 17:04:24.605134091 -0400
@@ -49,6 +49,7 @@
   struct file *ofile[NOFILE];  // Open files
   struct inode *cwd;           // Current directory
   char name[16];               // Process name (debugging)
+  int priority, schedtick;
 };
 
 // Process memory is laid out contiguously, low addresses first:
diff -u xv6-public/syscall.c xv6/syscall.c
--- xv6-public/syscall.c	2021-08-25 16:24:12.000000000 -0400
+++ xv6/syscall.c	2021-10-20 17:13:15.238159192 -0400
@@ -103,6 +103,7 @@
 extern int sys_wait(void);
 extern int sys_write(void);
 extern int sys_uptime(void);
+extern int sys_setpriority(void);
 
 static int (*syscalls[])(void) = {
 [SYS_fork]    sys_fork,
@@ -126,6 +127,7 @@
 [SYS_link]    sys_link,
 [SYS_mkdir]   sys_mkdir,
 [SYS_close]   sys_close,
+[SYS_setpriority] sys_setpriority,
 };
 
 void
diff -u xv6-public/syscall.h xv6/syscall.h
--- xv6-public/syscall.h	2021-08-25 16:24:12.000000000 -0400
+++ xv6/syscall.h	2021-10-20 16:45:17.204079813 -0400
@@ -20,3 +20,4 @@
 #define SYS_link   19
 #define SYS_mkdir  20
 #define SYS_close  21
+#define SYS_setpriority 22
diff -u xv6-public/sysproc.c xv6/sysproc.c
--- xv6-public/sysproc.c	2021-08-25 16:24:12.000000000 -0400
+++ xv6/sysproc.c	2021-10-20 16:50:29.369094580 -0400
@@ -89,3 +89,13 @@
   release(&tickslock);
   return xticks;
 }
+
+int
+sys_setpriority(void)
+{
+  int pid, pri;
+  if (argint(0, &pid) < 0) return -1;
+  if (argint(1, &pri) < 0) return -1;
+
+  return setpriority(pid, pri);
+}
diff -u xv6-public/user.h xv6/user.h
--- xv6-public/user.h	2021-08-25 16:24:12.000000000 -0400
+++ xv6/user.h	2021-10-20 16:39:56.515064643 -0400
@@ -23,6 +23,7 @@
 char* sbrk(int);
 int sleep(int);
 int uptime(void);
+int setpriority(int, int);
 
 // ulib.c
 int stat(const char*, struct stat*);
diff -u xv6-public/usys.S xv6/usys.S
--- xv6-public/usys.S	2021-08-25 16:24:12.000000000 -0400
+++ xv6/usys.S	2021-10-20 16:45:23.992080134 -0400
@@ -29,3 +29,4 @@
 SYSCALL(sbrk)
 SYSCALL(sleep)
 SYSCALL(uptime)
+SYSCALL(setpriority)
