File tree Expand file tree Collapse file tree 5 files changed +68
-10
lines changed Expand file tree Collapse file tree 5 files changed +68
-10
lines changed Original file line number Diff line number Diff line change @@ -46,21 +46,21 @@ static uint32_t *core1_stack = NULL;
46
46
static size_t core1_stack_num_words = 0 ;
47
47
48
48
// Thread mutex.
49
- static mutex_t atomic_mutex ;
49
+ static recursive_mutex_t atomic_mutex ;
50
50
51
51
uint32_t mp_thread_begin_atomic_section (void ) {
52
52
if (core1_entry ) {
53
53
// When both cores are executing, we also need to provide
54
54
// full mutual exclusion.
55
- return mutex_enter_blocking_and_disable_interrupts (& atomic_mutex );
55
+ return recursive_mutex_enter_blocking_and_disable_interrupts (& atomic_mutex );
56
56
} else {
57
57
return save_and_disable_interrupts ();
58
58
}
59
59
}
60
60
61
61
void mp_thread_end_atomic_section (uint32_t state ) {
62
62
if (atomic_mutex .owner != LOCK_INVALID_OWNER_ID ) {
63
- mutex_exit_and_restore_interrupts (& atomic_mutex , state );
63
+ recursive_mutex_exit_and_restore_interrupts (& atomic_mutex , state );
64
64
} else {
65
65
restore_interrupts (state );
66
66
}
@@ -70,7 +70,7 @@ void mp_thread_end_atomic_section(uint32_t state) {
70
70
void mp_thread_init (void ) {
71
71
assert (get_core_num () == 0 );
72
72
73
- mutex_init (& atomic_mutex );
73
+ recursive_mutex_init (& atomic_mutex );
74
74
75
75
// Allow MICROPY_BEGIN_ATOMIC_SECTION to be invoked from core1.
76
76
multicore_lockout_victim_init ();
Original file line number Diff line number Diff line change 9
9
// These functions are taken from lib/pico-sdk/src/common/pico_sync/mutex.c and modified
10
10
// so that they atomically obtain the mutex and disable interrupts.
11
11
12
- uint32_t __time_critical_func (mutex_enter_blocking_and_disable_interrupts )( mutex_t * mtx ) {
12
+ uint32_t __time_critical_func (recursive_mutex_enter_blocking_and_disable_interrupts )( recursive_mutex_t * mtx ) {
13
13
lock_owner_id_t caller = lock_get_caller_owner_id ();
14
14
do {
15
15
uint32_t save = spin_lock_blocking (mtx -> core .spin_lock );
16
- if (!lock_is_owner_id_valid (mtx -> owner )) {
16
+ if (mtx -> owner == caller || !lock_is_owner_id_valid (mtx -> owner )) {
17
17
mtx -> owner = caller ;
18
+ uint __unused total = ++ mtx -> enter_count ;
18
19
spin_unlock_unsafe (mtx -> core .spin_lock );
20
+ assert (total ); // check for overflow
19
21
return save ;
20
22
}
21
23
lock_internal_spin_unlock_with_wait (& mtx -> core , save );
22
24
} while (true);
23
25
}
24
26
25
- void __time_critical_func (mutex_exit_and_restore_interrupts )( mutex_t * mtx , uint32_t save ) {
27
+ void __time_critical_func (recursive_mutex_exit_and_restore_interrupts )( recursive_mutex_t * mtx , uint32_t save ) {
26
28
spin_lock_unsafe_blocking (mtx -> core .spin_lock );
27
29
assert (lock_is_owner_id_valid (mtx -> owner ));
28
- mtx -> owner = LOCK_INVALID_OWNER_ID ;
30
+ assert (mtx -> enter_count );
31
+ if (!-- mtx -> enter_count ) {
32
+ mtx -> owner = LOCK_INVALID_OWNER_ID ;
33
+ }
29
34
lock_internal_spin_unlock_with_notify (& mtx -> core , save );
30
35
}
Original file line number Diff line number Diff line change 28
28
29
29
#include "pico/mutex.h"
30
30
31
- uint32_t mutex_enter_blocking_and_disable_interrupts ( mutex_t * mtx );
32
- void mutex_exit_and_restore_interrupts ( mutex_t * mtx , uint32_t save );
31
+ uint32_t recursive_mutex_enter_blocking_and_disable_interrupts ( recursive_mutex_t * mtx );
32
+ void recursive_mutex_exit_and_restore_interrupts ( recursive_mutex_t * mtx , uint32_t save );
33
33
34
34
#endif // MICROPY_INCLUDED_RP2_MUTEX_EXTRA_H
Original file line number Diff line number Diff line change
1
+ # Ensure that disabling IRQs creates mutual exclusion between threads
2
+ # (also tests nesting of disable_irq across threads)
3
+ import machine
4
+ import time
5
+ import _thread
6
+
7
+ if not hasattr (machine , "disable_irq" ):
8
+ print ("SKIP" )
9
+ raise SystemExit
10
+
11
+ count = 0
12
+ thread_done = False
13
+
14
+
15
+ def inc_count ():
16
+ global count
17
+ a = machine .disable_irq ()
18
+ try :
19
+ count += 1
20
+ i = 0
21
+ while i < 20 :
22
+ b = machine .disable_irq ()
23
+ try :
24
+ count += 1
25
+ count -= 1
26
+ i += 1
27
+ finally :
28
+ machine .enable_irq (b )
29
+ finally :
30
+ machine .enable_irq (a )
31
+
32
+
33
+ def inc_count_multiple (times ):
34
+ for _ in range (times ):
35
+ inc_count ()
36
+
37
+
38
+ def thread_entry (inc_times ):
39
+ global thread_done
40
+ inc_count_multiple (inc_times )
41
+ thread_done = True
42
+
43
+
44
+ _thread .start_new_thread (thread_entry , (1000 ,))
45
+ inc_count_multiple (1000 )
46
+
47
+ time .sleep (1 )
48
+
49
+ print ("count" , count , thread_done )
50
+ if count == 2000 :
51
+ print ("PASS" )
Original file line number Diff line number Diff line change
1
+ count 2000 True
2
+ PASS
You can’t perform that action at this time.
0 commit comments