Skip to content

Commit 672e48e

Browse files
Add sem_try_acquire(). Fixes #846 (#856)
Co-authored-by: Geoff Simmons <geoff@uplex.de>
1 parent ef47dfe commit 672e48e

File tree

5 files changed

+57
-1
lines changed

5 files changed

+57
-1
lines changed

src/common/pico_sync/include/pico/sem.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,17 @@ bool sem_acquire_timeout_us(semaphore_t *sem, uint32_t timeout_us);
122122
*/
123123
bool sem_acquire_block_until(semaphore_t *sem, absolute_time_t until);
124124

125+
/*! \brief Attempt to acquire a permit from a semaphore without blocking
126+
* \ingroup sem
127+
*
128+
* This function will return false without blocking if no permits are
129+
* available, otherwise it will acquire a permit and return true.
130+
*
131+
* \param sem Pointer to semaphore structure
132+
* \return true if permit was acquired.
133+
*/
134+
bool sem_try_acquire(semaphore_t *sem);
135+
125136
#ifdef __cplusplus
126137
}
127138
#endif

src/common/pico_sync/sem.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ bool __time_critical_func(sem_acquire_block_until)(semaphore_t *sem, absolute_ti
5252
} while (true);
5353
}
5454

55+
bool __time_critical_func(sem_try_acquire)(semaphore_t *sem) {
56+
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
57+
if (sem->permits > 0) {
58+
sem->permits--;
59+
lock_internal_spin_unlock_with_notify(&sem->core, save);
60+
return true;
61+
}
62+
spin_unlock(sem->core.spin_lock, save);
63+
return false;
64+
}
65+
5566
// todo this should really have a blocking variant for when permits are maxed out
5667
bool __time_critical_func(sem_release)(semaphore_t *sem) {
5768
uint32_t save = spin_lock_blocking(sem->core.spin_lock);

test/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ if (PICO_ON_DEVICE)
99
add_subdirectory(hardware_irq_test)
1010
add_subdirectory(hardware_pwm_test)
1111
add_subdirectory(cmsis_test)
12-
endif()
12+
add_subdirectory(pico_sem_test)
13+
endif()

test/pico_sem_test/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
add_executable(pico_sem_test pico_sem_test.c)
2+
3+
target_link_libraries(pico_sem_test PRIVATE pico_test pico_sync)
4+
pico_add_extra_outputs(pico_sem_test)

test/pico_sem_test/pico_sem_test.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <stdio.h>
8+
9+
#include "pico/sem.h"
10+
#include "pico/test.h"
11+
#include "pico/stdio.h"
12+
13+
PICOTEST_MODULE_NAME("SEM", "semaphore test");
14+
15+
int main() {
16+
semaphore_t sem;
17+
18+
stdio_init_all();
19+
sem_init(&sem, 1, 1);
20+
21+
PICOTEST_START();
22+
23+
PICOTEST_START_SECTION("sem_try_acquire");
24+
PICOTEST_CHECK(sem_try_acquire(&sem), "available permit not acquired");
25+
PICOTEST_CHECK(!sem_try_acquire(&sem), "success with no permits");
26+
PICOTEST_END_SECTION();
27+
28+
PICOTEST_END_TEST();
29+
}

0 commit comments

Comments
 (0)