1+ use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
2+
3+ use aero_syscall:: OpenFlags ;
14use alloc:: { sync:: Arc , vec:: Vec } ;
25
36use crate :: utils:: sync:: { BlockQueue , Mutex } ;
@@ -38,41 +41,59 @@ impl Buffer {
3841 }
3942}
4043
41- struct BufferQueue {
42- buffer : Mutex < Buffer > ,
43- }
44-
45- impl BufferQueue {
46- fn new ( ) -> Self {
47- Self {
48- buffer : Mutex :: new ( Buffer :: new ( ) ) ,
49- }
50- }
51- }
52-
5344pub struct Pipe {
54- queue : BufferQueue ,
45+ queue : Mutex < Buffer > ,
5546
5647 readers : BlockQueue ,
5748 writers : BlockQueue ,
49+
50+ /// The number of writers currently connected to the pipe.
51+ num_writers : AtomicUsize ,
5852}
5953
6054impl Pipe {
6155 pub fn new ( ) -> Arc < Self > {
6256 Arc :: new ( Self {
63- queue : BufferQueue :: new ( ) ,
57+ queue : Mutex :: new ( Buffer :: new ( ) ) ,
6458
6559 readers : BlockQueue :: new ( ) ,
6660 writers : BlockQueue :: new ( ) ,
61+
62+ num_writers : AtomicUsize :: new ( 0 ) ,
6763 } )
6864 }
65+
66+ /// Returns whether the pipe has active writers.
67+ pub fn has_active_writers ( & self ) -> usize {
68+ self . num_writers . load ( Ordering :: SeqCst )
69+ }
6970}
7071
7172impl INodeInterface for Pipe {
73+ fn open ( & self , flags : OpenFlags ) -> super :: Result < ( ) > {
74+ // Write end of the pipe:
75+ if flags. contains ( OpenFlags :: O_WRONLY ) {
76+ self . num_writers . fetch_add ( 1 , Ordering :: SeqCst ) ;
77+ }
78+
79+ Ok ( ( ) )
80+ }
81+
82+ fn close ( & self , flags : OpenFlags ) {
83+ // Write end of the pipe:
84+ if flags. contains ( OpenFlags :: O_WRONLY ) {
85+ let active_writers = ( self . num_writers . fetch_sub ( 1 , Ordering :: SeqCst ) - 1 ) == 0 ;
86+ // There are no active writers and no data to read (reached EOF).
87+ if active_writers {
88+ self . readers . notify_complete ( ) ;
89+ }
90+ }
91+ }
92+
7293 fn read_at ( & self , _offset : usize , buf : & mut [ u8 ] ) -> super :: Result < usize > {
73- let mut buffer = self
74- . readers
75- . block_on ( & self . queue . buffer , |lock| lock . has_data ( ) ) ?;
94+ let mut buffer = self . readers . block_on ( & self . queue , |lock| {
95+ lock . has_data ( ) || ! self . has_active_writers ( ) == 0
96+ } ) ?;
7697
7798 let read = buffer. read_data ( buf) ;
7899
@@ -85,7 +106,7 @@ impl INodeInterface for Pipe {
85106 }
86107
87108 fn write_at ( & self , offset : usize , buf : & [ u8 ] ) -> super :: Result < usize > {
88- let res = offset + self . queue . buffer . lock ( ) . write_data ( buf) ;
109+ let res = offset + self . queue . lock ( ) . write_data ( buf) ;
89110 self . readers . notify_complete ( ) ;
90111
91112 Ok ( res)
0 commit comments