@@ -4,21 +4,22 @@ use crate::mem;
4
4
use crate :: ptr;
5
5
use crate :: sys:: mutex:: Mutex ;
6
6
use crate :: time:: Duration ;
7
- use crate :: sync:: { Arc , atomic:: { AtomicUsize , Ordering :: SeqCst } } ;
7
+ use crate :: sync:: { Arc , atomic:: { AtomicU8 , Ordering :: SeqCst } } ;
8
8
9
9
use crate :: sys:: ffi:: * ;
10
10
use crate :: sys:: thread_local;
11
11
12
- const RUNNING : usize = 0 ;
13
- const DETACHED : usize = 1 ;
14
- const EXITED : usize = 2 ;
12
+ const PENDING : u8 = 0 ;
13
+ const RUNNING : u8 = 1 ;
14
+ const DETACHED : u8 = 2 ;
15
+ const EXITED : u8 = 3 ;
15
16
16
17
pub const DEFAULT_MIN_STACK_SIZE : usize = 4096 ;
17
18
18
19
pub struct Thread {
19
20
id : TaskHandle_t ,
20
21
join_mutex : Arc < Mutex > ,
21
- state : Arc < AtomicUsize > ,
22
+ state : Arc < AtomicU8 > ,
22
23
}
23
24
24
25
unsafe impl Send for Thread { }
@@ -29,27 +30,29 @@ impl Thread {
29
30
pub unsafe fn new ( name : Option < & CStr > , stack : usize , p : Box < dyn FnOnce ( ) > )
30
31
-> io:: Result < Thread > {
31
32
let join_mutex = Arc :: new ( Mutex :: new ( ) ) ;
32
- let state = Arc :: new ( AtomicUsize :: new ( RUNNING ) ) ;
33
+ let state = Arc :: new ( AtomicU8 :: new ( PENDING ) ) ;
33
34
34
35
let arg = box ( join_mutex. clone ( ) , state. clone ( ) , box p) ;
35
36
36
37
let name = name. unwrap_or_else ( || CStr :: from_bytes_with_nul_unchecked ( b"\0 " ) ) ;
37
38
38
39
let mut thread = Thread { id : ptr:: null_mut ( ) , join_mutex, state } ;
39
40
40
- thread . join_mutex . lock ( ) ;
41
+ let arg = Box :: into_raw ( arg ) ;
41
42
42
43
let res = xTaskCreate (
43
44
thread_start,
44
45
name. as_ptr ( ) ,
45
46
stack as u32 ,
46
- Box :: into_raw ( arg) as * mut libc:: c_void ,
47
+ arg as * mut libc:: c_void ,
47
48
5 ,
48
49
& mut thread. id ,
49
50
) ;
50
51
51
52
if res != pdTRUE {
52
- thread. join_mutex . unlock ( ) ;
53
+ if thread. state . load ( SeqCst ) == PENDING {
54
+ drop ( Box :: from_raw ( arg) ) ;
55
+ }
53
56
54
57
if res == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY {
55
58
return Err ( io:: Error :: new ( io:: ErrorKind :: Other , "could not allocate required memory for thread" ) ) ;
@@ -62,9 +65,13 @@ impl Thread {
62
65
63
66
extern fn thread_start ( arg : * mut libc:: c_void ) -> * mut libc:: c_void {
64
67
unsafe {
65
- let arg = Box :: < ( Arc < Mutex > , Arc < AtomicUsize > , Box < Box < dyn FnOnce ( ) > > ) > :: from_raw ( arg as * mut _ ) ;
68
+ let arg = Box :: < ( Arc < Mutex > , Arc < AtomicU8 > , Box < Box < dyn FnOnce ( ) > > ) > :: from_raw ( arg as * mut _ ) ;
66
69
let ( join_mutex, state, main) = * arg;
67
70
71
+ join_mutex. lock ( ) ;
72
+
73
+ state. store ( RUNNING , SeqCst ) ;
74
+
68
75
main ( ) ;
69
76
thread_local:: cleanup ( ) ;
70
77
@@ -119,6 +126,8 @@ impl Thread {
119
126
unsafe {
120
127
assert ! ( self . id != xTaskGetCurrentTaskHandle( ) ) ;
121
128
129
+ while self . state . load ( SeqCst ) == PENDING { }
130
+
122
131
// Just wait for the thread to finish, the rest is handled by `Drop`.
123
132
self . join_mutex . lock ( ) ;
124
133
self . join_mutex . unlock ( ) ;
0 commit comments