Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/common/pico_sync/include/pico/sem.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/common/pico_sync/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 4 additions & 0 deletions test/pico_sem_test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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 changes: 29 additions & 0 deletions test/pico_sem_test/pico_sem_test.c
Original file line number Diff line number Diff line change
@@ -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();
}