TSysCall

#include <lib/debug.h>
#include <lib/pmap.h>
#include <lib/types.h>
#include <lib/x86.h>
#include <lib/trap.h>
#include <lib/syscall.h>
#include "import.h"
  • <lib/debug.h>: Provides debugging macros like KERN_INFO for logging kernel information.

  • <lib/pmap.h>: Includes page management and memory mapping utilities.

  • <lib/types.h>: Defines standard types like uint8_t, unsigned int, etc.

  • <lib/x86.h>: Contains architecture-specific macros and utilities for x86.

  • <lib/trap.h>: Defines structures and utilities for trap handling.

  • <lib/syscall.h>: Declares syscall numbers and related utilities.

  • "import.h": Includes project-specific imports like kernel constants and utilities.


sys_puts

Purpose

Prints a string from user space to the kernel log. This is invoked by the user-level printf as a system call.

Code Analysis

void sys_puts(void)
{
    unsigned int cur_pid;
    unsigned int str_uva, str_len;
    unsigned int remain, cur_pos, nbytes;

    cur_pid = get_curid();
    str_uva = syscall_get_arg2();
    str_len = syscall_get_arg3();
  • get_curid(): Fetches the current process ID.

  • syscall_get_arg2() and syscall_get_arg3(): Retrieve string address and length passed by the user process.

    if (!(VM_USERLO <= str_uva && str_uva + str_len <= VM_USERHI)) {
        syscall_set_errno(E_INVAL_ADDR);
        return;
    }
  • Validates if the string lies within the allowed user virtual address space.

  • E_INVAL_ADDR: Error code for invalid address.

    remain = str_len;
    cur_pos = str_uva;

    while (remain) {
        if (remain < PAGESIZE - 1)
            nbytes = remain;
        else
            nbytes = PAGESIZE - 1;

        if (pt_copyin(cur_pid, cur_pos, sys_buf[cur_pid], nbytes) != nbytes) {
            syscall_set_errno(E_MEM);
            return;
        }

        sys_buf[cur_pid][nbytes] = '\0';
        KERN_INFO("%s", sys_buf[cur_pid]);

        remain -= nbytes;
        cur_pos += nbytes;
    }

    syscall_set_errno(E_SUCC);
}
  • Purpose: Copies the string from user space in chunks of PAGESIZE to sys_buf, ensuring safe access.

  • Logging: Uses KERN_INFO to print the string.

  • Error Handling: Returns E_MEM if memory copy fails.


sys_spawn

Purpose

Creates a new child process using a predefined ELF binary in memory. Statically loads the binary and allocates resources.

Code Analysis

void sys_spawn(void)
{
    unsigned int current_pid = get_curid();
    unsigned int elf_id = syscall_get_arg2();
    unsigned int quota = syscall_get_arg3();
    unsigned int new_pid = NUM_IDS;
    void *elf_addr = NULL;
  • syscall_get_arg2() and syscall_get_arg3(): Fetch ELF identifier and quota.

    if (elf_id > 3 || elf_id < 1) {
        syscall_set_errno(E_INVAL_PID);
        syscall_set_retval1(NUM_IDS);
        return;
    }
  • Ensures valid ELF ID (1-3). Returns E_INVAL_PID for invalid IDs.

    if (elf_id == 1)
        elf_addr = (void *)_binary___obj_user_pingpong_ping_start;
    else if (elf_id == 2)
        elf_addr = (void *)_binary___obj_user_pingpong_pong_start;
    else if (elf_id == 3)
        elf_addr = (void *)_binary___obj_user_pingpong_ding_start;
  • Maps elf_id to predefined ELF binaries.

    new_pid = proc_create(elf_addr, quota);

    if (new_pid == NUM_IDS) {
        syscall_set_errno(E_MEM);
    } else {
        syscall_set_errno(E_SUCC);
    }

    syscall_set_retval1(new_pid);
}
  • proc_create(): Creates a new process with the ELF binary.

  • Error Handling: Returns E_MEM if process creation fails.

  • Use Case: Spawn predefined processes for specific user-level functionality.


sys_yield

Purpose

Allows a process to voluntarily yield the CPU to another process.

Code Analysis

void sys_yield(void)
{
    thread_yield();
    syscall_set_errno(E_SUCC);
}
  • thread_yield(): Forces the current thread to yield CPU control.

  • Error Handling: Always succeeds (E_SUCC).


sys_fork

Purpose

Creates a new child process by duplicating the address space of the current process. Uses a predefined ELF binary for the test.

Code Analysis

void sys_fork()
{
    unsigned int cur_pid = get_curid();
    unsigned int new_pid = proc_create((void *)_binary___obj_user_fork_test_fork_test_start, 0);
  • proc_create(): Spawns a new process with the predefined ELF binary for fork_test.

    if (new_pid == NUM_IDS) {
        syscall_set_errno(E_MEM);
    } else {
        syscall_set_errno(E_SUCC);
        syscall_set_retval1(new_pid);
    }
}
  • Returns the child process ID on success or NUM_IDS with an error code (E_MEM) on failure.


Summary of Use Cases

  1. sys_puts: Enables user processes to log messages.

  2. sys_spawn: Creates predefined child processes for applications like ping, pong, or ding.

  3. sys_yield: Facilitates cooperative multitasking.

  4. sys_fork: Implements process duplication for testing and multitasking.

Each function ensures robust error handling and complies with syscall conventions in mCertiKOS. If you need more specific details or formatting, let me know!

Last updated