@@ -31,13 +31,8 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131 * @author{Abhi Gundrala <gundralaa@berkeley.edu>}
3232 */
3333
34- #if !defined(LF_SINGLE_THREADED )
35- #error "Only the single-threaded runtime has support for RP2040"
36- #endif
37-
3834#include "platform/lf_rp2040_support.h"
3935#include "low_level_platform.h"
40- #include "utils/util.h"
4136#include "tag.h"
4237
4338#include <pico/stdlib.h>
@@ -67,6 +62,8 @@ static uint32_t _lf_num_nested_crit_sec = 0;
6762 */
6863void _lf_initialize_clock (void ) {
6964 // init stdio lib
65+ // may fail, but failure may be ok/expected if printing is not needed
66+ // (i.e. if neither USB nor UART are enabled)
7067 stdio_init_all ();
7168 // init sync structs
7269 critical_section_init (& _lf_crit_sec );
@@ -161,7 +158,7 @@ int lf_disable_interrupts_nested() {
161158 return 1 ;
162159 }
163160 // check crit sec count
164- // enter non-rentrant state by disabling interrupts
161+ // enter non-reentrant state by disabling interrupts
165162 // lock second core execution
166163 if (_lf_num_nested_crit_sec == 0 ) {
167164 // block if associated spin lock in use
@@ -202,9 +199,120 @@ int lf_enable_interrupts_nested() {
202199 */
203200int _lf_single_threaded_notify_of_event () {
204201 // notify main sleep loop of event
205- sem_release (& _lf_sem_irq_event );
202+ if (sem_release (& _lf_sem_irq_event )) {
203+ return 0 ;
204+ }
205+ return 1 ;
206+ }
207+
208+ #else // LF_SINGLE_THREADED
209+
210+ #warning "Threaded runtime on RP2040 is still experimental"
211+
212+ /**
213+ * @brief Get the number of cores on the host machine.
214+ */
215+ int lf_available_cores () { return 2 ; }
216+
217+ static void * (* thread_1 )(void * );
218+ static void * thread_1_args ;
219+ static int num_create_threads_called = 0 ;
220+ static semaphore_t thread_1_done ;
221+ static void * thread_1_return ;
222+
223+ #define MAGIC_THREAD1_ID 314159
224+
225+ void core1_entry () {
226+ thread_1_return = thread_1 (thread_1_args );
227+ sem_reset (& thread_1_done , 1 );
228+ }
229+
230+ int lf_thread_create (lf_thread_t * thread , void * (* lf_thread )(void * ), void * arguments ) {
231+ // make sure this fn is only called once
232+ if (num_create_threads_called != 0 ) {
233+ return 1 ;
234+ }
235+ thread_1 = lf_thread ;
236+ thread_1_args = arguments ;
237+ num_create_threads_called += 1 ;
238+ sem_init (& thread_1_done , 0 , 1 );
239+ multicore_launch_core1 (core1_entry );
240+ * thread = MAGIC_THREAD1_ID ;
241+ return 0 ;
242+ }
243+
244+ int lf_thread_join (lf_thread_t thread , void * * thread_return ) {
245+ if (thread != MAGIC_THREAD1_ID ) {
246+ return 1 ;
247+ }
248+ sem_acquire_blocking (& thread_1_done );
249+ // release in case join is called again
250+ if (!sem_release (& thread_1_done )) {
251+ // shouldn't be possible; lf_thread_join is only called from main thread
252+ return 1 ;
253+ }
254+ if (thread_return ) {
255+ * thread_return = thread_1_return ;
256+ }
257+ return 0 ;
258+ }
259+
260+ int lf_mutex_init (lf_mutex_t * mutex ) {
261+ recursive_mutex_init (mutex );
262+ return 0 ;
263+ }
264+
265+ int lf_mutex_lock (lf_mutex_t * mutex ) {
266+ recursive_mutex_enter_blocking (mutex );
267+ return 0 ;
268+ }
269+
270+ int lf_mutex_unlock (lf_mutex_t * mutex ) {
271+ recursive_mutex_exit (mutex );
206272 return 0 ;
207273}
208- #endif // LF_SINGLE_THREADED
274+
275+ // condition variables "notify" threads using a semaphore per core.
276+ // although there are only two cores, may not use just a single semaphore
277+ // as a cond_broadcast may be called from within an interrupt
278+ int lf_cond_init (lf_cond_t * cond , lf_mutex_t * mutex ) {
279+ for (int i = 0 ; i < NUM_CORES ; i ++ ) {
280+ sem_init (& (cond -> notifs [i ]), 0 , 1 );
281+ }
282+ cond -> mutex = mutex ;
283+ return 0 ;
284+ }
285+
286+ int lf_cond_broadcast (lf_cond_t * cond ) {
287+ for (int i = 0 ; i < NUM_CORES ; i ++ ) {
288+ sem_reset (& (cond -> notifs [i ]), 1 );
289+ }
290+ return 0 ;
291+ }
292+
293+ int lf_cond_signal (lf_cond_t * cond ) {
294+ return lf_cond_broadcast (cond ); // spurious wakeups, but that's ok
295+ }
296+
297+ int lf_cond_wait (lf_cond_t * cond ) {
298+ semaphore_t * mailbox = & (cond -> notifs [get_core_num ()]);
299+ lf_mutex_unlock (cond -> mutex );
300+ sem_acquire_blocking (mailbox );
301+ lf_mutex_lock (cond -> mutex );
302+ return 0 ;
303+ }
304+
305+ int _lf_cond_timedwait (lf_cond_t * cond , instant_t absolute_time_ns ) {
306+ semaphore_t * mailbox = & (cond -> notifs [get_core_num ()]);
307+ absolute_time_t a = from_us_since_boot (absolute_time_ns / 1000 );
308+ bool acquired_permit = sem_acquire_block_until (mailbox , a );
309+ return acquired_permit ? 0 : LF_TIMEOUT ;
310+ }
311+
312+ void initialize_lf_thread_id () {}
313+
314+ int lf_thread_id () { return get_core_num (); }
315+
316+ #endif // !LF_SINGLE_THREADED
209317
210318#endif // PLATFORM_RP2040
0 commit comments