pthread rwlock bugfixes

This commit is contained in:
Mark Schulte 2017-04-07 15:45:24 -06:00 committed by Gregory Nutt
parent b631dc886f
commit 2b1ca79b4b
4 changed files with 28 additions and 11 deletions

View File

@ -343,6 +343,7 @@ struct pthread_rwlock_s
pthread_cond_t cv; pthread_cond_t cv;
unsigned int num_readers; unsigned int num_readers;
unsigned int num_writers; unsigned int num_writers;
bool write_in_progress;
}; };
typedef struct pthread_rwlock_s pthread_rwlock_t; typedef struct pthread_rwlock_s pthread_rwlock_t;

View File

@ -60,8 +60,9 @@ int pthread_rwlock_init(FAR pthread_rwlock_t *lock,
return -ENOSYS; return -ENOSYS;
} }
lock->num_readers = 0; lock->num_readers = 0;
lock->num_writers = 0; lock->num_writers = 0;
lock->write_in_progress = false;
err = pthread_cond_init(&lock->cv, NULL); err = pthread_cond_init(&lock->cv, NULL);
if (err != 0) if (err != 0)
@ -111,9 +112,9 @@ int pthread_rwlock_unlock(FAR pthread_rwlock_t *rw_lock)
err = pthread_cond_broadcast(&rw_lock->cv); err = pthread_cond_broadcast(&rw_lock->cv);
} }
} }
else if (rw_lock->num_writers > 0) else if (rw_lock->write_in_progress)
{ {
rw_lock->num_writers--; rw_lock->write_in_progress = false;
err = pthread_cond_broadcast(&rw_lock->cv); err = pthread_cond_broadcast(&rw_lock->cv);
} }

View File

@ -54,7 +54,7 @@ static int tryrdlock(FAR pthread_rwlock_t *rw_lock)
{ {
int err; int err;
if (rw_lock->num_writers > 0) if (rw_lock->num_writers > 0 || rw_lock->write_in_progress)
{ {
err = EBUSY; err = EBUSY;
} }

View File

@ -75,13 +75,13 @@ int pthread_rwlock_trywrlock(FAR pthread_rwlock_t *rw_lock)
return err; return err;
} }
if (rw_lock->num_readers > 0 || rw_lock->num_writers > 0) if (rw_lock->num_readers > 0 || rw_lock->write_in_progress)
{ {
err = EBUSY; err = EBUSY;
} }
else else
{ {
rw_lock->num_writers++; rw_lock->write_in_progress = true;
} }
pthread_mutex_unlock(&rw_lock->lock); pthread_mutex_unlock(&rw_lock->lock);
@ -92,20 +92,21 @@ int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock,
FAR const struct timespec *ts) FAR const struct timespec *ts)
{ {
int err = pthread_mutex_lock(&rw_lock->lock); int err = pthread_mutex_lock(&rw_lock->lock);
int num_writers_current;
if (err != 0) if (err != 0)
{ {
return err; return err;
} }
num_writers_current = rw_lock->num_writers++; if (rw_lock->num_writers == UINT_MAX)
if (num_writers_current == 0)
{ {
err = EAGAIN;
goto exit_with_mutex; goto exit_with_mutex;
} }
while (rw_lock->num_writers != num_writers_current) rw_lock->num_writers++;
while (rw_lock->write_in_progress || rw_lock->num_readers > 0)
{ {
if (ts != NULL) if (ts != NULL)
{ {
@ -122,6 +123,20 @@ int pthread_rwlock_timedwrlock(FAR pthread_rwlock_t *rw_lock,
} }
} }
if (err == 0)
{
rw_lock->write_in_progress = true;
}
else
{
/* In case of error, notify any blocked readers. */
(void) pthread_cond_broadcast(&rw_lock->cv);
}
rw_lock->num_writers--;
exit_with_mutex: exit_with_mutex:
pthread_mutex_unlock(&rw_lock->lock); pthread_mutex_unlock(&rw_lock->lock);
return err; return err;