Chapter 2: Process Management and Scheduling
parent. However, the semantics are opposite to all other flags: IfCLONE_NEWxyzisnotspecified,
then the specific namespace is shared with the parent. Otherwise, a new namespace is generated.
copy_namespaceis a dispatcher that executes a copy routine for each possible namespace. The
individual copy routines, however, are not too interesting because they essentially copy data or
make already existing instances shared by meansof reference counter management, so I will not
discuss their implementation in detail.
❑ copy_threadis — in contrast to all othercopyoperations discussed here — an architecture-
specific function that copies the thread-specific data of a process.
Thread-specificin this context does not refer to any of theCLONEflags or to the fact
that the operation is performed for threads only and not for full processes. It simply
means that all data that contribute to the architecture-specific execution context are
copied (the termthreadis used with more than one meaning in the kernel).
What is important is to fill the elements oftask_struct->thread.Thisisastructureofthe
thread_structtype whose definition is architecture-dependent. It holds all registers (plus other
information) needed by the kernel to save and restore process contents during low-level switch-
ing between tasks.
Intimate knowledge of the various CPUs is needed to understand the layout of the individual
thread_structstructures. A full discussion of these structures is beyond the scope of this book.
However, Appendix A includes some information relating to the contents of the structures on
several systems.
Back incopy_process, the kernel must fill in various elements of the task structure that differ between
parent and child. These include the following:
❑ The various list elements contained intask_struct, for instance,siblingandchildren.
❑ The interval timer elementscpu_timers(see Chapter 15).
❑ The list of pending signals (pending) discussed in Chapter 5.
After allocating a newpidinstance for the task with the mechanisms described before, they are stored in
the task structure. For threads, the thread group ID is the same as that of the forking process:
kernel/fork.c
p->pid = pid_nr(pid);
p->tgid = p->pid;
if (clone_flags & CLONE_THREAD)
p->tgid = current->tgid;
...
Recall thatpid_nrcomputes the global numerical PID for a givenpidinstance.
For regular processes, the parent process is the forking process. This is different for threads: Since they
are seen as the second (or third, or fourth,...) line of executionwithinthe generating process, their parent
is the parent’s parent. This is easier to express in code than in words:
kernel/fork.c
if (clone_flags & (CLONE_PARENT|CLONE_THREAD))
p->real_parent = current->real_parent;
else