Skip to content

Instantly share code, notes, and snippets.

@develhox
Created April 13, 2015 19:35
Show Gist options
  • Save develhox/3151350a182dbde785e6 to your computer and use it in GitHub Desktop.
Save develhox/3151350a182dbde785e6 to your computer and use it in GitHub Desktop.
C99 Mutex implementation to avoid same-thread deadlock and define locked portions of code
#ifndef __MUTEX_H__
#define __MUTEX_H__
#include <pthread.h>
/**
* Mutex type
*/
typedef struct {
pthread_mutex_t mutex; // pthread mutex
pthread_t owner; // which thread is using the lock
unsigned int nest; // how many time "owner" called the
// pthread_mutex_lock
} mutex_t;
/**
* Macro to lock a mutex_t object for a specific portion of code (it needs C99)
*/
#define MUTEX_LOCK(lock) for(int __once=mutex_lock(lock); \
__once; __once=mutex_unlock(lock))
/** Initialize a mutex_t object */
static void mutex_init(mutex_t *mutex) {
mutex->owner=-1;
mutex->nest=0;
}
/**
* Lock the mutex.
* If it's locked by the same thread it does nothing
* If it's locked by a different thread, it waits for the mutex to be unlocked
*/
static int mutex_lock(mutex_t *mutex) {
pthread_t self = pthread_self();
if (self != mutex->owner) {
pthread_mutex_lock (&mutex->mutex);
mutex->owner=self;
mutex->nest = 0;
}
mutex->nest++;
return 1;
}
/**
* Unlock the mutex.
* If the locking thread has called the mutex_lock() multiple times, only the last
* mutex_unlock() will unlock the mutex.
*/
static int mutex_unlock(mutex_t *mutex) {
pthread_t self = pthread_self();
if (self == mutex->owner) {
mutex->nest--;
if (0 == mutex->nest) {
mutex->owner=-1;
pthread_mutex_unlock (&mutex->mutex);
}
}
return 0;
}
#endif // __MUTEX_H__
#include <unistd.h>
#include <stdio.h>
#include "mutex.h"
static mutex_t mutex;
/**
* | T0 | T1 |
* 0s | lock | |
* 1s | lock | |
* 2s | | lock |
* 3s | unlock | |
* 4s | unlock | |
* 5s | | unlock |
*/
void *t0(void* null) {
MUTEX_LOCK(&mutex) {
printf("T0: Locked 0s\n");
sleep(1);
MUTEX_LOCK(&mutex) {
printf("T0: Locked 1s\n");
sleep(1);
}
printf("T0: Unlocked 3s\n");
sleep(1);
}
printf("T0: Unlocked 4s\n");
sleep(1);
return NULL;
}
void *t1(void *null) {
MUTEX_LOCK(&mutex) {
printf("T1: Locked 2s\n");
sleep(1);
}
printf("T1: Unlocked 5s\n");
sleep(1);
return NULL;
}
int main() {
pthread_t t;
mutex_init(&mutex);
pthread_create(&t,NULL,t1,NULL);
t0(NULL);
pthread_join(t,NULL);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment