59 lines
1.5 KiB
C
59 lines
1.5 KiB
C
#include <assert.h>
|
|
#include "ucore/ticket_lock.h"
|
|
|
|
//pthread implementation of http://en.wikipedia.org/wiki/Ticket_lock
|
|
//The underlying phtread mutex is not held while the lock is acquired.
|
|
//This will allow other threads to enqueue itself.
|
|
//
|
|
//The condition variable is needed to wake up threads waiting to acquire
|
|
//the lock instead of letting the system block on the pthread mutex while waiting.
|
|
|
|
int uc_ticket_lock_init(struct UCTicketLock *lock)
|
|
{
|
|
return uc_ticket_lock_init_ex(lock, NULL, NULL);
|
|
}
|
|
|
|
int uc_ticket_lock_init_ex(struct UCTicketLock *lock,
|
|
pthread_mutexattr_t *mattr,
|
|
pthread_condattr_t *cattr)
|
|
{
|
|
int rc;
|
|
lock->queue_head = 0;
|
|
lock->queue_tail = 0;
|
|
|
|
rc = pthread_mutex_init(&lock->mutex, mattr);
|
|
assert(rc == 0);
|
|
if (rc != 0) {
|
|
return rc;
|
|
}
|
|
|
|
rc = pthread_cond_init(&lock->cond, cattr);
|
|
if (rc != 0) {
|
|
pthread_mutex_destroy(&lock->mutex);
|
|
}
|
|
assert(rc == 0);
|
|
|
|
return rc;
|
|
}
|
|
|
|
void uc_ticket_lock(struct UCTicketLock *lock)
|
|
{
|
|
unsigned long queue_me;
|
|
|
|
pthread_mutex_lock(&lock->mutex);
|
|
queue_me = lock->queue_tail++;
|
|
while (queue_me != lock->queue_head)
|
|
{
|
|
pthread_cond_wait(&lock->cond, &lock->mutex);
|
|
}
|
|
pthread_mutex_unlock(&lock->mutex);
|
|
}
|
|
|
|
void uc_ticket_unlock(struct UCTicketLock *lock)
|
|
{
|
|
pthread_mutex_lock(&lock->mutex);
|
|
lock->queue_head++;
|
|
pthread_cond_broadcast(&lock->cond);
|
|
pthread_mutex_unlock(&lock->mutex);
|
|
}
|