Skip to content

Instantly share code, notes, and snippets.

@valkheim
Created April 22, 2019 18:30
Show Gist options
  • Save valkheim/fdf1f930d43d2e884bf38eada82ef498 to your computer and use it in GitHub Desktop.
Save valkheim/fdf1f930d43d2e884bf38eada82ef498 to your computer and use it in GitHub Desktop.
/* Lamport's bakery algorithm */
/* Improve safety in the usage of shared resources among multiple threads by */
/* means of mutual exclusion */
/* Communications of the ACM, August 1974, Volume 17, Number 8, P.453 */
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#define NUM_THREADS (20)
#define NAN (0) /* invalid number */
/* The counter threads will increment */
static unsigned int c;
/* This indicates if a thread is choosing a number */
static bool choosing[NUM_THREADS] = { false };
/* This is the priority system, the smallest enters the critical section */
static unsigned int numbers[NUM_THREADS] = { NAN }; /* must have been unbound */
static unsigned int max_in_numbers(void) {
/* Retrieve the greatest number in numbers[] */
unsigned int max = 0;
for (unsigned int i = 0 ; i < NUM_THREADS ; ++i) {
if (numbers[i] > max)
max = numbers[i];
}
return max;
}
#define LESS(i, j) \
(numbers[j] < numbers[i]) || ((numbers[j] == numbers[i]) && (j < i))
/* i represent a single thread */
/* j is sequentially representing all the threads */
static void lock(unsigned int const i) {
/* We are choosing our number */
choosing[i] = true;
/* We have a maximum value number */
numbers[i] = 1 + max_in_numbers(); /* unsafe ? */
/* We chose our number */
choosing[i] = false;
/* We will observe other threads */
for (unsigned int j = 0 ; j < NUM_THREADS ; ++j) {
/* We are waiting for every other thread j to choose a number */
while (choosing[j] == true) {
/* We are busy for an other thread j to choose its number */
}
/* We are waiting other threads to have a chose number which is strictly */
/* less than ours */
while (numbers[j] != NAN && LESS(i, j)) {
/* Waiting for an other thread j to have a smaller number than our */
}
}
/* At this point we have the smallest number of all the threads so we have */
/* priority to enter the critical section */
}
static void unlock(unsigned int const i) {
/* We reset our smallest number so an other thread can enter the critical */
/* section */
numbers[i] = NAN;
}
static void inc(void) {
for (unsigned int i = 0 ; i < 5000 ; ++i) {
c++;
}
}
static void *inc_safe(void *args) {
unsigned int tid = *(unsigned int *)args;
lock(tid);
inc();
unlock(tid);
pthread_exit(0);
}
static void *inc_unsafe(void *args) {
(void)args;
inc();
pthread_exit(0);
}
int main() {
unsigned int tid[NUM_THREADS];
pthread_t t[NUM_THREADS];
for (unsigned int i = 0 ; i < NUM_THREADS; ++i)
tid[i] = i;
c = 0;
for (unsigned int i = 0 ; i < NUM_THREADS; ++i)
pthread_create(&t[i], NULL, inc_unsafe, &tid[i]);
for (unsigned int i = 0 ; i < NUM_THREADS; ++i)
pthread_join(t[i], NULL);
printf("counter (unsafe) = %d\n", c);
c = 0;
for (unsigned int i = 0 ; i < NUM_THREADS; ++i)
pthread_create(&t[i], NULL, inc_safe, &tid[i]);
for (unsigned int i = 0 ; i < NUM_THREADS; ++i)
pthread_join(t[i], NULL);
printf("counter (safe) = %d\n", c);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment