[FreeBSD] System Calls

2024. 7. 10. 18:06ComputerScience/FreeBSD

 

 

 

3.2 System Calls

The most frequent trap into the kernel (after clock processing) is a request to do a system call. System performance requires that the kernel minimize the overhead in fielding and dispatching a system call.
The system-call handler must do the following work:

  • Verify that the parameters to the system call are located at a valid user address, and copy them from the user’s address space into the kernel
  • Call a kernel routine that implements the system call

 

 

 

https://eastrivervillage.com/Anatomy-of-Linux-system-call-in-ARM64/

 

 

 

Result Handling

Eventually, the system call returns to the calling process, either successfully or unsuccessfully. On the PC architecture, success or failure is returned as the carry bit in the user process’s program status longword: If it is zero, the return was successful; otherwise, it was unsuccessful.

 

On many machines, return values of C functions are passed back through a general-purpose register (for the PC, data register EAX). The routines in the kernel that implement system calls return the values that are normally associated with the global variable errnoAfter a system call, the kernel system-call handler leaves this value in the register. If the system call failed, a C library routine moves that value into errno, and sets the return register to -1. The calling process

is expected to notice the value of the return register, and then to examine errno. The mechanism involving the carry bit and the global variable errno exists for historical reasons derived from the PDP-11.

 

There are two kinds of unsuccessful returns from a system call: those where kernel routines discover an error and those where a system call is interrupted. The most common case is a system call that is interrupted when it has relinquished the processor to wait for an event that may not occur for a long time (such as terminal input), and a signal arrives in the interim. When signal handlers are initialized by a process, they specify whether system calls that they interrupt should be restarted or whether the system call should return with an interrupted system call (EINTR) error.

 

When a system call is interrupted, the signal is delivered to the process. If the process has requested that the signal abort the system call, the handler then returns an error, as described previously. If the system call is to be restarted, however, the handler resets the process’s program counter to the machine instruction that caused the system-call trap into the kernel. (This calculation is necessary because the program-counter value that was saved when the system-call trap was done is for the instruction after the trap-causing instruction.) The handler replaces the saved program-counter value with this address. When the process returns from the signal handler, it resumes at the program-counter value that the handler provided and reexecutes the same system call.

 

Restarting a system call by resetting the program counter has certain implications. (오오?)

First, the kernel must not modify any of the input parameters in the process address space (it can modify the kernel copy of the parameters that it makes).  

Second, it must ensure that the system call has not performed any actions that cannot be repeated. For example, in the current system, if any characters have been read from the terminal, the read must return with a short count. Otherwise, if the call were to be restarted, the already-read bytes would be lost.

 

 

 

Returning from a System Call

While the system call is running or sleeping with signals blocked, a signal may be posted to the process, or another process may attain a higher scheduling priority. After the system call completes, the system-call exit code checks to see whether either event has occurred. 

 

The system-call exit code first checks for a posted signal. Such signals include signals that interrupted the system call, as well as signals that arrived while a system call was in progress but were held pending until the system call completed. Signals that are ignored, by default or by explicit programmatic request, are never posted to the process. Signals with a default action have that action taken before the process runs again (i.e., the process may be stopped or terminated as appropriate). If a signal is to be caught (and is not currently blocked), the system-call exit code arranges to have the appropriate signal handler called rather than have the process return directly from the system call. After the signal handler returns, the process will resume execution at system-call return (or system-call execution, if the system call is being restarted).

 

After checking for posted signals, the system-call exit code checks to see whether any process has a priority higher than that of the currently running one. If such a process exists, the system-call exit code calls the context-switch routine to cause the higher-priority process to run. At a later time, the current process will again have the highest priority and will resume execution by returning from the system call to the user process.

 

If a process has requested that the system do profiling, the system-call exit code also calculates the amount of time that has been spent in the system call - that is, the system time accounted to the process between the latter’s entry into and exit from the kernel. This time is charged to the routine in the user’s process that made the system call.