@@ -43,7 +43,7 @@ use crate::safeposix::filesystem::{decref_dir, metawalk, Inode, FS_METADATA};
4343use crate :: safeposix:: net:: NET_METADATA ;
4444use crate :: safeposix:: shm:: SHM_METADATA ;
4545
46- use std :: sync :: Arc as RustRfc ;
46+
4747
4848impl Cage {
4949 fn unmap_shm_mappings ( & self ) {
@@ -71,16 +71,61 @@ impl Cage {
7171 }
7272 }
7373
74+ /// ### Description
75+ ///
76+ ///'fork_syscall` creates a new process (cage object)
77+ /// The newly created child process is an exact copy of the
78+ /// parent process (the process that calls fork)
79+ /// apart from it's cage_id and the parent_id
80+ /// In this function we clone the mutex table, condition variables table,
81+ /// semaphore table and the file descriptors and create
82+ /// a new Cage object with these cloned tables.
83+ /// We also update the shared memory mappings - and create mappings
84+ /// from the new Cage object the the
85+ /// parent Cage object's memory mappings.
86+ ///
87+ /// ### Arguments
88+ ///
89+ /// It accepts one parameter:
90+ ///
91+ /// * `child_cageid` : an integer representing the pid of the child process
92+ ///
93+ /// ### Errors
94+ ///
95+ /// There are 2 scenarios where the call to `fork_syscall` might return an error
96+ ///
97+ /// * When the RawMutex::create() call fails to create a new Mutex object
98+ /// * When the RawCondvar::create() call fails to create a new Condition Variable object
99+ ///
100+ /// ### Returns
101+ ///
102+ /// On success it returns a value of 0, and the new child Cage object is added to Cagetable
103+ ///
104+ /// ### Panics
105+ ///
106+ /// This system call has no scenarios where it panics
107+ ///
108+ /// To learn more about the syscall and possible error values, see
109+ /// [fork(2)](https://man7.org/linux/man-pages/man2/fork.2.html)
110+
74111 pub fn fork_syscall ( & self , child_cageid : u64 ) -> i32 {
75- //construct a new mutex in the child cage where each initialized mutex is in
76- // the parent cage
112+ //Create a new mutex table that replicates the mutex table of the parent (calling) Cage object
113+ //Since the child process inherits all the locks that the parent process holds,
77114 let mutextable = self . mutex_table . read ( ) ;
115+ // Initialize the child object's mutex table
78116 let mut new_mutex_table = vec ! [ ] ;
117+ //Loop through each element in the mutex table
118+ //Each entry in the mutex table represents a `lock` which the parent process holds
119+ //Copying them into the child's Cage exhibits the inheritance of the lock
79120 for elem in mutextable. iter ( ) {
80121 if elem. is_some ( ) {
122+ //If the mutex is `Some` - we create a new mutex and store it in the child's mutex table
123+ //The create method returns a new struct obejct that represents a Mutex
81124 let new_mutex_result = interface:: RawMutex :: create ( ) ;
82125 match new_mutex_result {
126+ // If the mutex creation is successful we push it on the child's table
83127 Ok ( new_mutex) => new_mutex_table. push ( Some ( interface:: RustRfc :: new ( new_mutex) ) ) ,
128+ // If the mutex creation returns an error, we abort the system call and return the appropriate error
84129 Err ( _) => {
85130 match Errno :: from_discriminant ( interface:: get_errno ( ) ) {
86131 Ok ( i) => {
@@ -97,20 +142,30 @@ impl Cage {
97142 }
98143 }
99144 } else {
145+ // If the mutex is `None` - we mimic the same behavior in the child's mutex table
100146 new_mutex_table. push ( None ) ;
101147 }
102148 }
103149 drop ( mutextable) ;
104150
105- //construct a new condvar in the child cage where each initialized condvar is
106- // in the parent cage
151+ //Construct a replica of the condition variables table in the child cage object
152+ //This table stores condition variables - which are special variables that the process
153+ //uses to determine whether certain conditions have been met or not. Threads use condition variables
154+ //to stop or resume their operation depending on the value of these variables.
155+ //Read the CondVar table of the calling process
107156 let cvtable = self . cv_table . read ( ) ;
157+ // Initialize the table for the child process
108158 let mut new_cv_table = vec ! [ ] ;
159+ // Loop through all the variables in the parent's table
109160 for elem in cvtable. iter ( ) {
110161 if elem. is_some ( ) {
162+ //Create a condvar to store in the child's Cage object
163+ //Returns the condition variable struct object which implements theb signal, wait, broadcast and timed_wait methods
111164 let new_cv_result = interface:: RawCondvar :: create ( ) ;
112165 match new_cv_result {
166+ // If the result of the creation of the RawCondVar is successful - push it onto the child's mutex table
113167 Ok ( new_cv) => new_cv_table. push ( Some ( interface:: RustRfc :: new ( new_cv) ) ) ,
168+ // If the creation was unsucessful - return an Error
114169 Err ( _) => {
115170 match Errno :: from_discriminant ( interface:: get_errno ( ) ) {
116171 Ok ( i) => {
@@ -127,18 +182,25 @@ impl Cage {
127182 }
128183 }
129184 } else {
185+ // If the value is None - mimic the behavior in the child's condition variable table
130186 new_cv_table. push ( None ) ;
131187 }
132188 }
133189 drop ( cvtable) ;
134190
135- //construct new cage struct with a cloned fdtable
191+ //Clone the file descriptor table in the child's Cage object
192+ //Each entry in the file descriptor table points to an open file description which
193+ //in turn references the actual inodes of the files on disk
136194 let newfdtable = init_fdtable ( ) ;
195+ //Loop from 0 to maximum value of file descriptor index
137196 for fd in 0 ..MAXFD {
138197 let checkedfd = self . get_filedescriptor ( fd) . unwrap ( ) ;
198+ //Get the lock for the file descriptor
139199 let unlocked_fd = checkedfd. read ( ) ;
140200 if let Some ( filedesc_enum) = & * unlocked_fd {
201+ // Check the type of the file descriptor
141202 match filedesc_enum {
203+ // If the fd is linked to a file
142204 File ( _normalfile_filedesc_obj) => {
143205 let inodenum_option = if let File ( f) = filedesc_enum {
144206 Some ( f. inode )
@@ -147,8 +209,10 @@ impl Cage {
147209 } ;
148210
149211 if let Some ( inodenum) = inodenum_option {
150- //increment the reference count on the inode
151212 let mut inode = FS_METADATA . inodetable . get_mut ( & inodenum) . unwrap ( ) ;
213+ //Since the child Cage also inherits the parent's fd table
214+ //We increment the reference count on the actual inodes of the files on disk
215+ //Since the child Cage is a new process that also references those files
152216 match * inode {
153217 Inode :: File ( ref mut f) => {
154218 f. refcount += 1 ;
@@ -165,52 +229,56 @@ impl Cage {
165229 }
166230 }
167231 }
232+ // If the fd is linked to a pipe increment the ref count of the pipe
168233 Pipe ( pipe_filedesc_obj) => {
169234 pipe_filedesc_obj. pipe . incr_ref ( pipe_filedesc_obj. flags )
170235 }
236+ // If the fd is linked to a socket increment the ref count of the socket
171237 Socket ( socket_filedesc_obj) => {
172- // checking whether this is a domain socket
238+ // Check if it is a domain socket
173239 let sock_tmp = socket_filedesc_obj. handle . clone ( ) ;
174240 let mut sockhandle = sock_tmp. write ( ) ;
175241 let socket_type = sockhandle. domain ;
242+ //Here we only increment the reference for AF_UNIX socket type
243+ //Since these are the only sockets that have an inode associated with them
176244 if socket_type == AF_UNIX {
245+ //Increment the appropriate reference counter of the correct socket
246+ //Each socket has two pipes associated with them - a read and write pipe
247+ //Here we grab these two pipes and increment their references individually
248+ //And also increment the reference count of the socket as a whole
177249 if let Some ( sockinfo) = & sockhandle. unix_info {
178250 if let Some ( sendpipe) = sockinfo. sendpipe . as_ref ( ) {
179251 sendpipe. incr_ref ( O_WRONLY ) ;
180252 }
181253 if let Some ( receivepipe) = sockinfo. receivepipe . as_ref ( ) {
182254 receivepipe. incr_ref ( O_RDONLY ) ;
183255 }
184- if let Some ( uinfo) = & mut sockhandle. unix_info {
185- if let Inode :: Socket ( ref mut sock) =
186- * ( FS_METADATA . inodetable . get_mut ( & uinfo. inode ) . unwrap ( ) )
256+ if let Inode :: Socket ( ref mut sock) =
257+ * ( FS_METADATA . inodetable . get_mut ( & sockinfo. inode ) . unwrap ( ) )
187258 {
188259 sock. refcount += 1 ;
189260 }
190- }
191261 }
192262 }
193263 drop ( sockhandle) ;
194- let sock_tmp = socket_filedesc_obj. handle . clone ( ) ;
195- let mut sockhandle = sock_tmp. write ( ) ;
196- if let Some ( uinfo) = & mut sockhandle. unix_info {
197- if let Inode :: Socket ( ref mut sock) =
198- * ( FS_METADATA . inodetable . get_mut ( & uinfo. inode ) . unwrap ( ) )
199- {
200- sock. refcount += 1 ;
201- }
202- }
203264 }
204265 _ => { }
205266 }
206267
207268 let newfdobj = filedesc_enum. clone ( ) ;
208-
269+ // Insert the file descriptor object into the new file descriptor table
209270 let _insertval = newfdtable[ fd as usize ] . write ( ) . insert ( newfdobj) ;
210- //add deep copied fd to fd table
271+
211272 }
212273 }
274+
275+ //We read the current working directory of the parent Cage object
213276 let cwd_container = self . cwd . read ( ) ;
277+ //We try to resolve the inode of the current working directory - if the
278+ //resolution is successful we update the reference count of the current working directory
279+ //since the newly created Child cage object also references the same directory
280+ //If the resolution is not successful - the code panics since the cwd's inode cannot be resolved
281+ //correctly
214282 if let Some ( cwdinodenum) = metawalk ( & cwd_container) {
215283 if let Inode :: Dir ( ref mut cwddir) =
216284 * ( FS_METADATA . inodetable . get_mut ( & cwdinodenum) . unwrap ( ) )
@@ -223,13 +291,16 @@ impl Cage {
223291 panic ! ( "We changed from a directory that was not a directory in chdir!" ) ;
224292 }
225293
226- // we grab the parent cages main threads sigset and store it at 0
227- // we do this because we haven't established a thread for the cage yet, and dont
228- // have a threadid to store it at this way the child can initialize the
229- // sigset properly when it establishes its own mainthreadid
294+ // We clone the parent cage's main threads and store them and index 0
295+ // This is done since there isn't a thread established for the child Cage object yet -
296+ // And there is no threadId to store it at.
297+ // The child Cage object can then initialize and store the sigset appropriately when it establishes its own
298+ // main thread id.
230299 let newsigset = interface:: RustHashMap :: new ( ) ;
300+ // Here we check if Lind is being run under the test suite or not
231301 if !interface:: RUSTPOSIX_TESTSUITE . load ( interface:: RustAtomicOrdering :: Relaxed ) {
232- // we don't add these for the test suite
302+ // When rustposix runs independently (not as Lind paired with NaCL runtime) we do not handle signals
303+ // The test suite runs rustposix independently and hence we do not handle signals for the test suite
233304 let mainsigsetatomic = self
234305 . sigset
235306 . get (
@@ -241,29 +312,33 @@ impl Cage {
241312 let mainsigset = interface:: RustAtomicU64 :: new (
242313 mainsigsetatomic. load ( interface:: RustAtomicOrdering :: Relaxed ) ,
243314 ) ;
315+ // Insert the parent cage object's main threads sigset and store them at index 0
244316 newsigset. insert ( 0 , mainsigset) ;
245317 }
246318
247- /*
248- * Construct a new semaphore table in child cage which equals to the one in
249- * the parent cage
250- */
319+ // Construct a new semaphore table in child cage which equals to the one in the parent cage
251320 let semtable = & self . sem_table ;
252321 let new_semtable: interface:: RustHashMap <
253322 u32 ,
254323 interface:: RustRfc < interface:: RustSemaphore > ,
255324 > = interface:: RustHashMap :: new ( ) ;
256- // Loop all pairs
325+ // Loop all pairs of semaphores and insert their copies into the new semaphore table
326+ // Each pair consists of a key which is 32 bit unsigned integer
327+ // And a Semaphore Object implemented as RustSemaphore
257328 for pair in semtable. iter ( ) {
258329 new_semtable. insert ( ( * pair. key ( ) ) . clone ( ) , pair. value ( ) . clone ( ) ) ;
259330 }
260331
332+ // Create a new cage object using the cloned tables and the child id passed as a parameter
261333 let cageobj = Cage {
262334 cageid : child_cageid,
263335 cwd : interface:: RustLock :: new ( self . cwd . read ( ) . clone ( ) ) ,
336+ // Setting the parent to be the current Cage object
264337 parent : self . cageid ,
338+ // Setting the fd table with our cloned fd table
265339 filedescriptortable : newfdtable,
266340 cancelstatus : interface:: RustAtomicBool :: new ( false ) ,
341+ // Intitialize IDs with the default value
267342 // This happens because self.getgid tries to copy atomic value which does not implement
268343 // "Copy" trait; self.getgid.load returns i32.
269344 getgid : interface:: RustAtomicI32 :: new (
@@ -278,28 +353,43 @@ impl Cage {
278353 geteuid : interface:: RustAtomicI32 :: new (
279354 self . geteuid . load ( interface:: RustAtomicOrdering :: Relaxed ) ,
280355 ) ,
356+ // Clone the reverse shm mappings
281357 rev_shm : interface:: Mutex :: new ( ( * self . rev_shm . lock ( ) ) . clone ( ) ) ,
358+ // Setting the mutex tables with our copy of the mutex table
282359 mutex_table : interface:: RustLock :: new ( new_mutex_table) ,
360+ // Setting the condition variables table with our copy
283361 cv_table : interface:: RustLock :: new ( new_cv_table) ,
362+ // Setting the semaphores table with our copy
284363 sem_table : new_semtable,
364+ // Creating a new empty table for storing threads of the child Cage object
285365 thread_table : interface:: RustHashMap :: new ( ) ,
366+ // Cloning the signal handler of the parent Cage object
286367 signalhandler : self . signalhandler . clone ( ) ,
368+ // Setting the signal set with the cloned and altered sigset
287369 sigset : newsigset,
370+ // Creating a new copy for the pending signal set
288371 pendingsigset : interface:: RustHashMap :: new ( ) ,
372+ // Setting the main thread id to 0 - since it is uninitialized
289373 main_threadid : interface:: RustAtomicU64 :: new ( 0 ) ,
374+ // Creating a new timer for the process with id = child_cageid
290375 interval_timer : interface:: IntervalTimer :: new ( child_cageid) ,
291376 } ;
292377
293378 let shmtable = & SHM_METADATA . shmtable ;
294- //update fields for shared mappings in cage
379+ // Updating the shared mappings in the child cage object
380+ // Loop through all the reverse mappings in the new cage object
295381 for rev_mapping in cageobj. rev_shm . lock ( ) . iter ( ) {
296382 let mut shment = shmtable. get_mut ( & rev_mapping. 1 ) . unwrap ( ) ;
297383 shment. shminfo . shm_nattch += 1 ;
384+ // Get the references of the curret cage id
298385 let refs = shment. attached_cages . get ( & self . cageid ) . unwrap ( ) ;
386+ // Copy the references
299387 let childrefs = refs. clone ( ) ;
300388 drop ( refs) ;
389+ // Create references from the new Cage object to the copied references
301390 shment. attached_cages . insert ( child_cageid, childrefs) ;
302391 }
392+ // Inserting the child Cage object at the appropriate index in the Cage table
303393 interface:: cagetable_insert ( child_cageid, cageobj) ;
304394
305395 0
0 commit comments