6.1 KiB
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 } }
- very similar to the errant Load/Store lock, but the special instructions here can detect intervening
- 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); }
-