LogSeq/pages/OSTEP Code Snippets.md
2023-04-13 10:16:50 +08:00

6.1 KiB

  • Spin Lock Implement id:: 6436aafd-c85f-414c-8aee-acdc71e9138e
    • void lock(lock_t *lock) {
        while (TestAndSet(&lock->status, 1) == 1);
      }
      void unlock(lock_t *lock) { lock->status = 0; }
      
  • Test-And-Set Code Description id:: 6436af87-3f1b-4ee8-a2c8-4de0f1961f1a
    • int TestAndSet(int *old_ptr, int new) {
        int old = *old_ptr;
        *old_ptr = new;
        return old;
      }
      
  • Ticket Lock Implement id:: 6436af5c-0000-4bfb-9a27-1d7cf0a830db
    • struct lock_t{
        int ticket;
        int turn;
      };
      void lock(lock_t *lock) {
        int myturn = FetchAndAdd(&lock->ticket);
        // atomically allocate a ticket as the thread's turn
        while (lock->turn != myturn) ;
        // wait for its turn
      }
      void unlock(lock_t *lock) {
        lock->turn += 1;
      }
      
  • Lock with Queue Implement id:: 6436b05f-2873-4af4-952c-86d82685b583
    • struct lock_t{
        int lk;
        int guard; // spin lock for the whole lock
        queue_t *q; // control who gets the lock next
      };
      void lock(lock_t *lock) {
        while (TestAndSet(&m->guard, 1) == 1) ;
        if (m->lk == 0) {
          m->lk =  1;
          m->guard = 0;
        }
        else {
          m->q->add(get_tid());
          setpark(); // newly added
          m->guard = 0;
          // ---- wakeup/waiting race ----
          park();
        }
      }
      void unlock(lock_t *lock) {
        while (TestAndSet(&m->guard, 1) == 1) ;
        if (m->q->empty())
          m->flag = 0;
        else
          unpark(m->q->pop()); // should not clear flag here
        // Wake up Only one waiting thread
        m->guard = 0;
      }
      
  • Producer/Consumer Solution with Condition Variable id:: 6436b07d-9279-46bb-9c6b-985eb2324df8
    • cond_t empty, fill;
      mutex_t mutex;
      void *producer(void *arg) {
        int i;
        for (i = 0; i < loops; i++) {
          Pthread_mutex_lock(&mutex);
          while (count == MAX)
            Pthread_cond_wait(&empty, &mutex);
          put(i);
          Pthread_cond_signal(&fill);
          Pthread_mutex_unlock(&mutex);
        }
      }
      void *consumer(void *arg) {
        int i;
        for (i = 0; i < loops; i++) {
          Pthread_mutex_lock(&mutex);
          while (count == 0)
            Pthread_cond_wait(&fill, &mutex);
          int tmp = get();
          Pthread_cond_signal(&empty);
          Pthread_mutex_unlock(&mutex);
          printf("%d\n", tmp);
        }
      }
      
  • Producer/Consumer Solution with Semaphore id:: 6436b15a-98b4-49be-8cdf-abefcf7e60b1
    • int empty = MAX, full = 0, mutex = 1;
      void *producer() {
        for (int i = 0; i < loops; ++ i) {
          sem_wait(&empty);
          sem_wait(&mutex);
          put(i);
          sem_post(&mutex);
          sem_post(&full);
        }
      }
      void *consumer() {
        for (int i = 0; i < loops; ++ i) {
          sem_wait(&full);
          sem_wait(&mutex);
          int tmp = get();
          sem_post(&mutex);
          sem_post(&empty);
          printf("%d\n", tmp);
        }
      }
      
  • Dining Philosopher Solution with Semaphore id:: 6436bebd-0681-4f94-9d04-4d8e4a554512
    • void put_forks(int p) {
        sem_post(&forks[left(p)]);
        sem_post(&forks[right(p)]);
      }
      void get_forks(int p) {
        if (p == 4) {
          sem_wait(&forks[right(p)]);
          sem_wait(&forks[left(p)]);
        } else {
          sem_wait(&forks[left(p)]);
          sem_wait(&forks[right(p)]);
        }
      }
      void philosopher() {
        while (1) {
          think();
          get_forks(p);
          eat();
          put_forks(p);
        }
      }
      
  • Simple Semaphore Implement id:: 6436c47e-dc86-4452-b9b5-4e7997dbfbfb
    • struct sem_t{
        int value;
        cond_t cond;
        mutex_t lock;
      };
      void sem_wait(sem_t *sem) {
        mutex_lock(&sem->lock);
        while (s->value <= 0)
          cond_wait(&sem->cond, &sem->lock);
        s->value --;
        mutex_unlock(&sem->lock);
      }
      void sem_post(sem_t *sem) {
        mutex_lock(&sem->lock);
        sem->value ++;
        cond_signal(&sem->cond);
        mutex_unlock(&sem->lock);
      }
      
  • Compare-And-Swap Code Description id:: 6436c5c7-32e7-4071-b909-4fdc14bb479d
    • int CompareAndSwap(int *ptr, int expected, int new) {
        int original = *ptr;
        if (original == expected) *ptr = new;
        return orginial
      }
      
  • Compare-and-swap flavor spin lock id:: b7679e9b-aabe-4bd3-8c2c-eb0a23fad491
    • void lock(lock_t *lock) {
        while (CompareAndSwap(&lock->status, 0, 1) == 1) ;
      }
      
  • LL/SC Code Description id:: 6436c620-4884-45a7-9273-b7952a6521ae
    • int LL(int *ptr) { return *ptr; }
      int SC(int *ptr, int value) {
        if (/*no update to *ptr since LoadLinked to this address*/) {
          *ptr = value;
          return 1; // success!
        } else {
          return 0; // failed to update
        }
      }
      
  • LL/SC flavor spin lock id:: c38274a9-22dd-40e2-b74a-d3a9be63600e
    • very similar to the errant Load/Store lock, but the special instructions here can detect intervening
      void lock(lock_t *lock) {
        while (true) {
          while (LL(&lock->status) == 1) ; // test
          if (SC(&lock->status, 1) == 1) // set
            break;
          // else retry, in case lock->status is changed
        }
      }
      
  • Simple Yield Lock Code id:: 6436c684-ac4a-4144-9e7e-b4cb8f976c1f
    • void lock(lock_t *lock) {
        while (TestAndSet(&lock->status, 1) == 1)
          yield();
      }
      
  • Fetch-And-Add Code Description id:: 6436c66c-807b-4e9d-93ed-b1d9703e6dc2
    • int FetchAndAdd(int *ptr) {
        int old = *ptr;
        *ptr = old + 1;
        return old;
      }
      
  • Readers-Writer Lock Implement id:: 6436c668-5be8-4ce1-b701-1f2a00d34cc9
    • typedef struct _rwlock_t {
        sem_t guard; // binary semaphore (basic lock)
        sem_t writelock; // allow ONE writer/MANY readers
        int readers; // #readers in critical section
      } rwlock_t;
      void rwlock_acquire_readlock(rwlock_t *rw) {
        sem_wait(&rw->guard);
        if (++rw->readers == 1) sem_wait(&rw->writelock);
        sem_post(&rw->guard);
      }
      void rwlock_release_readlock(rwlock_t *rw) {
        sem_wait(&rw->guard);
        if (--rw->readers == 0) sem_post(&rw->writelock);
        sem_post(&rw->guard);
      }
      void rwlock_acquire_writelock(rwlock_t *rw) { sem_wait(&rw->writelock); }
      void rwlock_release_writelock(rwlock_t *rw) { sem_post(&rw->writelock); }