1
1
//@ignore-target-windows: No eventfd in windows
2
2
3
+ use std:: thread;
4
+
3
5
fn main ( ) {
4
- test_read_write ( ) ;
6
+ //test_read_write();
7
+ test_race ( ) ;
5
8
}
6
9
7
10
fn test_read_write ( ) {
8
11
let flags = libc:: EFD_NONBLOCK | libc:: EFD_CLOEXEC ;
9
12
let fd = unsafe { libc:: eventfd ( 0 , flags) } ;
10
- let data : [ u8 ; 8 ] ;
13
+ let sized_8_data : [ u8 ; 8 ] ;
11
14
if cfg ! ( target_endian = "big" ) {
12
15
// Adjust the data based on the endianess of host system.
13
- data = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ;
16
+ sized_8_data = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ;
14
17
} else {
15
- data = [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
18
+ sized_8_data = [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
16
19
}
17
- // Write 1 to the counter
18
- let res: i64 =
19
- unsafe { libc:: write ( fd, data. as_ptr ( ) as * const libc:: c_void , 8 ) . try_into ( ) . unwrap ( ) } ;
20
+ // Write 1 to the counter.
21
+ let res: i64 = unsafe {
22
+ libc:: write ( fd, sized_8_data. as_ptr ( ) as * const libc:: c_void , 8 ) . try_into ( ) . unwrap ( )
23
+ } ;
20
24
assert_eq ! ( res, 8 ) ;
21
25
22
- // Read 1 from the counter
26
+ // Read 1 from the counter.
23
27
let mut buf: [ u8 ; 8 ] = [ 1 ; 8 ] ;
24
28
let res: i32 = unsafe {
25
29
libc:: read ( fd, buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) as libc:: size_t ) . try_into ( ) . unwrap ( )
26
30
} ;
27
- // read returns number of bytes has been read, which is always 8
31
+ // Read returns number of bytes has been read, which is always 8.
28
32
assert_eq ! ( res, 8 ) ;
29
33
let counter: u64 ;
30
34
if cfg ! ( target_endian = "big" ) {
@@ -34,4 +38,82 @@ fn test_read_write() {
34
38
counter = u64:: from_le_bytes ( buf) ;
35
39
}
36
40
assert_eq ! ( counter, 1 ) ;
41
+
42
+ // Write with buffer size > 8 bytes.
43
+ let res: i64 = unsafe {
44
+ libc:: write ( fd, sized_8_data. as_ptr ( ) as * const libc:: c_void , 8 ) . try_into ( ) . unwrap ( )
45
+ } ;
46
+ assert_eq ! ( res, 8 ) ;
47
+
48
+ // Read with supplied buffer that < 8 bytes.
49
+ let mut buf: [ u8 ; 7 ] = [ 1 ; 7 ] ;
50
+ let res: i32 = unsafe {
51
+ libc:: read ( fd, buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) as libc:: size_t ) . try_into ( ) . unwrap ( )
52
+ } ;
53
+ assert_eq ! ( res, -1 ) ;
54
+
55
+ // Write with supplied buffer that < 8 bytes
56
+ let res: i64 = unsafe {
57
+ libc:: write ( fd, sized_8_data[ 0 ..7 ] . as_ptr ( ) as * const libc:: c_void , 7 ) . try_into ( ) . unwrap ( )
58
+ } ;
59
+ assert_eq ! ( res, -1 ) ;
60
+
61
+ // Write with supplied buffer that > 8 bytes
62
+ let sized_9_data: [ u8 ; 9 ] ;
63
+ if cfg ! ( target_endian = "big" ) {
64
+ // Adjust the data based on the endianess of host system.
65
+ sized_9_data = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ;
66
+ } else {
67
+ sized_9_data = [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
68
+ }
69
+ let res: i64 = unsafe {
70
+ libc:: write ( fd, sized_9_data. as_ptr ( ) as * const libc:: c_void , 8 ) . try_into ( ) . unwrap ( )
71
+ } ;
72
+ assert_eq ! ( res, 8 ) ;
73
+
74
+ // Read with supplied buffer > 8 bytes.
75
+ let mut buf: [ u8 ; 9 ] = [ 1 ; 9 ] ;
76
+ let res: i32 = unsafe {
77
+ libc:: read ( fd, buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) as libc:: size_t ) . try_into ( ) . unwrap ( )
78
+ } ;
79
+ assert_eq ! ( res, 8 ) ;
80
+ }
81
+
82
+ fn test_race ( ) {
83
+ static mut VAL : u8 = 0 ;
84
+ let flags = libc:: EFD_NONBLOCK | libc:: EFD_CLOEXEC ;
85
+ let fd = unsafe { libc:: eventfd ( 0 , flags) } ;
86
+ let thread1 = thread:: spawn ( move || {
87
+ let mut buf: [ u8 ; 8 ] = [ 0 ; 8 ] ;
88
+ let res: i32 = unsafe {
89
+ libc:: read ( fd, buf. as_mut_ptr ( ) . cast ( ) , buf. len ( ) as libc:: size_t ) . try_into ( ) . unwrap ( )
90
+ } ;
91
+ // read returns number of bytes has been read, which is always 8
92
+ assert_eq ! ( res, 8 ) ;
93
+ let counter: u64 ;
94
+ if cfg ! ( target_endian = "big" ) {
95
+ // Read will store the bytes based on the endianess of the host system.
96
+ counter = u64:: from_be_bytes ( buf) ;
97
+ } else {
98
+ counter = u64:: from_le_bytes ( buf) ;
99
+ }
100
+ assert_eq ! ( counter, 1 ) ;
101
+ // Read from the static mutable variable
102
+ unsafe { assert_eq ! ( VAL , 1 ) } ;
103
+ } ) ;
104
+ // Write to the static mutable variable
105
+ unsafe { VAL = 1 } ;
106
+ let data: [ u8 ; 8 ] ;
107
+ if cfg ! ( target_endian = "big" ) {
108
+ // Adjust the data based on the endianess of host system.
109
+ data = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] ;
110
+ } else {
111
+ data = [ 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
112
+ }
113
+ let res: i64 =
114
+ unsafe { libc:: write ( fd, data. as_ptr ( ) as * const libc:: c_void , 8 ) . try_into ( ) . unwrap ( ) } ;
115
+ // write return number of bytes written, which is always 8
116
+ assert_eq ! ( res, 8 ) ;
117
+ thread:: yield_now ( ) ;
118
+ thread1. join ( ) . unwrap ( ) ;
37
119
}
0 commit comments