Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.programming.threads > #499 > unrolled thread
| Started by | Sudhanshu Shukla <sudhan345@gmail.com> |
|---|---|
| First post | 2011-08-09 14:06 -0700 |
| Last post | 2011-08-15 11:31 +0200 |
| Articles | 2 — 2 participants |
Back to article view | Back to comp.programming.threads
mutex and condition variable implementation using futex Sudhanshu Shukla <sudhan345@gmail.com> - 2011-08-09 14:06 -0700
Re: mutex and condition variable implementation using futex Alexander Terekhov <terekhov@web.de> - 2011-08-15 11:31 +0200
| From | Sudhanshu Shukla <sudhan345@gmail.com> |
|---|---|
| Date | 2011-08-09 14:06 -0700 |
| Subject | mutex and condition variable implementation using futex |
| Message-ID | <6752ab19-9142-471e-8b83-14fdc3784567@glegroupsg2000goo.googlegroups.com> |
Hi All,
I have implemented mutex and condition variables using futex syscall. I think my implementation is correct, but if some one could verify the correctness of my implementation it would be great.
Any hints for further optimizing the mutex and condition variables would be greatly appreciated.
--------------------------------------------------------------------------------
typedef UINT32 mutex;
typedef struct condvar condvar;
struct condvar {
mutex *m;
int seq;
};
void mutex_init(mutex *m) {
*m = 0;
}
void mutex_destroy(mutex *m) {
*m = 0;
};
void mutex_lock(mutex *m) {
UINT32 c;
if((c = __sync_val_compare_and_swap(m, 0, 1)) != 0) {
do {
if((c == 2) || __sync_val_compare_and_swap(m, 1, 2) != 0)
syscall(SYS_futex, m, FUTEX_WAIT_PRIVATE, 2, NULL, NULL, 0);
} while((c = __sync_val_compare_and_swap(m, 0, 2)) != 0);
}
};
void mutex_unlock(mutex *m) {
if(__sync_fetch_and_sub(m, 1) != 1) {
*m = 0;
syscall(SYS_futex, m, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
}
}
void cond_init(condvar *c, mutex *m) {
c->m = m;
c->seq = 0;
}
void cond_destroy(condvar *c) {
c->m = NULL;
c->seq = 0;
};
void cond_signal(condvar *c) {
__sync_fetch_and_add(&(c->seq), 1);
syscall(SYS_futex, &(c->seq), FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
}
void cond_broadcast(condvar *c) {
__sync_fetch_and_add(&(c->seq), 1);
syscall(SYS_futex, &(c->seq), FUTEX_REQUEUE_PRIVATE, 1, (void *) INT_MAX, c->m, 0);
}
void cond_wait(condvar *c) {
UINT32 oldSeq = c->seq;
mutex_unlock(c->m);
syscall(SYS_futex, &(c->seq), FUTEX_WAIT_PRIVATE, oldSeq, NULL, NULL, 0);
while (xchg32(c->m, 2)) {
syscall(SYS_futex, c->m, FUTEX_WAIT_PRIVATE, 2, NULL, NULL, 0);
}
}
--------------------------------------------------------------------------------
Thanks
Sudhanshu
[toc] | [next] | [standalone]
| From | Alexander Terekhov <terekhov@web.de> |
|---|---|
| Date | 2011-08-15 11:31 +0200 |
| Message-ID | <4E48E78F.5A0B6048@web.de> |
| In reply to | #499 |
Sudhanshu Shukla wrote:
[...]
> Any hints for further optimizing the mutex and condition variables
> would be greatly appreciated.
Linux's futex interface isn't really optimal for mutexes and condvars
because the kernel doesn't maintain 'waiters bit' (e.g. 0x80000000)
indicating that there are queued waiters.
With waiters bit, mutex would be simply
WHILE atomic_bit_test_set_hlb(&lock, 1) // efficient 'acquire'
lock_queue_wait(&lock, 1) // wait if locked bit is set
for lock() and
uintptr_t lock_queue;
IF atomic_decrement_rel(lock_queue = &lock)
THEN lock_queue_wake(lock_queue, 1)
for unlock.
For condvar, it is better to let the kernel set waiters bit and then
unlock the associated mutex.
The signal would be simply
IF cv_queue
THEN cv_queue_wake(&cv_queue, 1)
and broadcast
IF cv_queue
THEN cv_queue_wake(&cv_queue, UINT_MAX)
regards,
alexander.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.programming.threads
csiph-web