If a local thread is attempted to be 'pause'd via cpu_session, don't wait
until it gets into the recalled state. If the caller is lucky it is, if not
return only the stack pointer.
Avoids deadlocking of the gdb when attached to a process running a server.
Issue #478
This patch introduces new types for expressing CPU affinities. Instead
of dealing with physical CPU numbers, affinities are expressed as
rectangles in a grid of virtual CPU nodes. This clears the way to
conveniently assign sets of adjacent CPUs to subsystems, each of them
managing their respective viewport of the coordinate space.
By using 2D Cartesian coordinates, the locality of CPU nodes can be
modeled for different topologies such as SMP (simple Nx1 grid), grids of
NUMA nodes, or ring topologies.
The new core-internal 'Address_space' interface enables cores RM service
to flush mappings of a PD in which a given 'Rm_client' thread resides.
Prior this patch, each platform invented their own way to flush mappings
in the respective 'rm_session_support.cc' implementation. However, those
implementations used to deal poorly with some corner cases. In
particular, if a PD session was destroyed prior a RM session, the RM
session would try to use no longer existing PD session. The new
'Address_space' uses the just added weak-pointer mechanism to deal with
this issue.
Furthermore, the generic 'Rm_session_component::detach' function has
been improved to avoid duplicated unmap operations for platforms that
implement the 'Address_space' interface. Therefore, it is related to
issue #595. Right now, this is OKL4 only, but other platforms will follow.
This patch introduces the functions 'affinity' and 'num_cpus' to the CPU
session interface. The interface extension will allow the assignment of
individual threads to CPUs. At this point, it is just a stub with no
actual platform support.
The cpu_session interface fails to be virtualized by gdb_monitor because
platform-nova uses an extended nova_cpu_session interface.
The problem was that threads have been created directly at core without
knowledge of gdb_monitor. This lead to the situation that gdb_monitor didn't
know of all threads to be debugged.
Tunnel the additional parameters required on base-nova through the state()
call of the cpu_session interface before the thread actual is started.
The kernel provides a "recall" feature issued on threads to force a thread into
an exception. In the exception the current state of the thread can be obtained
and its execution can be halted/paused.
However, the recall exception is only delivered when the next time the thread
would leave the kernel. That means the delivery is asynchronous and Genode has
to wait until the exception triggered.
Waiting for the exception can either be done in the cpu_session service or
outside the service in the protection domain of the caller.
It turned out that waiting inside the cpu_service is prone to deadlock the
system. The cpu_session interface is one of many session interfaces handled by
the same thread inside Core.
Deadlock situation:
* The caller (thread_c) to pause some thread_p manages to establish the call
to the cpu_session thread_s of Core but get be interrupted before issuing
the actual pause (recall) command.
* Now the - to be recalled thread_p - is scheduled and tries to invoke another
service of Core, like making log output.
* Since the Core thread_s is handling the session request of thread_c, the
kernel uses the timeslice of thread_p to help to finish the request handled
by thread_s.
* Thread_s issues the actual pause/recall on thread_p and blocks inside Core
to wait for the recall exception to be issued.
* thread_p will leave not the kernel before finishing it actual IPC with
thread_s which is blocked waiting for thread_p.
That is the reason why the waiting/blocking for the recall exception taking
place must be done on NOVA in the context of the caller (thread_1).
Introduce a pause_sync call to the cpu_session which returns a semaphore
capability to the caller. The caller blocks on the semaphore and is woken up
when the pager of thread_p receives the recall exception with the state of
thread_p.
Vancouver recalls the vCPU in the vCPU dispatcher code. Enable the right bit
in the mapped native cap so that Vancouver actually is able to perform this
operation.