Lecture: Concurrency and scheduling

preparation

overview

locks

struct lock { int locked; };

void acquire(struct lock *l)
{
  for (;;) {
    if (l->locked == 0) { // A: test
      l->locked = 1;      // B: set
      return;
    }
  }
}

void release(struct lock *l)
{
  l->locked = 0;
}
void acquire(struct lock *l)
{
  while (__sync_lock_test_and_set(&l->locked, 1) != 0)
    ;
}

void release(struct lock *l)
{
  __sync_lock_release(&l->locked);
}

threads

      +-----+             +-----+
      | sh  |             | cat |
      +-----+             +-----+
         |                   ^
user     |                   |
==================================
kernel   |                   |
         v                   |
        +-+       +-+       +-+
        | | swtch | | swtch | |
        | | ----> | | ----> | |
        | |       | |       | |
        +-+       +-+       +-+
       kstack    kstack    kstack
         sh     scheduler   cat

scheduling

// user/spin.c
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

int
main(int argc, char *argv[])
{
  int pid;

  pid = fork();
  if(pid < 0){
    printf("fork failed\n");
    exit(1);
  }

  while (1) {}
  exit(0);
}
     +-------+           +-------+
     | spin  |           | spin  |
     | pid=3 |           | pid=4 |
     +-------+           +-------+
         |                   ^
user     |                   |
==================================
kernel   |                   |
         v                   |
        +-+       +-+       +-+
        | | swtch | | swtch | |
        | | ----> | | ----> | |
        | |       | |       | |
        +-+       +-+       +-+
       kstack    kstack    kstack
       spin(3)   scheduler spin(4)

Q&A

struct lock { _Atomic int next, now_serving; };

void acquire(struct lock *l)
{
  int ticket = atomic_fetch_add(&l->next, 1);
  while (l->now_serving != ticket) {}
}

void release(struct lock *l)
{
  ++l->now_serving;
}