Răsfoiți Sursa

Add sem_try_acquire(). Fixes #846 (#856)

Co-authored-by: Geoff Simmons <geoff@uplex.de>
Graham Sanderson 3 ani în urmă
părinte
comite
672e48e9e9

+ 11 - 0
src/common/pico_sync/include/pico/sem.h

@@ -122,6 +122,17 @@ bool sem_acquire_timeout_us(semaphore_t *sem, uint32_t timeout_us);
  */
 bool sem_acquire_block_until(semaphore_t *sem, absolute_time_t until);
 
+/*! \brief Attempt to acquire a permit from a semaphore without blocking
+ *  \ingroup sem
+ *
+ * This function will return false without blocking if no permits are
+ * available, otherwise it will acquire a permit and return true.
+ *
+ * \param sem Pointer to semaphore structure
+ * \return true if permit was acquired.
+ */
+bool sem_try_acquire(semaphore_t *sem);
+
 #ifdef __cplusplus
 }
 #endif

+ 11 - 0
src/common/pico_sync/sem.c

@@ -52,6 +52,17 @@ bool __time_critical_func(sem_acquire_block_until)(semaphore_t *sem, absolute_ti
     } while (true);
 }
 
+bool __time_critical_func(sem_try_acquire)(semaphore_t *sem) {
+    uint32_t save = spin_lock_blocking(sem->core.spin_lock);
+    if (sem->permits > 0) {
+        sem->permits--;
+        lock_internal_spin_unlock_with_notify(&sem->core, save);
+        return true;
+    }
+    spin_unlock(sem->core.spin_lock, save);
+    return false;
+}
+
 // todo this should really have a blocking variant for when permits are maxed out
 bool __time_critical_func(sem_release)(semaphore_t *sem) {
     uint32_t save = spin_lock_blocking(sem->core.spin_lock);

+ 2 - 1
test/CMakeLists.txt

@@ -9,4 +9,5 @@ if (PICO_ON_DEVICE)
     add_subdirectory(hardware_irq_test)
     add_subdirectory(hardware_pwm_test)
     add_subdirectory(cmsis_test)
-endif()
+    add_subdirectory(pico_sem_test)
+endif()

+ 4 - 0
test/pico_sem_test/CMakeLists.txt

@@ -0,0 +1,4 @@
+add_executable(pico_sem_test pico_sem_test.c)
+
+target_link_libraries(pico_sem_test PRIVATE pico_test pico_sync)
+pico_add_extra_outputs(pico_sem_test)

+ 29 - 0
test/pico_sem_test/pico_sem_test.c

@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+
+#include "pico/sem.h"
+#include "pico/test.h"
+#include "pico/stdio.h"
+
+PICOTEST_MODULE_NAME("SEM", "semaphore test");
+
+int main() {
+    semaphore_t sem;
+
+    stdio_init_all();
+    sem_init(&sem, 1, 1);
+
+    PICOTEST_START();
+
+    PICOTEST_START_SECTION("sem_try_acquire");
+        PICOTEST_CHECK(sem_try_acquire(&sem), "available permit not acquired");
+        PICOTEST_CHECK(!sem_try_acquire(&sem), "success with no permits");
+    PICOTEST_END_SECTION();
+
+    PICOTEST_END_TEST();
+}