aboutsummaryrefslogtreecommitdiff
path: root/linuxthreads/rwlock.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-06-26 08:01:33 +0000
committerUlrich Drepper <drepper@redhat.com>2000-06-26 08:01:33 +0000
commitc49ebf7645b828a4a82b69791dc23e19b7264e21 (patch)
tree235fa4a4995064709979e7b7b4faec8568efd928 /linuxthreads/rwlock.c
parentd82e4c7bb231c9e0f835bd46467563ac3b56cebe (diff)
downloadglibc-c49ebf7645b828a4a82b69791dc23e19b7264e21.zip
glibc-c49ebf7645b828a4a82b69791dc23e19b7264e21.tar.gz
glibc-c49ebf7645b828a4a82b69791dc23e19b7264e21.tar.bz2
Update.
2000-06-26 Ulrich Drepper <drepper@redhat.com> * Makefile (tests): Add ex11. Add rules to build it. * Examples/ex11.c: New file. * rwlock.c: Fix complete braindamaged previous try to implement timedout functions. * spinlock.c: Pretty print.
Diffstat (limited to 'linuxthreads/rwlock.c')
-rw-r--r--linuxthreads/rwlock.c136
1 files changed, 108 insertions, 28 deletions
diff --git a/linuxthreads/rwlock.c b/linuxthreads/rwlock.c
index 6ee5b62..2bcdf97 100644
--- a/linuxthreads/rwlock.c
+++ b/linuxthreads/rwlock.c
@@ -27,6 +27,35 @@
#include "spinlock.h"
#include "restart.h"
+/* Function called by pthread_cancel to remove the thread from
+ waiting inside pthread_rwlock_timedrdlock or pthread_rwlock_timedwrlock. */
+
+static int rwlock_rd_extricate_func(void *obj, pthread_descr th)
+{
+ volatile pthread_descr self = thread_self();
+ pthread_rwlock_t *rwlock = obj;
+ int did_remove = 0;
+
+ __pthread_lock((struct _pthread_fastlock *) &rwlock->__rw_lock, self);
+ did_remove = remove_from_queue(&rwlock->__rw_read_waiting, th);
+ __pthread_unlock((struct _pthread_fastlock *) &rwlock->__rw_lock);
+
+ return did_remove;
+}
+
+static int rwlock_wr_extricate_func(void *obj, pthread_descr th)
+{
+ volatile pthread_descr self = thread_self();
+ pthread_rwlock_t *rwlock = obj;
+ int did_remove = 0;
+
+ __pthread_lock((struct _pthread_fastlock *) &rwlock->__rw_lock, self);
+ did_remove = remove_from_queue(&rwlock->__rw_write_waiting, th);
+ __pthread_unlock((struct _pthread_fastlock *) &rwlock->__rw_lock);
+
+ return did_remove;
+}
+
/*
* Check whether the calling thread already owns one or more read locks on the
* specified lock. If so, return a pointer to the read lock info structure
@@ -214,10 +243,10 @@ __pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
int readers;
_pthread_descr writer;
- __pthread_alt_lock (&rwlock->__rw_lock, NULL);
+ __pthread_lock (&rwlock->__rw_lock, NULL);
readers = rwlock->__rw_readers;
writer = rwlock->__rw_writer;
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
if (readers > 0 || writer != NULL)
return EBUSY;
@@ -241,18 +270,18 @@ __pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
for (;;)
{
- __pthread_alt_lock (&rwlock->__rw_lock, self);
+ __pthread_lock (&rwlock->__rw_lock, self);
if (rwlock_can_rdlock(rwlock, have_lock_already))
break;
enqueue (&rwlock->__rw_read_waiting, self);
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
suspend (self); /* This is not a cancellation point */
}
++rwlock->__rw_readers;
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
if (have_lock_already || out_of_mem)
{
@@ -273,6 +302,7 @@ __pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
pthread_descr self = NULL;
pthread_readlock_info *existing;
int out_of_mem, have_lock_already;
+ pthread_extricate_if extr;
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
return EINVAL;
@@ -283,21 +313,46 @@ __pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock,
if (self == NULL)
self = thread_self ();
+ /* Set up extrication interface */
+ extr.pu_object = rwlock;
+ extr.pu_extricate_func = rwlock_rd_extricate_func;
+
+ /* Register extrication interface */
+ __pthread_set_own_extricate_if (self, &extr);
+
for (;;)
{
- if (__pthread_alt_timedlock (&rwlock->__rw_lock, self, abstime) == 0)
- return ETIMEDOUT;
+ __pthread_lock (&rwlock->__rw_lock, self);
if (rwlock_can_rdlock(rwlock, have_lock_already))
break;
enqueue (&rwlock->__rw_read_waiting, self);
- __pthread_alt_unlock (&rwlock->__rw_lock);
- suspend (self); /* This is not a cancellation point */
+ __pthread_unlock (&rwlock->__rw_lock);
+ /* This is not a cancellation point */
+ if (timedsuspend (self, abstime) == 0)
+ {
+ int was_on_queue;
+
+ __pthread_lock (&rwlock->__rw_lock, self);
+ was_on_queue = remove_from_queue (&rwlock->__rw_read_waiting, self);
+ __pthread_unlock (&rwlock->__rw_lock);
+
+ if (was_on_queue)
+ {
+ __pthread_set_own_extricate_if (self, 0);
+ return ETIMEDOUT;
+ }
+
+ /* Eat the outstanding restart() from the signaller */
+ suspend (self);
+ }
}
+ __pthread_set_own_extricate_if (self, 0);
+
++rwlock->__rw_readers;
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
if (have_lock_already || out_of_mem)
{
@@ -322,7 +377,7 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
have_lock_already = rwlock_have_already(&self, rwlock,
&existing, &out_of_mem);
- __pthread_alt_lock (&rwlock->__rw_lock, self);
+ __pthread_lock (&rwlock->__rw_lock, self);
/* 0 is passed to here instead of have_lock_already.
This is to meet Single Unix Spec requirements:
@@ -336,7 +391,7 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
retval = 0;
}
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
if (retval == 0)
{
@@ -361,17 +416,17 @@ __pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
while(1)
{
- __pthread_alt_lock (&rwlock->__rw_lock, self);
+ __pthread_lock (&rwlock->__rw_lock, self);
if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
{
rwlock->__rw_writer = self;
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
return 0;
}
/* Suspend ourselves, then try again */
enqueue (&rwlock->__rw_write_waiting, self);
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
suspend (self); /* This is not a cancellation point */
}
}
@@ -383,28 +438,53 @@ __pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock,
const struct timespec *abstime)
{
pthread_descr self;
+ pthread_extricate_if extr;
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
return EINVAL;
self = thread_self ();
+ /* Set up extrication interface */
+ extr.pu_object = rwlock;
+ extr.pu_extricate_func = rwlock_wr_extricate_func;
+
+ /* Register extrication interface */
+ __pthread_set_own_extricate_if (self, &extr);
+
while(1)
{
- if (__pthread_alt_timedlock (&rwlock->__rw_lock, self, abstime) == 0)
- return ETIMEDOUT;
+ __pthread_lock (&rwlock->__rw_lock, self);
if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
{
rwlock->__rw_writer = self;
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_set_own_extricate_if (self, 0);
+ __pthread_unlock (&rwlock->__rw_lock);
return 0;
}
/* Suspend ourselves, then try again */
enqueue (&rwlock->__rw_write_waiting, self);
- __pthread_alt_unlock (&rwlock->__rw_lock);
- suspend (self); /* This is not a cancellation point */
+ __pthread_unlock (&rwlock->__rw_lock);
+ /* This is not a cancellation point */
+ if (timedsuspend (self, abstime) == 0)
+ {
+ int was_on_queue;
+
+ __pthread_lock (&rwlock->__rw_lock, self);
+ was_on_queue = remove_from_queue (&rwlock->__rw_write_waiting, self);
+ __pthread_unlock (&rwlock->__rw_lock);
+
+ if (was_on_queue)
+ {
+ __pthread_set_own_extricate_if (self, 0);
+ return ETIMEDOUT;
+ }
+
+ /* Eat the outstanding restart() from the signaller */
+ suspend (self);
+ }
}
}
strong_alias (__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock)
@@ -415,13 +495,13 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
{
int result = EBUSY;
- __pthread_alt_lock (&rwlock->__rw_lock, NULL);
+ __pthread_lock (&rwlock->__rw_lock, NULL);
if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL)
{
rwlock->__rw_writer = thread_self ();
result = 0;
}
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
return result;
}
@@ -434,13 +514,13 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
pthread_descr torestart;
pthread_descr th;
- __pthread_alt_lock (&rwlock->__rw_lock, NULL);
+ __pthread_lock (&rwlock->__rw_lock, NULL);
if (rwlock->__rw_writer != NULL)
{
/* Unlocking a write lock. */
if (rwlock->__rw_writer != thread_self ())
{
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
return EPERM;
}
rwlock->__rw_writer = NULL;
@@ -452,14 +532,14 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
/* Restart all waiting readers. */
torestart = rwlock->__rw_read_waiting;
rwlock->__rw_read_waiting = NULL;
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
while ((th = dequeue (&torestart)) != NULL)
restart (th);
}
else
{
/* Restart one waiting writer. */
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
restart (th);
}
}
@@ -468,7 +548,7 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
/* Unlocking a read lock. */
if (rwlock->__rw_readers == 0)
{
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
return EPERM;
}
@@ -479,7 +559,7 @@ __pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
else
th = NULL;
- __pthread_alt_unlock (&rwlock->__rw_lock);
+ __pthread_unlock (&rwlock->__rw_lock);
if (th != NULL)
restart (th);