\chapter{Threads and Tasks} The \texttt{task} server will provide the ability to create tasks and threads, and to destroy them. \begin{comment} In L4, only threads in the privileged address space (the rootserver) are allowed to manipulate threads and address spaces (using the \textsc{ThreadControl} and \textsc{SpaceControl} system calls). The \texttt{task} server will use the system call wrappers provided by the rootserver, see section \ref{rootserver} on page \pageref{rootserver}. \end{comment} The \texttt{task} server provides three different capability types. \paragraph{Task control capabilities} If a new task is created, it is always associated with a task control capability. The task control capability can be used to create and destroy threads in the task, and destroy the task itself. So the task control capability gives the owner of a task control over it. Task control capabilities have the side effect that the task ID of this task is not reused, as long as the task control capability is not released. Thus, having a task control capability affects the global namespace of task IDs. If a task is destroyed, task death notifications are sent to holders of task control capabilities for that task. \begin{comment} A task is also implicitely destroyed when the last task control capability reference is released. \end{comment} \paragraph{Task info capabilities} \label{taskinfocap} Any task can create task info capabilities for other tasks. Such task info capabilities are used mainly in the IPC system (see section \ref{ipc} on page \pageref{ipc}). Task info capabilities have the side effect that the task ID of this task is not reused, as long as the task info capability is not released. Thus, having a task info capability affects the global namespace of task IDs. If a task is destroyed, task death notifications are sent to holders of task info capabilities for that task. \begin{comment} Because of that, holding task info capabilities must be restricted somehow. Several strategies can be taken: \begin{itemize} \item Task death notifications can be monitored. If there is no acknowdgement within a certain time period, the \texttt{task} server could be allowed to reuse the task ID anyway. This is not a good strategy because it can considerably weaken the security of the system (capabilities might be leaked to tasks which reuse such a task ID reclaimed by force). \item The proc server can show dead task IDs which are not released yet, in analogy to the zombie processes in Unix. It can also make available the list of tasks which prevent reusing the task ID, to allow users or the system administrator to clean up manually. \item Quotas can be used to punish users which do not acknowledge task death timely. For example, if the number of tasks the user is allowed to create is restricted, the task info caps that the user holds for dead tasks could be counted toward that limit. \item Any task could be restricted to as many task ID references as there are live tasks in the system, plus some slack. That would prevent the task from creating new task info caps if it does not release old ones from death tasks. The slack would be provided to not unnecessarily slow down a task that processes task death notifications asynchronously to making connections with new tasks. \end{itemize} In particular the last two approaches should proof to be effective in providing an incentive for tasks to release task info caps they do not need anymore. \end{comment} \paragraph{Task manager capability} A task is a relatively simple object, compared to a full blown POSIX process, for example. As the \texttt{task} server is enforced system code, the Hurd does not impose POSIX process semantics in the task server. Instead, POSIX process semantics are implemented in a different server, the proc server (see also section \ref{proc} on page \pageref{proc}). To allow the \texttt{proc} server to do its work, it needs to be able to get the task control capability for any task, and gather other statistics about them. Furthermore, there must be the possibility to install quota mechanisms and other monitoring systems. The \texttt{task} server provides a task manager capability, that allows the holder of that capability to control the behaviour of the \texttt{task} server and get access to the information and objects it provides. \begin{comment} For example, the task manager capability could be used to install a policy capability that is used by the \texttt{task} server to make upcalls to a policy server whenever a new task or thread is created. The policy server could then indicate if the creation of the task or thread is allowed by that user. For this to work, the \texttt{task} server itself does not need to know about the concept of a user, or the policies that the policy server implements. Now that I am writing this, I realize that without any further support by the \texttt{task} server, the policy server would be restricted to the task and thread ID of the caller (or rather the task control capability used) to make its decision. A more capability oriented approach would then not be possible. This requires more thought. The whole task manager interface is not written yet. \end{comment} When creating a new task, the \texttt{task} server allocates a new task ID for it. The task ID will be used as the version field of the thread ID of all threads created in the task. This allows the recipient of a message to verify the sender's task ID efficiently and easily. \begin{comment} The version field is 14 bit on 32-bit architectures, and 32 bit on 64 bit architectures. Because the lower six bits must not be all zero (to make global thread IDs different from local thread IDs), the number of available task IDs is $2^{14} - 2^6$ resp. $2^{32} - 2^6$. If several systems are running in parallel on the same host, they might share thread IDs by encoding the system ID in the upper bits of the thread number. \end{comment} Task IDs will be reused only if there are no task control or info capabilities for that task ID held by any task in the system. To support bootstrapping an IPC connection (see section \ref{ipcbootstrap} on page \pageref{ipcbootstrap}), the \texttt{task} server will delay reusing a task ID as long as possible. \begin{comment} This is similar to how PIDs are generated in Unix. Although it is attempted to keep PIDs small for ease of use, PIDs are not reused immediately. Instead, the PID is incremented up to a certain maximum number, and only then smaller PID values are reused again. As task IDs are not a user interface, there is no need to keep them small. The whole available range can be used to delay reusing a task ID as long as possible. \end{comment} When creating a new task, the \texttt{task} server also has to create the initial thread. This thread will be inactive. Once the creation and activation of the initial thread has been requested by the user, it will be activated. When the user requests to destroy the last thread in a task, the \texttt{task} server makes that thread inactive again. \begin{comment} In L4, an address space can only be implicitely created (resp. destroyed) with the first (resp. last) thread in that address space. \end{comment} Some operations, like starting and stopping threads in a task, can not be supported by the task server, but have to be implemented locally in each task because of the minimality of L4. If external control over the threads in a task at this level is required, the debugger interface might be used (see section \ref{debug} on page \pageref{debug}). \section{Accounting} We want to allow the users of the system to use the \texttt{task} server directly, and ignore other task management facilities like the \texttt{proc} server. However, the system administrator still needs to be able to identify the user who created such anonymous tasks. For this, a simple accounting mechanism is provided by the task server. An identifier can be set for a task by the task manager capability, which is inherited at task creation time from the parent task. This accounting ID can not be changed without the task manager capability. The \texttt{proc} server sets the accounting ID to the process ID (PID) of the task whenever a task registers itself with the \texttt{proc} server. This means that all tasks which do not register themself with the \texttt{proc} server will be grouped together with the first parent task that did. This allows to easily kill all unregistered tasks together with its registered parent. The \texttt{task} server does not interpret or use the accounting ID in any way. \section{Proxy Task Server} \label{proxytaskserver} The \texttt{task} server can be safely proxied, and the users of such a proxy task server can use it like the real \texttt{task} server, even though capabilities work a bit differently for the \texttt{task} server than for other servers. The problem exists because the proxy task server would hold the real task info capabilities for the task info capabilities that it provides to the proxied task. So if the proxy task server dies, all such task info capabilities would be released, and the tasks using the proxy task server would become insecure and open to attacks by imposters. However, this is not really a problem, because the proxy task server will also provide proxy objects for all task control capabilities. So it will be the only task which holds task control capabilities for the tasks that use it. When the proxy task server dies, all tasks that were created with it will be destroyed when these tak control capabilities are released. The proxy task server is a vital system component for the tasks that use it, just as the real \texttt{task} server is a vital system component for the whole system. \section{Scheduling} The task server is the natural place to implement a simple, initial scheduler for the Hurd. A first version can at least collect some information about the cpu time of a task and its threads. Later a proper scheduler has to be written that also has SMP support. The scheduler should run at a higher priority than normal threads. \begin{comment} This might require that the whole task server must run at a higher priority, which makes sense anyway. Not much thought has been given to the scheduler so far. This is work that still needs to be done. \end{comment} There is no way to get at the ``system time'' in L4, it is assumed that no time is spent in the kernel (which is mostly true). So system time will always be reported as $0.00$, or $0.01$.