kernel/task/
syscall.rs

1//! Task-related system call implementations.
2//!
3//! This module implements system calls that interact with task management,
4//! filesystem operations, and process control. Many operations leverage
5//! the VfsManager for filesystem access when tasks have isolated namespaces.
6//!
7//! # VfsManager Integration
8//!
9//! System calls automatically use the task's VfsManager when available:
10//! - Tasks with `vfs: Some(Arc<VfsManager>)` use their isolated filesystem namespace
11//! - Tasks with `vfs: None` fall back to global filesystem operations
12//! - Bind mount operations enable controlled sharing between isolated namespaces
13//! - All filesystem operations are thread-safe and handle concurrent access properly
14
15use core::usize;
16
17use alloc::vec::Vec;
18
19use crate::abi::MAX_ABI_LENGTH;
20use crate::device::manager::DeviceManager;
21use crate::executor::executor::TransparentExecutor;
22use crate::fs::MAX_PATH_LENGTH;
23use crate::library::std::string::{
24    parse_c_string_from_userspace, parse_string_array_from_userspace,
25};
26
27use crate::arch::{Trapframe, get_cpu};
28use crate::sched::scheduler::get_scheduler;
29use crate::task::{
30    CloneFlags, CloneFlagsDef, WaitError, get_parent_waitpid_waker, get_waitpid_waker,
31};
32use crate::timer::ns_to_ticks;
33
34const MAX_ARG_COUNT: usize = 256; // Maximum number of arguments for execve
35
36// Flags for execve system calls
37pub const EXECVE_FORCE_ABI_REBUILD: usize = 0x1; // Force ABI environment reconstruction
38
39use super::mytask;
40
41pub fn sys_brk(trapframe: &mut Trapframe) -> usize {
42    let task = mytask().unwrap();
43    let brk = trapframe.get_arg(0);
44    trapframe.increment_pc_next(task);
45    match task.set_brk(brk) {
46        Ok(_) => task.get_brk(),
47        Err(_) => usize::MAX, /* -1 */
48    }
49}
50
51pub fn sys_sbrk(trapframe: &mut Trapframe) -> usize {
52    let task = mytask().unwrap();
53    let increment = trapframe.get_arg(0);
54    let brk = task.get_brk();
55    trapframe.increment_pc_next(task);
56    match task.set_brk(unsafe { brk.unchecked_add(increment) }) {
57        Ok(_) => brk,
58        Err(_) => usize::MAX, /* -1 */
59    }
60}
61
62pub fn sys_putchar(trapframe: &mut Trapframe) -> usize {
63    let c = trapframe.get_arg(0) as u32;
64    let task = mytask().unwrap();
65    trapframe.increment_pc_next(task);
66    if let Some(ch) = char::from_u32(c) {
67        let manager = DeviceManager::get_manager();
68        if let Some(device_id) = manager.get_first_device_by_type(crate::device::DeviceType::Char) {
69            if let Some(char_device) = manager.get_device(device_id).unwrap().as_char_device() {
70                // Use CharDevice trait methods to write
71                if let Err(e) = char_device.write_byte(ch as u8) {
72                    crate::print!("Error writing character: {}", e);
73                    return usize::MAX; // -1
74                }
75                // Successfully written character
76                return 0;
77            }
78        }
79    }
80    return usize::MAX; // -1
81}
82
83pub fn sys_getchar(trapframe: &mut Trapframe) -> usize {
84    let task = mytask().unwrap();
85    trapframe.increment_pc_next(task);
86
87    // Find TTY device for blocking input
88    let manager = DeviceManager::get_manager();
89    if let Some(borrowed_device) = manager.get_device_by_name("tty0") {
90        if let Some(char_device) = borrowed_device.as_char_device() {
91            // Check if data is available
92            if let Some(byte) = char_device.read_byte() {
93                return byte as usize;
94            }
95        }
96    }
97
98    0 // Return 0 if no device found (should not happen)
99}
100
101pub fn sys_exit(trapframe: &mut Trapframe) -> usize {
102    let task = mytask().unwrap();
103    task.vcpu.lock().store(trapframe);
104    let exit_code = trapframe.get_arg(0) as i32;
105    task.exit(exit_code);
106    usize::MAX // -1 (If exit is successful, this will not be reached)
107}
108
109pub fn sys_clone(trapframe: &mut Trapframe) -> usize {
110    let parent_task = mytask().unwrap();
111    trapframe.increment_pc_next(parent_task); /* Increment the program counter */
112    /* Save the trapframe to the task before cloning */
113    parent_task.vcpu.lock().store(trapframe);
114    let clone_flags = CloneFlags::from_raw(trapframe.get_arg(0) as u64);
115    let child_stack = trapframe.get_arg(1); // Second argument: child stack pointer
116    let child_fn = trapframe.get_arg(2); // Third argument: function pointer (trampoline)
117    let child_arg = trapframe.get_arg(3); // Fourth argument: argument to pass to function (closure pointer)
118    let tls_ptr = trapframe.get_arg(4); // Fifth argument: TLS pointer
119
120    // crate::println!("[CLONE] Parent task {} cloning with flags: 0x{:x}", parent_task.get_id(), clone_flags.get_raw());
121
122    /* Clone the task */
123    match parent_task.clone_task(clone_flags) {
124        Ok(mut child_task) => {
125            // crate::println!("[CLONE] Successfully created child task {}, state: {:?}, PC: 0x{:x}",
126            //     child_id, child_task.get_state(), child_task.vcpu.get_pc());
127            child_task.vcpu.lock().iregs.set_return_value(0); /* Set the return value to 0 in the child task */
128
129            // If child_stack is provided, set child's user SP
130            if child_stack != 0 {
131                child_task.vcpu.lock().set_sp(child_stack);
132            }
133
134            // If child_fn is provided, set it as PC (thread entry point)
135            if child_fn != 0 {
136                child_task.vcpu.lock().set_pc(child_fn as u64);
137            }
138
139            // If child_arg is provided, pass it as first argument (a0/x0)
140            if child_arg != 0 {
141                child_task.vcpu.lock().iregs.set_arg(0, child_arg);
142            }
143
144            let scheduler = get_scheduler();
145            let cpu_id = get_cpu().get_cpuid();
146            let parent_id = parent_task.get_id();
147
148            // Handle SetTls flag: set TLS pointer and tp register
149            if clone_flags.is_set(CloneFlagsDef::SetTls) {
150                // Set TLS pointer in task's ABI state
151                // SAFETY: Child task is not yet visible to scheduler
152                unsafe {
153                    if let Some(abi) = child_task.default_abi.get_mut().as_mut() {
154                        abi.set_tls_pointer(tls_ptr);
155                    }
156                }
157
158                // Set TLS pointer using architecture-specific VCPU method
159                child_task.vcpu.lock().set_tls_pointer(tls_ptr);
160            }
161
162            // Add child to scheduler and get the allocated ID
163            let child_id = scheduler.add_task(child_task, cpu_id);
164            // crate::println!("[CLONE] Child task {} added to scheduler", child_id);
165
166            // Establish parent-child relationship now that both have valid IDs
167            if let Some(child) = scheduler.get_task_by_id(child_id) {
168                child.set_parent_id(parent_id);
169            }
170            if let Some(parent) = scheduler.get_task_by_id(parent_id) {
171                parent.add_child(child_id);
172            }
173
174            // Get the child's namespace-local PID (after add_task has set the IDs)
175            let child_ns_pid = scheduler
176                .get_task_by_id(child_id)
177                .map(|t| t.get_namespace_id())
178                .unwrap_or(0);
179
180            /* Return the child task PID (namespace-local) to the parent task */
181            child_ns_pid
182        }
183        Err(_) => {
184            usize::MAX /* Return -1 on error */
185        }
186    }
187}
188
189/// Set the TLS pointer for the current task
190pub fn sys_set_tls(trapframe: &mut Trapframe) -> usize {
191    let task = mytask().unwrap();
192    let tls_ptr = trapframe.get_arg(0);
193
194    // Update ABI state
195    // SAFETY: This is the currently executing task on this hart
196    unsafe {
197        if let Some(abi) = task.default_abi.get_mut().as_mut() {
198            abi.set_tls_pointer(tls_ptr);
199        }
200    }
201
202    // Set TLS pointer using architecture-specific VCPU method
203    task.vcpu.lock().set_tls_pointer(tls_ptr);
204
205    trapframe.increment_pc_next(task);
206    0 // Success
207}
208
209/// Get the TLS pointer for the current task
210pub fn sys_get_tls(trapframe: &mut Trapframe) -> usize {
211    let task = mytask().unwrap();
212
213    // Get TLS pointer from ABI state
214    // SAFETY: This is the currently executing task on this hart
215    let tls_ptr = unsafe {
216        task.default_abi
217            .get()
218            .as_ref()
219            .and_then(|abi| abi.get_tls_pointer())
220            .unwrap_or(0)
221    };
222
223    trapframe.increment_pc_next(task);
224    tls_ptr // Return TLS pointer
225}
226
227/// Set the clear_child_tid pointer for thread exit notification
228pub fn sys_set_tid_address(trapframe: &mut Trapframe) -> usize {
229    let task = mytask().unwrap();
230    let tid_ptr = trapframe.get_arg(0);
231
232    // Update ABI state
233    // SAFETY: This is the currently executing task on this hart
234    unsafe {
235        if let Some(abi) = task.default_abi.get_mut().as_mut() {
236            abi.set_clear_child_tid(tid_ptr);
237        }
238    }
239
240    trapframe.increment_pc_next(task);
241    task.get_namespace_id() // Return current TID (Linux-compatible)
242}
243
244pub fn sys_execve(trapframe: &mut Trapframe) -> usize {
245    let task = mytask().unwrap();
246
247    // crate::println!("[EXECVE] Task {} starting execve", task.get_id());
248
249    // Increment PC to avoid infinite loop if execve fails
250    trapframe.increment_pc_next(task);
251
252    // Get arguments from trapframe
253    let path_ptr = trapframe.get_arg(0);
254    let argv_ptr = trapframe.get_arg(1);
255    let envp_ptr = trapframe.get_arg(2);
256    let flags = trapframe.get_arg(3); // New flags argument
257
258    // Parse path
259    let path_str = match parse_c_string_from_userspace(task, path_ptr, MAX_PATH_LENGTH) {
260        Ok(path) => {
261            // crate::println!("[EXECVE] Task {}: Executing path: {}", task.get_id(), path);
262            path
263        }
264        Err(_) => {
265            // crate::println!("[EXECVE] Task {}: Path parsing error", task.get_id());
266            return usize::MAX; // Path parsing error
267        }
268    };
269
270    // Parse argv and envp
271    let argv_strings =
272        match parse_string_array_from_userspace(task, argv_ptr, MAX_ARG_COUNT, MAX_PATH_LENGTH) {
273            Ok(args) => {
274                // crate::println!("[EXECVE] Task {}: argv count: {}", task.get_id(), args.len());
275                args
276            }
277            Err(_) => {
278                // crate::println!("[EXECVE] Task {}: argv parsing error", task.get_id());
279                return usize::MAX; // argv parsing error
280            }
281        };
282
283    let envp_strings =
284        match parse_string_array_from_userspace(task, envp_ptr, MAX_ARG_COUNT, MAX_PATH_LENGTH) {
285            Ok(env) => {
286                // crate::println!("[EXECVE] Task {}: envp count: {}", task.get_id(), env.len());
287                env
288            }
289            Err(_) => {
290                // crate::println!("[EXECVE] Task {}: envp parsing error", task.get_id());
291                return usize::MAX; // envp parsing error
292            }
293        };
294
295    // Convert Vec<String> to Vec<&str> for TransparentExecutor
296    let argv_refs: Vec<&str> = argv_strings.iter().map(|s| s.as_str()).collect();
297    let envp_refs: Vec<&str> = envp_strings.iter().map(|s| s.as_str()).collect();
298
299    // Check if force ABI rebuild is requested
300    let force_abi_rebuild = (flags & EXECVE_FORCE_ABI_REBUILD) != 0;
301
302    // crate::println!("[EXECVE] Task {}: Starting TransparentExecutor::execute_binary", task.get_id());
303
304    // Use TransparentExecutor for cross-ABI execution
305    match TransparentExecutor::execute_binary(
306        &path_str,
307        &argv_refs,
308        &envp_refs,
309        task,
310        trapframe,
311        force_abi_rebuild,
312    ) {
313        Ok(_) => {
314            // crate::println!("[EXECVE] Task {}: execute_binary succeeded", task.get_id());
315            // execve normally should not return on success - the process is replaced
316            // However, if ABI module sets trapframe return value and returns here,
317            // we should respect that value instead of hardcoding 0
318            trapframe.get_return_value()
319        }
320        Err(e) => {
321            crate::println!(
322                "[EXECVE] Task {}: execute_binary failed for path='{}': {}",
323                task.get_id(),
324                path_str,
325                e
326            );
327            // Execution failed - return error code
328            // The trap handler will automatically set trapframe return value from our return
329            usize::MAX // Error return value
330        }
331    }
332}
333
334pub fn sys_execve_abi(trapframe: &mut Trapframe) -> usize {
335    let task = mytask().unwrap();
336
337    // Increment PC to avoid infinite loop if execve fails
338    trapframe.increment_pc_next(task);
339
340    // Get arguments from trapframe
341    let path_ptr = trapframe.get_arg(0);
342    let argv_ptr = trapframe.get_arg(1);
343    let envp_ptr = trapframe.get_arg(2);
344    let abi_str_ptr = trapframe.get_arg(3);
345    let flags = trapframe.get_arg(4); // New flags argument
346
347    // Parse path
348    let path_str = match parse_c_string_from_userspace(task, path_ptr, MAX_PATH_LENGTH) {
349        Ok(path) => path,
350        Err(_) => return usize::MAX, // Path parsing error
351    };
352
353    // Parse ABI string
354    let abi_str = match parse_c_string_from_userspace(task, abi_str_ptr, MAX_ABI_LENGTH) {
355        Ok(abi) => abi,
356        Err(_) => return usize::MAX, // ABI parsing error
357    };
358
359    // Parse argv and envp
360    let argv_strings = match parse_string_array_from_userspace(task, argv_ptr, 256, MAX_PATH_LENGTH)
361    {
362        Ok(args) => args,
363        Err(_) => return usize::MAX, // argv parsing error
364    };
365
366    let envp_strings = match parse_string_array_from_userspace(task, envp_ptr, 256, MAX_PATH_LENGTH)
367    {
368        Ok(env) => env,
369        Err(_) => return usize::MAX, // envp parsing error
370    };
371
372    // Convert Vec<String> to Vec<&str> for TransparentExecutor
373    let argv_refs: Vec<&str> = argv_strings.iter().map(|s| s.as_str()).collect();
374    let envp_refs: Vec<&str> = envp_strings.iter().map(|s| s.as_str()).collect();
375
376    // Check if force ABI rebuild is requested
377    let force_abi_rebuild = (flags & EXECVE_FORCE_ABI_REBUILD) != 0;
378
379    // Use TransparentExecutor for ABI-aware execution
380    match TransparentExecutor::execute_with_abi(
381        &path_str,
382        &argv_refs,
383        &envp_refs,
384        &abi_str,
385        task,
386        trapframe,
387        force_abi_rebuild,
388    ) {
389        Ok(()) => {
390            // execve normally should not return on success - the process is replaced
391            // However, if ABI module sets trapframe return value and returns here,
392            // we should respect that value instead of hardcoding 0
393            trapframe.get_return_value()
394        }
395        Err(_) => {
396            // Execution failed - return error code
397            // The trap handler will automatically set trapframe return value from our return
398            usize::MAX // Error return value
399        }
400    }
401}
402
403pub fn sys_waitpid(trapframe: &mut Trapframe) -> usize {
404    let task = mytask().unwrap();
405    // pid is namespace-local PID as seen by the calling task.
406    let pid = trapframe.get_arg(0) as i32;
407    let status_ptr = trapframe.get_arg(1) as *mut i32;
408    let options = trapframe.get_arg(2) as i32;
409
410    // WNOHANG flag (0x1): Return immediately if no child has exited
411    let wnohang = (options & 0x1) != 0;
412
413    // Loop until a child exits or an error occurs
414    loop {
415        if pid == -1 {
416            // Wait for any child process
417            for child_pid in task.get_children().clone() {
418                match task.wait(child_pid) {
419                    Ok(status) => {
420                        // Child has exited, return the status
421                        if status_ptr != core::ptr::null_mut() {
422                            let status_ptr = task
423                                .vm_manager
424                                .translate_vaddr(status_ptr as usize)
425                                .unwrap() as *mut i32;
426                            unsafe {
427                                *status_ptr = status;
428                            }
429                        }
430                        trapframe.increment_pc_next(task);
431                        // Return child's PID in caller's namespace (if visible)
432                        if let Some(local) = task.get_namespace().resolve_local_id(child_pid) {
433                            return local;
434                        }
435                        // Not visible in this namespace; keep searching
436                        continue;
437                    }
438                    Err(error) => match error {
439                        WaitError::ChildNotExited(_) => continue,
440                        _ => {
441                            trapframe.increment_pc_next(task);
442                            return usize::MAX;
443                        }
444                    },
445                }
446            }
447
448            // No child has exited yet
449            if wnohang {
450                // WNOHANG: Return immediately without blocking
451                trapframe.increment_pc_next(task);
452                return 0; // Return 0 to indicate no child has exited
453            }
454
455            // Block until a child exits
456            let parent_waker = get_parent_waitpid_waker(task.get_id());
457            parent_waker.wait(task.get_id(), trapframe);
458            // Continue the loop to re-check after waking up
459            continue;
460        }
461
462        // Wait for specific child process
463        if pid <= 0 {
464            trapframe.increment_pc_next(task);
465            return usize::MAX;
466        }
467
468        let target_global = match task.get_namespace().resolve_global_id(pid as usize) {
469            Some(g) => g,
470            None => {
471                trapframe.increment_pc_next(task);
472                return usize::MAX;
473            }
474        };
475
476        match task.wait(target_global) {
477            Ok(status) => {
478                // Child has exited, return the status
479                if status_ptr != core::ptr::null_mut() {
480                    let status_ptr = task
481                        .vm_manager
482                        .translate_vaddr(status_ptr as usize)
483                        .unwrap() as *mut i32;
484                    unsafe {
485                        *status_ptr = status;
486                    }
487                }
488                trapframe.increment_pc_next(task);
489                return pid as usize;
490            }
491            Err(error) => {
492                match error {
493                    WaitError::NoSuchChild(_) => {
494                        trapframe.increment_pc_next(task);
495                        return usize::MAX;
496                    }
497                    WaitError::ChildTaskNotFound(_) => {
498                        trapframe.increment_pc_next(task);
499                        crate::print!("Child task with PID {} not found", pid);
500                        return usize::MAX;
501                    }
502                    WaitError::ChildNotExited(_) => {
503                        // Child has not exited yet
504                        if wnohang {
505                            // WNOHANG: Return immediately without blocking
506                            trapframe.increment_pc_next(task);
507                            return 0; // Return 0 to indicate child has not exited
508                        }
509
510                        // Block until child exits
511                        let child_waker = get_waitpid_waker(target_global);
512                        child_waker.wait(task.get_id(), trapframe);
513                        assert_eq!(mytask().unwrap().get_id(), task.get_id());
514                        // Continue the loop to re-check after waking up
515                        continue;
516                    }
517                }
518            }
519        }
520    }
521}
522
523pub fn sys_getpid(trapframe: &mut Trapframe) -> usize {
524    let task = mytask().unwrap();
525    trapframe.increment_pc_next(task);
526    // Expose namespace-local task ID to user space.
527    // This allows task namespaces (PID namespaces) to provide independent PID spaces.
528    task.get_namespace_id() as usize
529}
530
531pub fn sys_getppid(trapframe: &mut Trapframe) -> usize {
532    let task = mytask().unwrap();
533    trapframe.increment_pc_next(task);
534    // Return parent's PID as seen from the caller's namespace.
535    // If the parent is not mapped/visible in this namespace, return 0.
536    match task.get_parent_id() {
537        Some(parent_global) => task
538            .get_namespace()
539            .resolve_local_id(parent_global)
540            .unwrap_or(0),
541        None => 0,
542    }
543}
544
545pub fn sys_sleep(trapframe: &mut Trapframe) -> usize {
546    let nanosecs = trapframe.get_arg(0) as u64;
547    let task = mytask().unwrap();
548
549    let ticks = ns_to_ticks(nanosecs);
550
551    // Increment PC before sleeping to avoid infinite loop
552    trapframe.increment_pc_next(task);
553
554    // Call the blocking sleep method - this will return when sleep completes
555    task.sleep(trapframe, ticks);
556
557    // Set return value to 0 for successful sleep
558    0
559}
560
561/// Yield execution to the scheduler
562///
563/// This is a cooperative scheduling primitive similar to `sched_yield(2)`.
564/// The calling task remains runnable, but allows another ready task to run.
565///
566/// # Returns
567/// * `0` on success
568pub fn sys_yield(trapframe: &mut Trapframe) -> usize {
569    let task = mytask().unwrap();
570
571    // Increment PC before yielding to avoid re-executing the syscall on resume
572    trapframe.increment_pc_next(task);
573
574    // Yield CPU to scheduler - returns when this task is scheduled again
575    get_scheduler().schedule(trapframe);
576
577    0
578}
579
580/// Exit all tasks in the thread group
581///
582/// This system call terminates all tasks with the same TGID (thread group).
583/// It is similar to Linux's exit_group system call and is the proper way
584/// for multi-threaded processes to exit.
585///
586/// # Arguments
587/// * `trapframe.arg(0)` - Exit status code
588///
589/// # Returns
590/// This function does not return on success (all tasks are terminated).
591/// Returns `usize::MAX` (-1) on error.
592///
593/// # Behavior
594/// - Terminates all tasks with the same TGID as the caller
595/// - The calling task is set to Zombie/Terminated
596/// - Other tasks in the group are forcefully terminated
597pub fn sys_exit_group(trapframe: &mut Trapframe) -> usize {
598    let task = mytask().unwrap();
599    task.vcpu.lock().store(trapframe);
600    let exit_code = trapframe.get_arg(0) as i32;
601    task.exit_group(exit_code);
602    usize::MAX // -1 (If exit_group is successful, this will not be reached)
603}
604
605/// Register an ABI zone for a specific memory range
606///
607/// # Arguments
608/// * `start` - Start address of the memory range
609/// * `len` - Length of the memory range in bytes
610/// * `abi_name_ptr` - Pointer to null-terminated ABI name string in user space
611///
612/// # Returns
613/// * `0` on success
614/// * `usize::MAX` (-1) on failure
615pub fn sys_register_abi_zone(trapframe: &mut Trapframe) -> usize {
616    let task = mytask().unwrap();
617    let start = trapframe.get_arg(0);
618    let len = trapframe.get_arg(1);
619    let abi_name_ptr = trapframe.get_arg(2);
620
621    trapframe.increment_pc_next(task);
622
623    // Parse the ABI name from user space
624    let abi_name = match parse_c_string_from_userspace(task, abi_name_ptr, MAX_ABI_LENGTH) {
625        Ok(name) => name,
626        Err(_) => {
627            crate::early_println!("[syscall] Failed to parse ABI name from user space");
628            return usize::MAX; // -1
629        }
630    };
631
632    crate::early_println!(
633        "[syscall] Registering ABI zone: start={:#x}, len={:#x}, abi={}",
634        start,
635        len,
636        abi_name
637    );
638
639    // Instantiate the ABI module
640    let abi = match crate::abi::AbiRegistry::instantiate(&abi_name) {
641        Some(abi) => abi,
642        None => {
643            crate::early_println!("[syscall] ABI '{}' not found in registry", abi_name);
644            return usize::MAX; // -1
645        }
646    };
647
648    // Create the ABI zone
649    let zone = crate::task::AbiZone {
650        range: start..(start + len),
651        abi,
652    };
653
654    // Insert into the task's ABI zones map
655    // SAFETY: This is the currently executing task on this hart
656    unsafe {
657        task.abi_zones.get_mut().insert(start, zone);
658    }
659
660    crate::early_println!("[syscall] Successfully registered ABI zone");
661    0
662}
663
664/// Unregister an ABI zone
665///
666/// # Arguments
667/// * `start` - Start address of the memory range to unregister
668///
669/// # Returns
670/// * `0` on success
671/// * `usize::MAX` (-1) on failure (zone not found)
672pub fn sys_unregister_abi_zone(trapframe: &mut Trapframe) -> usize {
673    let task = mytask().unwrap();
674    let start = trapframe.get_arg(0);
675
676    trapframe.increment_pc_next(task);
677
678    crate::early_println!("[syscall] Unregistering ABI zone at start={:#x}", start);
679
680    // Remove the ABI zone from the map
681    // SAFETY: This is the currently executing task on this hart
682    let result = unsafe { task.abi_zones.get_mut().remove(&start) };
683    match result {
684        Some(_) => {
685            crate::early_println!("[syscall] Successfully unregistered ABI zone");
686            0
687        }
688        None => {
689            crate::early_println!("[syscall] ABI zone not found at start={:#x}", start);
690            usize::MAX // -1
691        }
692    }
693}
694
695// Namespace creation flags (bit flags for smart control)
696pub const NS_CREATE_TASK: usize = 0x01; // Create separate task namespace
697pub const NS_CREATE_VFS: usize = 0x02; // Create separate VFS namespace
698pub const NS_CREATE_NET: usize = 0x04; // Create separate network namespace (future)
699pub const NS_CREATE_IPC: usize = 0x08; // Create separate IPC namespace (future)
700
701// Syscall error return value
702const SYSCALL_ERROR: usize = usize::MAX;
703
704/// Create a new namespace for the current task (Scarlet-style smart syscall)
705///
706/// # Arguments
707/// * `flags` - Bitfield specifying which namespaces to create (NS_CREATE_*)
708/// * `name_ptr` - Pointer to C string with namespace name (optional, can be null)
709///
710/// # Returns
711/// * `0` on success
712/// * `SYSCALL_ERROR` (-1) on failure
713///
714/// # Example
715/// ```rust
716/// // Create separate task and VFS namespaces
717/// sys_create_namespace(NS_CREATE_TASK | NS_CREATE_VFS, "container1");
718/// ```
719pub fn sys_create_namespace(trapframe: &mut Trapframe) -> usize {
720    use crate::fs::VfsManager;
721    use crate::task::namespace::TaskNamespace;
722
723    let task = mytask().unwrap();
724    let flags = trapframe.get_arg(0);
725    let name_ptr = trapframe.get_arg(1);
726
727    trapframe.increment_pc_next(task);
728
729    // Parse namespace name (optional)
730    let name = if name_ptr == 0 {
731        alloc::format!("ns_{}", task.get_id())
732    } else {
733        match parse_c_string_from_userspace(task, name_ptr, 64) {
734            Ok(s) => s,
735            Err(_) => {
736                crate::early_println!("[syscall] Failed to parse namespace name");
737                return SYSCALL_ERROR;
738            }
739        }
740    };
741
742    crate::early_println!(
743        "[syscall] Creating namespace '{}' with flags={:#x}",
744        name,
745        flags
746    );
747
748    // Create task namespace if requested
749    if flags & NS_CREATE_TASK != 0 {
750        let new_task_ns = TaskNamespace::new_child(task.get_namespace().clone(), name.clone());
751        task.set_namespace(new_task_ns);
752        crate::early_println!("[syscall] Created task namespace '{}'", name);
753    }
754
755    // Create VFS namespace if requested
756    if flags & NS_CREATE_VFS != 0 {
757        // Deep-clone the current mount topology so the initial view is the same,
758        // but future mount operations are isolated.
759        let source_vfs = match task.get_vfs() {
760            Some(vfs) => vfs,
761            None => return SYSCALL_ERROR,
762        };
763
764        let new_vfs = match VfsManager::clone_mount_namespace_deep(&source_vfs) {
765            Ok(vfs) => vfs,
766            Err(e) => {
767                crate::early_println!(
768                    "[syscall] Failed to clone VFS namespace '{}': {}",
769                    name,
770                    e.message
771                );
772                return SYSCALL_ERROR;
773            }
774        };
775
776        // Preserve current working directory when possible.
777        let cwd_path = source_vfs.get_cwd_path();
778        let _ = new_vfs.set_cwd_by_path(&cwd_path);
779
780        task.set_vfs(new_vfs);
781        crate::early_println!("[syscall] Created VFS namespace '{}'", name);
782    }
783
784    // Future: Network namespace
785    if flags & NS_CREATE_NET != 0 {
786        crate::early_println!("[syscall] Network namespace not yet implemented");
787    }
788
789    // Future: IPC namespace
790    if flags & NS_CREATE_IPC != 0 {
791        crate::early_println!("[syscall] IPC namespace not yet implemented");
792    }
793
794    0
795}