1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use core::ops;
15 
16 use ylong_io::Interest;
17 
18 const READABLE: usize = 0b0_01;
19 const WRITABLE: usize = 0b0_10;
20 const READ_CLOSED: usize = 0b0_0100;
21 const WRITE_CLOSED: usize = 0b0_1000;
22 
23 cfg_not_ffrt! {
24     use ylong_io::{Event, EventTrait};
25 }
26 
27 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
28 pub struct Ready(usize);
29 
30 #[derive(Debug)]
31 pub(crate) struct ReadyEvent {
32     tick: u8,
33     pub(crate) ready: Ready,
34 }
35 
36 impl Ready {
37     pub const EMPTY: Ready = Ready(0);
38 
39     pub const READABLE: Ready = Ready(READABLE);
40 
41     pub const WRITABLE: Ready = Ready(WRITABLE);
42 
43     pub const READ_CLOSED: Ready = Ready(READ_CLOSED);
44 
45     pub const WRITE_CLOSED: Ready = Ready(WRITE_CLOSED);
46 
47     pub const ALL: Ready = Ready(READABLE | WRITABLE | READ_CLOSED | WRITE_CLOSED);
48 
49     #[cfg(not(feature = "ffrt"))]
from_event(event: &Event) -> Ready50     pub(crate) fn from_event(event: &Event) -> Ready {
51         let mut ready = Ready::EMPTY;
52 
53         if event.is_readable() {
54             ready |= Ready::READABLE;
55         }
56 
57         if event.is_writable() {
58             ready |= Ready::WRITABLE;
59         }
60 
61         if event.is_read_closed() {
62             ready |= Ready::READ_CLOSED;
63         }
64 
65         if event.is_write_closed() {
66             ready |= Ready::WRITE_CLOSED;
67         }
68         ready
69     }
70 
is_empty(self) -> bool71     pub fn is_empty(self) -> bool {
72         self == Ready::EMPTY
73     }
74 
is_readable(self) -> bool75     pub fn is_readable(self) -> bool {
76         (self & Ready::READABLE).0 != 0 || self.is_read_closed()
77     }
78 
is_writable(self) -> bool79     pub fn is_writable(self) -> bool {
80         (self & Ready::WRITABLE).0 != 0 || self.is_write_closed()
81     }
82 
is_read_closed(self) -> bool83     pub fn is_read_closed(self) -> bool {
84         (self & Ready::READ_CLOSED).0 != 0
85     }
86 
is_write_closed(self) -> bool87     pub fn is_write_closed(self) -> bool {
88         (self & Ready::WRITE_CLOSED).0 != 0
89     }
90 
from_usize(val: usize) -> Ready91     pub(crate) fn from_usize(val: usize) -> Ready {
92         Ready(val & Ready::ALL.as_usize())
93     }
94 
as_usize(self) -> usize95     pub(crate) fn as_usize(self) -> usize {
96         self.0
97     }
98 
from_interest(interest: Interest) -> Ready99     pub(crate) fn from_interest(interest: Interest) -> Ready {
100         let mut ready = Ready::EMPTY;
101 
102         if interest.is_readable() {
103             ready |= Ready::READABLE;
104             ready |= Ready::READ_CLOSED;
105         }
106 
107         if interest.is_writable() {
108             ready |= Ready::WRITABLE;
109             ready |= Ready::WRITE_CLOSED;
110         }
111 
112         ready
113     }
114 
intersection(self, interest: Interest) -> Ready115     pub(crate) fn intersection(self, interest: Interest) -> Ready {
116         Ready(self.0 & Ready::from_interest(interest).0)
117     }
118 
satisfies(self, interest: Interest) -> bool119     pub(crate) fn satisfies(self, interest: Interest) -> bool {
120         self.0 & Ready::from_interest(interest).0 != 0
121     }
122 }
123 
124 impl ops::BitOr<Ready> for Ready {
125     type Output = Ready;
126 
127     #[inline]
bitor(self, other: Ready) -> Self::Output128     fn bitor(self, other: Ready) -> Self::Output {
129         Ready(self.0 | other.0)
130     }
131 }
132 
133 impl ops::BitOrAssign<Ready> for Ready {
134     #[inline]
bitor_assign(&mut self, other: Ready)135     fn bitor_assign(&mut self, other: Ready) {
136         self.0 |= other.0
137     }
138 }
139 
140 impl ops::BitAnd<Ready> for Ready {
141     type Output = Ready;
142 
143     #[inline]
bitand(self, other: Ready) -> Self::Output144     fn bitand(self, other: Ready) -> Self::Output {
145         Ready(self.0 & other.0)
146     }
147 }
148 
149 impl ops::Sub<Ready> for Ready {
150     type Output = Ready;
151 
152     #[inline]
sub(self, other: Ready) -> Self::Output153     fn sub(self, other: Ready) -> Self::Output {
154         Ready(self.0 & !other.0)
155     }
156 }
157 
158 impl ReadyEvent {
new(tick: u8, ready: Ready) -> Self159     pub fn new(tick: u8, ready: Ready) -> Self {
160         ReadyEvent { tick, ready }
161     }
162 
get_tick(&self) -> u8163     pub fn get_tick(&self) -> u8 {
164         self.tick
165     }
166 
get_ready(&self) -> Ready167     pub fn get_ready(&self) -> Ready {
168         self.ready
169     }
170 }
171 
172 cfg_ffrt! {
173     fn is_readable(event: i32) -> bool {
174         (event as libc::c_int & libc::EPOLLIN) != 0
175             || (event as libc::c_int & libc::EPOLLPRI) != 0
176     }
177 
178     fn is_writable(event: i32) -> bool {
179         (event as libc::c_int & libc::EPOLLOUT) != 0
180     }
181 
182     fn is_read_closed(event: i32) -> bool {
183         event as libc::c_int & libc::EPOLLHUP != 0
184             || (event as libc::c_int & libc::EPOLLIN != 0
185                 && event as libc::c_int & libc::EPOLLRDHUP != 0)
186     }
187 
188     fn is_write_closed(event: i32) -> bool {
189         event as libc::c_int & libc::EPOLLHUP != 0
190             || (event as libc::c_int & libc::EPOLLOUT != 0
191                 && event as libc::c_int & libc::EPOLLERR != 0)
192             || event as libc::c_int == libc::EPOLLERR
193     }
194 
195     pub(crate) fn from_event_inner(event: i32) -> Ready {
196         let mut ready = Ready::EMPTY;
197         if is_readable(event) {
198             ready |= Ready::READABLE;
199         }
200 
201         if is_writable(event) {
202             ready |= Ready::WRITABLE;
203         }
204 
205         if is_read_closed(event) {
206             ready |= Ready::READ_CLOSED;
207         }
208 
209         if is_write_closed(event) {
210             ready |= Ready::WRITE_CLOSED;
211         }
212         ready
213     }
214 }
215 
216 #[cfg(test)]
217 mod test {
218     use ylong_io::Interest;
219 
220     use crate::net::{Ready, ReadyEvent};
221 
222     // @title  ready from_event function ut test
223     // @design conditions of use override
224     // @precon none
225     // @brief  1. Create an event
226     //         2. Call from_event
227     //         3. Verify the returned results
228     // @expect 1. Event readable to get readable Ready instances
229     //         2. Event writable, call writable Ready instances
230     //         3. Event Read Close, Call Read Close Ready Instance
231     //         4. Event Write Close, Call Write Close Ready Instance
232     // @auto  Yes
233     #[test]
234     #[cfg(all(not(feature = "ffrt"), target_os = "linux"))]
ut_ready_from_event()235     fn ut_ready_from_event() {
236         ut_ready_from_event_01();
237         ut_ready_from_event_02();
238         ut_ready_from_event_03();
239         ut_ready_from_event_04();
240 
241         // Readable
242         fn ut_ready_from_event_01() {
243             let mut event = libc::epoll_event {
244                 events: 0b00,
245                 u64: 0,
246             };
247             event.events |= libc::EPOLLIN as u32;
248             let ready = Ready::from_event(&event);
249             assert_eq!(ready.0, 0b01);
250         }
251 
252         // Writable
253         fn ut_ready_from_event_02() {
254             let mut event = libc::epoll_event {
255                 events: 0b00,
256                 u64: 0,
257             };
258             event.events |= libc::EPOLLOUT as u32;
259             let ready = Ready::from_event(&event);
260             assert_eq!(ready.0, 0b10);
261         }
262 
263         // Read off
264         fn ut_ready_from_event_03() {
265             let mut event = libc::epoll_event {
266                 events: 0b00,
267                 u64: 0,
268             };
269             event.events |= (libc::EPOLLIN | libc::EPOLLRDHUP) as u32;
270             let ready = Ready::from_event(&event);
271             assert_eq!(ready.0, 0b101);
272         }
273 
274         // Write Off
275         fn ut_ready_from_event_04() {
276             let mut event = libc::epoll_event {
277                 events: 0x00,
278                 u64: 0,
279             };
280             event.events |= (libc::EPOLLOUT | libc::EPOLLERR) as u32;
281             let ready = Ready::from_event(&event);
282             assert_eq!(ready.0, 0b1010);
283         }
284     }
285 
286     /// UT test cases for ready from_usize function
287     ///
288     /// # Brief
289     /// 1. Enter a usize, call from_usize
290     /// 2. Verify the returned results
291     #[test]
ut_ready_from_usize()292     fn ut_ready_from_usize() {
293         let ready = Ready::from_usize(0x01);
294         assert_eq!(ready.0, 0x01);
295     }
296 
297     /// UT test cases for ready is_empty function
298     ///
299     /// # Brief
300     /// 1. Create a Ready
301     /// 2. Call is_empty
302     /// 3. Verify the returned results
303     #[test]
ut_ready_is_empty()304     fn ut_ready_is_empty() {
305         let ready = Ready::from_usize(0x00);
306         assert!(ready.is_empty());
307 
308         let ready = Ready::from_usize(0x01);
309         assert!(!ready.is_empty());
310     }
311 
312     /// UT test cases for ready is_readable function
313     ///
314     /// # Brief
315     /// 1. Create a Ready
316     /// 2. Call is_readable
317     /// 3. Verify the returned results
318     #[test]
ut_ready_is_readable()319     fn ut_ready_is_readable() {
320         let ready = Ready::from_usize(0x01);
321         assert!(ready.is_readable());
322 
323         let ready = Ready::from_usize(0x02);
324         assert!(!ready.is_readable());
325     }
326 
327     /// UT test cases for ready is_writable function
328     ///
329     /// # Brief
330     /// 1. Create a Ready
331     /// 2. Call is_writable
332     /// 3. Verify the returned results
333     #[test]
ut_ready_is_writable()334     fn ut_ready_is_writable() {
335         let ready = Ready::from_usize(0x02);
336         assert!(ready.is_writable());
337 
338         let ready = Ready::from_usize(0x01);
339         assert!(!ready.is_writable());
340     }
341 
342     /// UT test cases for ready is_read_closed function
343     ///
344     /// # Brief
345     /// 1. Create a Ready
346     /// 2. Call is_read_closed
347     /// 3. Verify the returned results
348     #[test]
ut_ready_is_read_closed()349     fn ut_ready_is_read_closed() {
350         let ready = Ready::from_usize(0x04);
351         assert!(ready.is_read_closed());
352 
353         let ready = Ready::from_usize(0x01);
354         assert!(!ready.is_read_closed());
355     }
356 
357     /// UT test cases for ready is_write_closed function
358     ///
359     /// # Brief
360     /// 1. Create a Ready
361     /// 2. Call is_write_closed
362     /// 3. Verify the returned results
363     #[test]
ut_ready_is_write_closed()364     fn ut_ready_is_write_closed() {
365         let ready = Ready::from_usize(0x08);
366         assert!(ready.is_write_closed());
367 
368         let ready = Ready::from_usize(0x01);
369         assert!(!ready.is_write_closed());
370     }
371 
372     /// UT test cases for ready as_usize function
373     ///
374     /// # Brief
375     /// 1. Create a Ready
376     /// 2. Call as_usize
377     /// 3. Verify the returned results
378     #[test]
ut_ready_as_usize()379     fn ut_ready_as_usize() {
380         let ready = Ready::from_usize(0x08);
381         assert_eq!(ready.as_usize(), 0x08);
382     }
383 
384     /// UT test cases for ready from_interest function
385     ///
386     /// # Brief
387     /// 1. Create a Interest instances
388     /// 2. Call from_interest
389     /// 3. Verify the returned results
390     #[test]
ut_ready_from_interest()391     fn ut_ready_from_interest() {
392         let interest = Interest::READABLE;
393         let ready = Ready::from_interest(interest);
394         assert_eq!(ready.as_usize(), 0b101);
395 
396         let interest = Interest::WRITABLE;
397         let ready = Ready::from_interest(interest);
398         assert_eq!(ready.as_usize(), 0b1010);
399     }
400 
401     /// UT test cases for ready intersection function
402     ///
403     /// # Brief
404     /// 1. Create a Interest instances and a Ready instances
405     /// 2. Call intersection
406     /// 3. Verify the returned results
407     #[test]
ut_ready_intersection()408     fn ut_ready_intersection() {
409         let interest = Interest::READABLE;
410         let ready = Ready::from_usize(0b1111);
411         let res = ready.intersection(interest);
412         assert_eq!(res.0, 0b0101);
413     }
414 
415     /// UT test cases for ready satisfies function
416     ///
417     /// # Brief
418     /// 1. Create a Interest instances, and a Ready instances
419     /// 2. Call satisfies
420     /// 3. Verify the returned results
421     #[test]
ut_ready_satisfies()422     fn ut_ready_satisfies() {
423         let interest = Interest::READABLE;
424         let ready = Ready::from_usize(0b1111);
425         assert!(ready.satisfies(interest));
426 
427         let ready = Ready::from_usize(0b0000);
428         assert!(!ready.satisfies(interest));
429     }
430 
431     /// UT test cases for ready bitor function
432     ///
433     /// # Brief
434     /// 1. Create two Ready instances
435     /// 2. Call bitor or use | logical operators
436     /// 3. Verify the returned results
437     #[test]
ut_ready_bitor()438     fn ut_ready_bitor() {
439         let ready1 = Ready::from_usize(0b1010);
440         let ready2 = Ready::from_usize(0b0101);
441         let ready3 = ready1 | ready2;
442         assert_eq!(ready3.0, 0b1111);
443     }
444 
445     /// UT test cases for ready bitor_assign function
446     ///
447     /// # Brief
448     /// 1. Create two Ready instances
449     /// 2. Call bitor_assign or use |= logical operators
450     /// 3. Verify the returned results
451     #[test]
ut_ready_bitor_assign()452     fn ut_ready_bitor_assign() {
453         let mut ready1 = Ready::from_usize(0b1010);
454         let ready2 = Ready::from_usize(0b0101);
455         ready1 |= ready2;
456         assert_eq!(ready1.0, 0b1111);
457     }
458 
459     /// UT test cases for ready bitand function
460     ///
461     /// # Brief
462     /// 1. Create two Ready instances
463     /// 2. Call bitand or use & logical operators
464     /// 3. Verify the returned results
465     #[test]
ut_ready_bitand()466     fn ut_ready_bitand() {
467         let ready1 = Ready::from_usize(0b1010);
468         let ready2 = Ready::from_usize(0b0101);
469         let ready = ready1 & ready2;
470         assert_eq!(ready.0, 0b0000);
471     }
472 
473     /// UT test cases for ready bitsub function
474     ///
475     /// # Brief
476     /// 1. Create two Ready instances
477     /// 2. Call bitsub or use - logical operators
478     /// 3. Verify the returned results
479     #[test]
ut_ready_bitsub()480     fn ut_ready_bitsub() {
481         let ready1 = Ready::from_usize(0b1111);
482         let ready2 = Ready::from_usize(0b0101);
483         let ready = ready1 - ready2;
484         assert_eq!(ready.0, 0b1010);
485     }
486 
487     /// UT test cases for ready_event new function
488     ///
489     /// # Brief
490     /// 1. Call new
491     /// 2. Verify the returned results
492     #[test]
ut_ready_event_new()493     fn ut_ready_event_new() {
494         let ready_event = ReadyEvent::new(1u8, Ready::from_usize(0b0101));
495         assert_eq!(ready_event.tick, 1u8);
496         assert_eq!(ready_event.ready.0, 0b0101);
497     }
498 
499     /// UT test cases for ready_event get_tick function
500     ///
501     /// # Brief
502     /// 1. Create a ready_event
503     /// 2. Call get_tick
504     /// 3. Verify the returned results
505     #[test]
ut_ready_event_get_tick()506     fn ut_ready_event_get_tick() {
507         let ready_event = ReadyEvent::new(1u8, Ready::from_usize(0b0101));
508         assert_eq!(ready_event.get_tick(), 1u8);
509     }
510 
511     /// UT test cases for ready_event get_ready function
512     ///
513     /// # Brief
514     /// 1. Create a ready_event
515     /// 2. Call get_ready
516     /// 3. Verify the returned results
517     #[test]
ut_ready_event_get_ready()518     fn ut_ready_event_get_ready() {
519         let ready_event = ReadyEvent::new(1u8, Ready::from_usize(0b0101));
520         assert_eq!(ready_event.get_ready().0, 0b0101);
521     }
522 }
523