@@ -143,6 +143,49 @@ impl TaskDescriptor {
143143
144144pub type ProcVM = ProcessVM < <ArchImpl as VirtualMemory >:: ProcessAddressSpace > ;
145145
146+ /// A per-task handle to a process address space.
147+ ///
148+ /// Separate processes may temporarily share the same underlying `ProcVM`
149+ /// (e.g. `CLONE_VM` without `CLONE_THREAD`, including `CLONE_VFORK`) while
150+ /// still allowing one side to detach on `execve()` without affecting the
151+ /// other. Tasks in the same thread group share the same `VmHandle` so that an
152+ /// `execve()` updates the whole group consistently.
153+ pub struct VmHandle {
154+ current : SpinLock < Arc < SpinLock < ProcVM > > > ,
155+ }
156+
157+ impl VmHandle {
158+ pub fn new ( vm : ProcVM ) -> Self {
159+ Self :: from_shared ( Arc :: new ( SpinLock :: new ( vm) ) )
160+ }
161+
162+ pub fn from_shared ( vm : Arc < SpinLock < ProcVM > > ) -> Self {
163+ Self {
164+ current : SpinLock :: new ( vm) ,
165+ }
166+ }
167+
168+ pub fn shared_vm ( & self ) -> Arc < SpinLock < ProcVM > > {
169+ self . current . lock_save_irq ( ) . clone ( )
170+ }
171+
172+ pub fn replace ( & self , vm : ProcVM ) {
173+ self . replace_shared ( Arc :: new ( SpinLock :: new ( vm) ) ) ;
174+ }
175+
176+ pub fn replace_shared ( & self , vm : Arc < SpinLock < ProcVM > > ) {
177+ * self . current . lock_save_irq ( ) = vm;
178+ }
179+
180+ pub fn activate ( & self ) {
181+ self . shared_vm ( )
182+ . lock_save_irq ( )
183+ . mm_mut ( )
184+ . address_space_mut ( )
185+ . activate ( ) ;
186+ }
187+ }
188+
146189#[ derive( Copy , Clone ) ]
147190pub struct Comm ( [ u8 ; 16 ] ) ;
148191
@@ -183,7 +226,7 @@ pub struct Task {
183226 pub tid : Tid ,
184227 pub comm : Arc < SpinLock < Comm > > ,
185228 pub process : Arc < ThreadGroup > ,
186- pub vm : Arc < SpinLock < ProcVM > > ,
229+ pub vm : Arc < VmHandle > ,
187230 pub cwd : Arc < SpinLock < ( Arc < dyn Inode > , PathBuf ) > > ,
188231 pub root : Arc < SpinLock < ( Arc < dyn Inode > , PathBuf ) > > ,
189232 pub creds : SpinLock < Credentials > ,
@@ -276,8 +319,10 @@ impl Task {
276319 Box :: into_pin ( fut) . await ?;
277320 }
278321
322+ let proc_vm = self . vm . shared_vm ( ) ;
323+
279324 {
280- let mut vm = self . vm . lock_save_irq ( ) ;
325+ let mut vm = proc_vm . lock_save_irq ( ) ;
281326
282327 if let Some ( pa) = vm. mm_mut ( ) . address_space_mut ( ) . translate ( va) {
283328 let region = pa. pfn . as_phys_range ( ) ;
@@ -302,7 +347,7 @@ impl Task {
302347 }
303348
304349 // Try to handle the fault.
305- match handle_demand_fault ( self . vm . clone ( ) , va, access_kind) ? {
350+ match handle_demand_fault ( proc_vm . clone ( ) , va, access_kind) ? {
306351 // Resolved the fault. Try again
307352 FaultResolution :: Resolved => continue ,
308353 FaultResolution :: Denied => return Err ( KernelError :: Fault ) ,
0 commit comments