1
votes

I have some doubt regarding system call in Linux on ARM processor.

In ARM system calls are handled in SWI mode. My doubt is do we perform entire required work in SWI mode or only part of that work is done in SWI mode and then we move to some process context? As per my understanding some system calls can take significant time and performing that work in SWI is not a good idea.

Also how do we return to calling user process? I mean in case of non-blocking system call how do we notify the user that required task is completed by system call?

1
At least the final link gives the answer that Linux always switches to supervisor mode. Here, the active task has a kernel stack and thread_info anchored by the r13/sp register. On a context switch, all register atomically update (to CPU) via ldm. For the Linux kernel, the SWI is already in supervisor mode and the code is in entry-common.Sartless noise
Thanks for your reply. My doubt is do we handle system call in some process context or it is in SVC context? Also please let me know how do we return to calling function of user process once system call is finished?user2806748
The swi in the user process causes an exception. During all exception, Linux saves context on the supervisor mode stack. A context switch may result in which case, the supervisor stack changes. The new supervisor stack has the new user space registers saved upon it. Also anchored in the supervisor stack is a thread_info which provides MM (memory management) info to update the MMU. This is answered in the other questions, if you read them.artless noise

1 Answers

1
votes

I think you're missing two concepts.

  1. CPU privilege modes and use of swi are both an implementation detail of system calls
  2. Non-blocking system calls don't work that way

Sure, under Linux, we use swi instructions and maintain privilege separation to implement system calls, but this doesn't reflect ARM systems in general. When you talk about Linux specifically, I think it makes more sense to refer to concepts like kernel vs user mode.

The Linux kernel have been preemptive for a long time now. If your system call is taking too long and exceeds the time quantum allocated to that process/thread, the scheduler will just kick in and do a context switch. Likewise, if your system call just consists of waiting for an event (like for I/O), it'll just get switched out until there's data available.

Taking this into account you don't usually have to worry about whether your system call takes too long. However, if you're spending a significant amount of time in a system call that's doing something that isn't waiting for some event, chances are that you're doing something in the kernel that should be done in user mode.

When the function handling the system call returns a value, it usually goes back to some sort of glue logic which restores the user context and allows the original user mode program to keep running.

Non-blocking system calls are something almost completely different. The system call handling function usually will check if it can return data at that very instant without waiting. If it can, it'll return whatever is available. It can also tell the user "I don't have any data at the moment but check back later" or "that's all, there's no more data to be read". The idea is they return basically instantly and don't block.

Finally, on your last question, I suspect you're missing the point of a system call.

You should never have to know when a task is 'completed' by a system call. If a system call doesn't return an error, you, as the process have to assume it succeeded. The rest is in the implementation details of the kernel. In the case of non-blocking system calls, they will tell you what to expect.

If you can provide an example for the last question, I may be able to explain in more detail.