Skip to content

Instantly share code, notes, and snippets.

@astarasikov
Created October 23, 2015 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save astarasikov/fd75fa7e706cb6337e60 to your computer and use it in GitHub Desktop.
Save astarasikov/fd75fa7e706cb6337e60 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
#if 0
#define YO do { printf("%s:%d\n", __func__, __LINE__); } while (0)
#else
#define YO do {} while (0)
#endif
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
static void die(char *message)
{
fputs(message, stderr);
fflush(stderr);
exit(-1);
}
static uint64_t NativeGetThreadId() {
return (uint64_t)pthread_self();
}
typedef struct ThreadData {
int ShouldRecurse;
} ThreadData;
typedef struct RecursiveMutex {
uint64_t OwnerThreadId;
uint64_t LockCount;
} RecursiveMutex;
static RecursiveMutex GlobalRecursiveMutex = {};
static void RecursiveMutexLock(RecursiveMutex *mutex)
{
uint64_t tid = NativeGetThreadId();
uint64_t oldTid = 0;
YO;
do {
YO;
oldTid = __sync_val_compare_and_swap(&mutex->OwnerThreadId,
0, tid);
usleep(0);
} while ((oldTid != 0) && (oldTid != tid));
YO;
/* all your mutexes are belong to us */
__sync_fetch_and_add(&mutex->LockCount, 1);
}
static void RecursiveMutexUnlock(RecursiveMutex *mutex)
{
uint64_t oldCount = __sync_fetch_and_add(&mutex->LockCount, -1);
YO;
if (oldCount > 1) {
YO;
return;
}
uint64_t tid = NativeGetThreadId();
while (!__sync_bool_compare_and_swap(
&mutex->OwnerThreadId,
tid,
0)) { YO; }
}
static void *ThreadRoutine(void *arg)
{
if (!arg) {
die("arg is NULL\n");
}
ThreadData *data = (ThreadData*)arg;
while (1) {
printf("Thread %llu: Before Lock\n", NativeGetThreadId());
RecursiveMutexLock(&GlobalRecursiveMutex);
printf("Thread %llu: In Lock\n", NativeGetThreadId());
//usleep(rand() % 10000);
if (data->ShouldRecurse) {
RecursiveMutexLock(&GlobalRecursiveMutex);
printf("Thread %llu: In Lock 2\n", NativeGetThreadId());
RecursiveMutexUnlock(&GlobalRecursiveMutex);
}
RecursiveMutexUnlock(&GlobalRecursiveMutex);
usleep(rand() % 100000);
}
return 0;
}
int main() {
static ThreadData threadData[] = {
{
.ShouldRecurse = 1,
},
{
.ShouldRecurse = 1,
},
{
.ShouldRecurse = 1,
},
{
.ShouldRecurse = 1,
},
{
.ShouldRecurse = 0,
},
};
size_t i = 0;
for (i = 0; i < ARRAY_SIZE(threadData); i++) {
pthread_t t;
pthread_create(&t, 0, ThreadRoutine, (void*)&threadData[i]);
}
while (1) {
sleep(99999);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment