Created
April 13, 2015 19:35
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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