pthread: added pthread_rwlock_tryrd/wrlock()

Closes https://github.com/espressif/esp-idf/issues/9229
This commit is contained in:
Jakob Hasse 2023-04-17 14:45:26 +08:00
parent 6acd082cc8
commit e7312cccea
3 changed files with 157 additions and 9 deletions

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -191,6 +191,34 @@ int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
return 0; return 0;
} }
int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
{
esp_pthread_rwlock_t *esp_rwlock;
int res;
res = checkrw_lock(rwlock);
if (res != 0) {
return res;
}
esp_rwlock = (esp_pthread_rwlock_t *)*rwlock;
res = pthread_mutex_trylock(&esp_rwlock->resource_mutex);
if (res != 0) {
return res;
}
if (esp_rwlock->active_writers == 0) {
esp_rwlock->active_readers++;
res = 0;
} else {
res = EBUSY;
}
pthread_mutex_unlock(&esp_rwlock->resource_mutex);
return res;
}
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
{ {
esp_pthread_rwlock_t *esp_rwlock; esp_pthread_rwlock_t *esp_rwlock;
@ -219,6 +247,35 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
return 0; return 0;
} }
int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) {
esp_pthread_rwlock_t *esp_rwlock;
int res;
res = checkrw_lock(rwlock);
if (res != 0) {
return res;
}
esp_rwlock = (esp_pthread_rwlock_t *)*rwlock;
res = pthread_mutex_trylock(&esp_rwlock->resource_mutex);
if (res != 0) {
return res;
}
if (esp_rwlock->active_readers > 0 ||
esp_rwlock->active_writers > 0 ||
esp_rwlock->waiting_writers > 0) { // the last check for waiting_writers is to avoid skipping the queue
res = EBUSY;
} else {
esp_rwlock->active_writers++;
res = 0;
}
pthread_mutex_unlock(&esp_rwlock->resource_mutex);
return res;
}
int pthread_rwlock_unlock (pthread_rwlock_t *rwlock) int pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
{ {
esp_pthread_rwlock_t *esp_rwlock; esp_pthread_rwlock_t *esp_rwlock;

View File

@ -293,3 +293,89 @@ TEST_CASE("wrlock multiple writers wait", "[pthread][rwlock]")
TEST_ASSERT_EQUAL_INT(pthread_rwlock_destroy(&rwlock), 0); TEST_ASSERT_EQUAL_INT(pthread_rwlock_destroy(&rwlock), 0);
vQueueDelete(wait_queue); vQueueDelete(wait_queue);
} }
TEST_CASE("tryrdlock invalid param", "[pthread][rwlock]")
{
TEST_ASSERT_EQUAL_INT(pthread_rwlock_tryrdlock(NULL), EINVAL);
pthread_rwlock_t rwlock = 0;
TEST_ASSERT_EQUAL_INT(pthread_rwlock_tryrdlock(&rwlock), EINVAL);
}
TEST_CASE("tryrdlock fails on write-locked rwlock", "[pthread][rwlock]")
{
pthread_rwlock_t rwlock;
TEST_ASSERT_EQUAL_INT(pthread_rwlock_init(&rwlock, NULL), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_wrlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_tryrdlock(&rwlock), EBUSY);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_unlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_destroy(&rwlock), 0);
}
TEST_CASE("tryrdlock succeeds on read-locked rwlock", "[pthread][rwlock]")
{
pthread_rwlock_t rwlock;
TEST_ASSERT_EQUAL_INT(pthread_rwlock_init(&rwlock, NULL), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_rdlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_tryrdlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_unlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_unlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_destroy(&rwlock), 0);
}
TEST_CASE("tryrdlock lock statically initialized lock", "[pthread][rwlock]")
{
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
TEST_ASSERT_EQUAL_INT(pthread_rwlock_tryrdlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_unlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_destroy(&rwlock), 0);
}
TEST_CASE("trywrlock invalid param", "[pthread][rwlock]")
{
TEST_ASSERT_EQUAL_INT(pthread_rwlock_trywrlock(NULL), EINVAL);
pthread_rwlock_t rwlock = 0;
TEST_ASSERT_EQUAL_INT(pthread_rwlock_trywrlock(&rwlock), EINVAL);
}
TEST_CASE("trywrlock fails on write-locked rwlock", "[pthread][rwlock]")
{
pthread_rwlock_t rwlock;
TEST_ASSERT_EQUAL_INT(pthread_rwlock_init(&rwlock, NULL), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_wrlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_trywrlock(&rwlock), EBUSY);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_unlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_destroy(&rwlock), 0);
}
TEST_CASE("trywrlock fails on read-locked rwlock", "[pthread][rwlock]")
{
pthread_rwlock_t rwlock;
TEST_ASSERT_EQUAL_INT(pthread_rwlock_init(&rwlock, NULL), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_rdlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_trywrlock(&rwlock), EBUSY);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_unlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_unlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_destroy(&rwlock), 0);
}
TEST_CASE("trywrlock lock statically initialized lock", "[pthread][rwlock]")
{
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
TEST_ASSERT_EQUAL_INT(pthread_rwlock_trywrlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_unlock(&rwlock), 0);
TEST_ASSERT_EQUAL_INT(pthread_rwlock_destroy(&rwlock), 0);
}

View File

@ -123,18 +123,23 @@ In IDF, POSIX *unnamed* semaphores are implemented. The accessible API is descri
* `sem_getvalue() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html>`_ * `sem_getvalue() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html>`_
Read/Write Locks Read/Write Locks
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
The following API functions of the POSIX reader-writer locks specification are implemented:
* `pthread_rwlock_init() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_init.html>`_
* ``pthread_rwlock_init()``
- The ``attr`` argument is not implemented and is ignored. - The ``attr`` argument is not implemented and is ignored.
* ``pthread_rwlock_destroy()``
* ``pthread_rwlock_rdlock()``
* ``pthread_rwlock_wrlock()``
* ``pthread_rwlock_unlock()``
Static initializer constant ``PTHREAD_RWLOCK_INITIALIZER`` is supported. * `pthread_rwlock_destroy() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_destroy.html>`_
* `pthread_rwlock_rdlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_rdlock.html>`_
* `pthread_rwlock_tryrdlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_tryrdlock.html>`_
* `pthread_rwlock_wrlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_wrlock.html>`_
* `pthread_rwlock_trywrlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_trywrlock.html>`_
* `pthread_rwlock_unlock() <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_unlock.html>`_
.. note:: These functions can be called from tasks created using either pthread or FreeRTOS APIs The static initializer constant ``PTHREAD_RWLOCK_INITIALIZER`` is supported.
.. note:: These functions can be called from tasks created using either pthread or FreeRTOS APIs.
Thread-Specific Data Thread-Specific Data
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^