On 01/15/2014 10:56:25 AM, Justus Winter wrote:
> I tested a simple userspace mutex based on this and multiple
futexes,
> all tests passed.
Could you put that somewhere? I still have so little "context", I'd
like to see how futexe are used in a mutex implementation.
Here's what I used:
#include "gnumach.h"
#include <mach_init.h>
#include <pthread.h>
#include <stdio.h>
struct simple_mutex {
#define SMUTEX_UNLOCKED 0
#define SMUTEX_NO_WAITERS 1
#define SMUTEX_WAITERS 2
int value;
};
void simple_mutex_init(struct simple_mutex *smutex)
{
smutex->value = SMUTEX_UNLOCKED;
}
void simple_mutex_lock(struct simple_mutex *smutex)
{
int c;
if ((c = __sync_val_compare_and_swap(&smutex->value,
SMUTEX_UNLOCKED, SMUTEX_NO_WAITERS)) != SMUTEX_UNLOCKED) {
if (c != SMUTEX_WAITERS)
c = __sync_lock_test_and_set(&smutex->value,
SMUTEX_WAITERS);
while (c != SMUTEX_UNLOCKED) {
futex_wait(mach_task_self(),
(vm_offset_t)&smutex->value, SMUTEX_WAITERS, 0, 1);
c = __sync_lock_test_and_set(&smutex->value,
SMUTEX_WAITERS);
}
}
}
void simple_mutex_unlock(struct simple_mutex *smutex)
{
if (__sync_lock_test_and_set(&smutex->value, smutex->value - 1)
!= SMUTEX_NO_WAITERS) {
smutex->value = SMUTEX_UNLOCKED;
futex_wake(mach_task_self(),
(vm_offset_t)&smutex->value, 0, 1);
}
}
int e = 0;
struct simple_mutex mutex;
void *thread_f(void *arg)
{
printf("Tread 2 locking the mutex.\n");
simple_mutex_lock(&mutex);
printf("Thread 2 in critical section.\n");
printf("Thread 2 about to sleep.\n");
futex_wait(mach_task_self(), (vm_offset_t)&e, e, 1000, 1);
printf("Thread 2 waking up.\n");
simple_mutex_unlock(&mutex);
printf("Thread 2 unlocked the mutex.\n");
return NULL;
}
int main()
{
simple_mutex_init(&mutex);
pthread_t new_thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&new_thread, &attr, thread_f, NULL);
futex_wait(mach_task_self(), (vm_offset_t)&e, e, 1000, 1);
printf("Thread 1 trying to lock the mutex.\n");
simple_mutex_lock(&mutex);
printf("Thread 1 in critical section.\n");
simple_mutex_unlock(&mutex);
printf("Thread 1 unlocked the mutex.\n");
return 0;
}