Skip to content

Commit

Permalink
Implement rwlock
Browse files Browse the repository at this point in the history
  • Loading branch information
ljanyst committed Mar 9, 2016
1 parent b8b6614 commit e489e26
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_library(
tb-mutexes.c
tb-cancel.c
tb-sched.c
tb-rwlock.c
tb-clone.S
tb-signal-trampoline.S)

Expand Down
136 changes: 136 additions & 0 deletions tb-rwlock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
//------------------------------------------------------------------------------
// Copyright (c) 2016 by Lukasz Janyst <lukasz@jany.st>
//------------------------------------------------------------------------------
// This file is part of thread-bites.
//
// thread-bites is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// thread-bites is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with thread-bites. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#include "tb.h"
#include "tb-private.h"

#include <limits.h>
#include <linux/futex.h>

//------------------------------------------------------------------------------
// Lock for reading
//------------------------------------------------------------------------------
int tbthread_rwlock_rdlock(tbthread_rwlock_t *rwlock)
{
while(1) {
tb_futex_lock(&rwlock->lock);

if(!rwlock->writer && !rwlock->writers_queued) {
++rwlock->readers;
tb_futex_unlock(&rwlock->lock);
return 0;
}
int sleep_status = rwlock->rd_futex;

tb_futex_unlock(&rwlock->lock);

SYSCALL3(__NR_futex, &rwlock->rd_futex, FUTEX_WAIT, sleep_status);
}
}

//------------------------------------------------------------------------------
// Lock for writing
//------------------------------------------------------------------------------
int tbthread_rwlock_wrlock(tbthread_rwlock_t *rwlock)
{
int queued = 0;
while(1) {
tb_futex_lock(&rwlock->lock);

if(!queued) {
queued = 1;
++rwlock->writers_queued;
}

if(!rwlock->writer && !rwlock->readers) {
rwlock->writer = tbthread_self();
--rwlock->writers_queued;
tb_futex_unlock(&rwlock->lock);
return 0;
}
int sleep_status = rwlock->wr_futex;

tb_futex_unlock(&rwlock->lock);

SYSCALL3(__NR_futex, &rwlock->wr_futex, FUTEX_WAIT, sleep_status);
}
}

//------------------------------------------------------------------------------
// Unlock
//------------------------------------------------------------------------------
int tbthread_rwlock_unlock(tbthread_rwlock_t *rwlock)
{
tb_futex_lock(&rwlock->lock);
if(rwlock->writer) {
rwlock->writer = 0;
if(rwlock->writers_queued) {
__sync_fetch_and_add(&rwlock->wr_futex, 1);
SYSCALL3(__NR_futex, &rwlock->wr_futex, FUTEX_WAKE, 1);
} else {
__sync_fetch_and_add(&rwlock->rd_futex, 1);
SYSCALL3(__NR_futex, &rwlock->rd_futex, FUTEX_WAKE, INT_MAX);
}
goto exit;
}

--rwlock->readers;
if(!rwlock->readers && rwlock->writers_queued) {
__sync_fetch_and_add(&rwlock->wr_futex, 1);
SYSCALL3(__NR_futex, &rwlock->wr_futex, FUTEX_WAKE, 1);
}

exit:
tb_futex_unlock(&rwlock->lock);
return 0;
}

//------------------------------------------------------------------------------
// Try to lock for reading
//------------------------------------------------------------------------------
int tbthread_rwlock_tryrdlock(tbthread_rwlock_t *rwlock)
{
tb_futex_lock(&rwlock->lock);
int status = -EBUSY;
if(!rwlock->writer && !rwlock->writers_queued) {
++rwlock->readers;
status = 0;
goto exit;
}
exit:
tb_futex_unlock(&rwlock->lock);
return status;
}

//------------------------------------------------------------------------------
// Try to lock for writing
//------------------------------------------------------------------------------
int tbthread_rwlock_trywrlock(tbthread_rwlock_t *rwlock)
{
tb_futex_lock(&rwlock->lock);
int status = -EBUSY;
if(!rwlock->writer && !rwlock->readers) {
rwlock->writer = tbthread_self();
status = 0;
goto exit;
}
exit:
tb_futex_unlock(&rwlock->lock);
return status;
}
27 changes: 27 additions & 0 deletions tb.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,20 @@ typedef int tbthread_once_t;

#define TBTHREAD_ONCE_INIT 0

//------------------------------------------------------------------------------
// RW lock
//------------------------------------------------------------------------------
typedef struct {
int lock;
int writers_queued;
int rd_futex;
int wr_futex;
tbthread_t writer;
int readers;
} tbthread_rwlock_t;

#define TBTHREAD_RWLOCK_INIT {0, 0, 0, 0, 0, 0}

//------------------------------------------------------------------------------
// General threading
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -197,6 +211,19 @@ int tbthread_mutex_getprioceiling(const tbthread_mutex_t *mutex, int *ceiling);
int tbthread_mutex_setprioceiling(tbthread_mutex_t *mutex, int ceiling,
int *old_ceiling);

//------------------------------------------------------------------------------
// RW Lock
//-----------------------------------------------------------------------------
int tbthread_rwlock_init(tbthread_rwlock_t *rwlock);
int tbthread_rwlock_destroy(tbthread_rwlock_t *rwlock);

int tbthread_rwlock_rdlock(tbthread_rwlock_t *rwlock);
int tbthread_rwlock_wrlock(tbthread_rwlock_t *rwlock);
int tbthread_rwlock_unlock(tbthread_rwlock_t *rwlock);

int tbthread_rwlock_tryrdlock(tbthread_rwlock_t *rwlock);
int tbthread_rwlock_trywrlock(tbthread_rwlock_t *rwlock);

//------------------------------------------------------------------------------
// Utility functions
//------------------------------------------------------------------------------
Expand Down

0 comments on commit e489e26

Please sign in to comment.