#include <thread.h>
Inheritance diagram for Thread:
Public Types | |
typedef void( | Utcb_copy_func )(Thread *sender, Thread *receiver) |
Public Member Functions | |
Thread (Task *task, Global_id id, unsigned short init_prio, unsigned short mcp) | |
Constructor. | |
void | sys_ipc () |
L4 IPC system call. | |
void | sys_fpage_unmap () |
L4 system call fpage_unmap. | |
void | sys_thread_switch () |
L4 system-call thread_switch. | |
void | sys_thread_schedule () |
L4 system call thread_schedule. | |
void | sys_task_new () |
L4 system call task_new. | |
void | sys_id_nearest () |
L4 system call id_nearest. | |
void | sys_thread_ex_regs () |
L4 system call lthread_ex_regs. | |
bool | handle_page_fault (Address pfa, Mword error, Mword pc) |
The global page fault handler switch. | |
Task_num | d_taskno () |
Task number for debugging purposes. | |
LThread_num | d_threadno () |
Thread number for debugging purposes. | |
Mword | is_tcb_mapped () const |
bool | ipc_short_cut () |
Short cut for L4 IPC system call (short IPC). | |
void * | operator new (size_t, L4_uid id) |
Class-specific allocator. | |
void | operator delete (void *) |
Deallocator. | |
virtual | ~Thread () |
Destructor. | |
Task * | task () const |
Task. | |
Thread_lock * | thread_lock () |
Thread lock. | |
Preemption * | preemption () |
void | handle_timer_interrupt () |
void | halt () |
Space_index | space_index () const |
Thread's space index. | |
Space_index | chief_index () const |
Chief's space index. | |
bool | kill_task (Space_index subtask) |
Kill a subtask of this thread's task. | |
unsigned | nest () const |
Return nesting level. | |
bool | has_privileged_iopl () |
void | unset_utcb_ptr () |
bool | initialize (Address ip, Address sp, Thread *pager, Receiver *preempter, Address *o_ip=0, Address *o_sp=0, Thread **o_pager=0, Receiver **o_preempter=0, Address *o_flags=0, bool no_cancel=0, bool alien=0) |
(Re-) Ininialize a thread and make it ready. | |
int | handle_slow_trap (Trap_state *ts) |
The global trap handler switch. | |
bool | raise_exception (Trap_state *ts, Address handler) |
Raise a machine exception for the task. | |
int | snd_exception (Trap_state *) const |
void | handle_fpu_trap () |
virtual void | ipc_receiver_ready () |
Receiver-ready callback. | |
Ipc_err | ipc_continue (Ipc_err ipc_code) |
Wake up sender. | |
Thread * | next_present () const |
void | sys_ipc_log () |
IPC logging. | |
void | sys_ipc_trace () |
IPC tracing. | |
void | sys_fpage_unmap_log () |
L4 system call fpage_unmap. | |
int | is_mapped () |
int | is_valid () |
void | print_snd_partner (int task_format=0) |
void | print_partner (int task_format=0) |
void | print_uid (int task_format=0) |
void | print_state_long (unsigned cut_on_len=0) |
Static Public Member Functions | |
static Thread * | lookup (L4_uid id, Space *s) |
Calculate TCB pointer from thread ID. | |
static Mword | pagein_tcb_request (Address pc) |
Check if the pagefault occured at a special place: At some places in the kernel we want to ensure that a specific address is mapped. | |
static Thread * | lookup (Context *c) |
Lookup function: Find Thread instance that owns a given Context. | |
static Thread * | lookup (Global_id id) |
Calculate TCB pointer from global thread ID. | |
static void | halt_current () |
static Thread * | lookup_first_thread (unsigned space) |
Return first thread in an address space. | |
static void | privilege_initialization () |
static void | set_int3_handler (int(*handler)(Trap_state *ts)) |
static int | log_page_fault () |
static Task_num | get_task (Global_id id) |
Static Public Attributes | |
static bool | may_enter_jdb = false |
Protected Member Functions | |
Thread (Task *task, L4_uid id) | |
Cut-down version of Thread constructor; only for kernel threads Do only what's necessary to get a kernel thread started -- skip all fancy stuff, no locking is necessary. | |
void | kill_all () |
void | reset_ipc_window () |
Resets the ipc window adresses. | |
void | setup_ipc_window (unsigned win, Address address) |
Define contents of IPC windows. | |
bool | in_present_list () |
Is this thread a member of the present list?. | |
void | present_enqueue (Thread *sibling) |
Enqueue in present list. | |
void | present_dequeue () |
Dequeue from present list. | |
Protected Attributes | |
Preemption | _preemption |
Deadline_timeout | _deadline_timeout |
Activation | _activation |
Task * | _task |
Thread_lock | _thread_lock |
Thread * | _pager |
Thread * | _ext_preempter |
Thread * | present_next |
Thread * | present_prev |
L4_rcv_desc | _target_desc |
unsigned | _pagein_status_code |
Address | _vm_window0 |
Address | _vm_window1 |
jmp_buf * | _recover_jmpbuf |
L4_timeout | _pf_timeout |
Address | _last_pf_address |
unsigned | _last_pf_error_code |
unsigned | _magic |
Irq_alloc * | _irq |
Idt_entry * | _idt |
Unsigned16 | _idt_limit |
Static Protected Attributes | |
static const unsigned | magic = 0xf001c001 |
static Trap_state::Handler nested_trap_handler | FIASCO_FASTCALL |
Private Member Functions | |
Thread (const Thread &) | |
Default copy constructor is undefined. | |
void * | operator new (size_t) |
Default new operator undefined. | |
bool | handle_sigma0_page_fault (Address pfa) |
bool | handle_smas_page_fault (Address pfa, Mword error, Ipc_err &ipc_code) |
void | kill_small_space () |
Additional things to do before killing, when using small spaces. | |
Mword | small_space () |
Return small address space the task is in. | |
void | set_small_space (Mword nr) |
Move the task this thread belongs to to the given small address space. | |
void | rcv_startup_msg () |
Receive startup message. | |
bool | associate_irq (Irq_alloc *irq) |
void | disassociate_irq (Irq_alloc *irq) |
bool | handle_smas_gp_fault () |
Mword | ipc_send_regs (Thread *receiver, Sys_ipc_frame const *sender_regs) |
IPC rendezvous. | |
void | page_fault_msg (Sys_ipc_frame &r, Address fault_address, Mword fault_ip, Mword err) |
Set up a page fault message. | |
void | commit_ipc_success (Sys_ipc_frame *regs, Ipc_err err) |
Write IPC error code into stack frame and/or UTCB in case of successful IPC. | |
void | commit_ipc_failure (Sys_ipc_frame *regs, Ipc_err err) |
Write IPC error code into stack frame and/or UTCB in case of failed IPC. | |
Ipc_err | get_ipc_err (Sys_ipc_frame *regs) |
Get the current IPC error code out of stack frame and/or UTCB. | |
void | set_source_local_id (Thread *receiver, Sys_ipc_frame *dest_regs) |
Set the source UTCB pointer in the IPC reg's, if this was an intra task IPC. | |
Address | remote_fault_addr (Address pfa) |
Compute remote pagefault address from the local pagefault address in the local Long-IPC window. | |
Mword | update_ipc_window (Address pfa, Mword error_code, Address remote_pfa) |
Try to upgrade the local IPC window with a mapping from the partner's address space. | |
bool | kill () |
Kill this thread. | |
void | copy_utcb_to (Thread *) |
void | enqueue_thread0_other_task () |
int | is_privileged_for_debug (Trap_state *) |
bool | get_ioport (Address, Trap_state *, unsigned *, unsigned *) |
void | enqueue_thread_other_task () |
void | setup_lipc_utcb () |
void | setup_exception_ipc () |
void | setup_utcb_kernel_addr () |
Dummy function to hold code in thread-ia32-ux-v2x0 generic. | |
void | arch_init () |
The ia32 specific part of the thread constructor. | |
int | check_trap13_kernel (Trap_state *ts, bool from_user) |
void | check_f00f_bug (Trap_state *ts) |
bool | handle_io_page_fault (Trap_state *ts, Address eip, bool from_user) |
bool | handle_sysenter_trap (Trap_state *ts, Address eip, bool from_user) |
bool | trap_is_privileged (Trap_state *) |
void | do_wrmsr_in_kernel (Trap_state *ts) |
void | do_rdmsr_in_kernel (Trap_state *ts) |
int | handle_not_nested_trap (Trap_state *ts) |
bool | handle_lldt (Trap_state *) |
void | get_timesharing_param (L4_sched_param *param, L4_uid *preempter, L4_uid *ipc_partner) |
Mword | set_schedule_param (L4_sched_param param, unsigned short const id) |
void | set_preempter (L4_uid const preempter) |
Mword | set_realtime_param (L4_sched_param param) |
Mword | remove_realtime_param () |
Mword | begin_periodic (Unsigned64 clock, Mword const type) |
Mword | end_periodic () |
void | reset_nest (L4_uid id) |
void | inc_nest (L4_uid id) |
void | update_nest (L4_uid id) |
int | handle_inter_task_ex_regs (Sys_ex_regs_frame *, L4_uid *, Thread **, Task **, Thread **) |
Unsigned64 | snd_timeout (L4_timeout t, Sys_ipc_frame const *regs) |
Compute thread's send timeout. | |
Unsigned64 | rcv_timeout (L4_timeout t, Sys_ipc_frame const *regs) |
Compute thread's receive timeout. | |
Ipc_err | do_send (Thread *partner, L4_timeout t, Sys_ipc_frame *regs) |
Send an IPC message. | |
void | prepare_receive (Sender *partner, Sys_ipc_frame *regs) |
Prepare an IPC-receive operation. | |
Ipc_err | do_receive (Sender *sender, L4_timeout t, Sys_ipc_frame *regs) |
Receive an IPC message. | |
Ipc_err | handle_page_fault_pager (Address pfa, Mword error_code) |
Page fault handler. | |
void | unlock_receiver (Receiver *receiver, const Sys_ipc_frame *) |
Unlock the Receiver locked with ipc_try_lock(). | |
Ipc_err | handle_ipc_page_fault (Address pfa, Mword error_code) |
Handle a page fault that occurred in one of the ``IPC-window'' virtual-address-space regions. | |
Ipc_err | ipc_snd_fpage (Thread *receiver, L4_fpage from_fpage, L4_fpage to_fpage, Address offset, bool grant, bool finish, bool dont_switch) |
Send a flexpage. | |
void | wake_receiver (Thread *receiver) |
Ipc_err | ipc_finish (Thread *receiver, Ipc_err new_state, bool dont_switch) |
Finish an IPC. | |
Ipc_err | ipc_pagein_request (Receiver *receiver, Address address, Mword error_code) |
Send a page-in request to a receiver. | |
bool | invalid_ipc_buffer (void const *a) |
Ipc_err | do_send_long (Thread *partner, Sys_ipc_frame *i_regs) |
Carry out long IPC. | |
void | page_fault_log (Address pfa, unsigned error_code, unsigned eip) |
Page-fault logging. | |
Static Private Member Functions | |
static void | user_invoke () |
Return to user. | |
static Mword const | exception_cs () |
Return code segment used for exception reflection to user mode. | |
static void | handle_double_fault (void) asm("thread_handle_double_fault") |
static void | user_invoke_generic () |
static void | print_page_fault_error (Mword e) |
static int | handle_int3 (Trap_state *ts) |
Default handle for int3 extensions if JDB is disabled. | |
static int | call_nested_trap_handler (Trap_state *ts) |
Call the nested trap handler (either Jdb::enter_kdebugger() or the gdb stub. | |
static Unsigned64 | round_quantum (Unsigned64 quantum) |
Round quantum up to the nearest supported value. | |
Static Private Attributes | |
static int(* | int3_handler )(Trap_state *) = handle_int3 |
Friends | |
class | Jdb |
class | Jdb_bt |
class | Jdb_tcb |
class | Jdb_thread_list |
class | Jdb_list_threads |
class | Jdb_list_timeouts |
class | Jdb_tbuf_show |
This class is the driver class for most kernel functionality.
|
|
|
Constructor.
|
|
Default copy constructor is undefined.
|
|
Cut-down version of Thread constructor; only for kernel threads Do only what's necessary to get a kernel thread started -- skip all fancy stuff, no locking is necessary.
|
|
Destructor. Reestablish the Context constructor's precondition.
|
|
The ia32 specific part of the thread constructor.
|
|
|
|
|
|
Call the nested trap handler (either Jdb::enter_kdebugger() or the gdb stub. Setup our own stack frame |
|
|
|
|
|
Chief's space index.
|
|
Write IPC error code into stack frame and/or UTCB in case of failed IPC.
|
|
Write IPC error code into stack frame and/or UTCB in case of successful IPC.
|
|
|
|
Task number for debugging purposes. May be changed to show sth. more useful for the debugger. Do not rely on this method in kernel code.
|
|
Thread number for debugging purposes.
|
|
|
|
|
|
Receive an IPC message. Block until we can receive a message or the timeout hits. Before calling this function, the thread needs to call prepare_receive(). The sender and regs arguments must correspond to those supplied to prepare_receive().
|
|
Send an IPC message. Block until we can send the message or the timeout hits.
|
|
Carry out long IPC. This method assumes that IPC handshake has finished successfully (ipc_send_regs()). Its arguments must correspond to those supplied to ipc_send_regs(). The method copies data from the sender's address space into the receiver's using IPC address-space windows. During copying, page faults in both the sender's and the receiver's buffer can occur, leading to page-fault--IPC handling. When using small address spaces great care must be taken when copying out of the users address space, as kernel and user may use different segments.
|
|
|
|
|
|
|
|
|
|
Return code segment used for exception reflection to user mode.
|
|
|
|
Get the current IPC error code out of stack frame and/or UTCB.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Default handle for int3 extensions if JDB is disabled. If the JDB is available, Jdb::handle_int3_threadctx is called instead.
|
|
|
|
|
|
Handle a page fault that occurred in one of the ``IPC-window'' virtual-address-space regions.
|
|
|
|
|
|
The global page fault handler switch. Handles page-fault monitoring, classification of page faults based on virtual-memory area they occured in, page-directory updates for kernel faults, IPC-window updates, and invocation of paging function for user-space page faults (handle_page_fault_pager).
|
|
Page fault handler. This handler suspends any ongoing IPC, then sets up page-fault IPC. Finally, the ongoing IPC's state (if any) is restored.
|
|
|
|
The global trap handler switch. This function handles CPU-exception reflection, emulation of CPU instructions (LIDT, WRMSR, RDMSR), int3 debug messages, kernel-debugger invocation, and thread crashes (if a trap cannot be handled).
|
|
|
|
|
|
|
|
|
|
|
|
Is this thread a member of the present list?.
|
|
|
|
(Re-) Ininialize a thread and make it ready. XXX Contrary to the L4-V2 spec we only cancel IPC if eip != 0xffffffff!
|
|
|
|
Wake up sender. A receiver wants to wake up a sender after a page-in request.
|
|
Finish an IPC.
|
|
Send a page-in request to a receiver. Requests that the receiver pages in some pages needed by the sender to copy data into the receiver's address space.
|
|
Receiver-ready callback. Receivers make sure to call this function on waiting senders when they get ready to receive a message from that sender. Senders need to overwrite this interface. Class Thread's implementation wakes up the sender if it is still in sender-wait state. Implements Sender. |
|
IPC rendezvous. This method sets up an IPC. It also finishes the IPC if it was a short IPC.
|
|
Short cut for L4 IPC system call (short IPC). For the special case of short IPC we try to avoid the full blown overhead of the interruptible ipc scheme. It's only applicable if the following requirements are all met:
|
|
Send a flexpage. Assumes we are in the middle of long IPC.
|
|
|
|
|
|
|
|
|
|
Kill this thread. If this thread has local number 0, kill its address space (task) as well. This function does not handle recursion.
|
|
|
|
Additional things to do before killing, when using small spaces.
|
|
Kill a subtask of this thread's task. This must be executed on thread 0 of the chief of the task to be killed.
|
|
|
|
Calculate TCB pointer from global thread ID.
|
|
Lookup function: Find Thread instance that owns a given Context.
|
|
Calculate TCB pointer from thread ID.
|
|
Return first thread in an address space.
|
|
Return nesting level.
|
|
|
|
Deallocator. This function currently does nothing: We do not free up space allocated to thread-control blocks. |
|
Class-specific allocator. This allocator ensures that threads are allocated at a fixed virtual address computed from their thread ID.
Reimplemented in Kernel_thread. |
|
Default new operator undefined.
|
|
Page-fault logging.
|
|
Set up a page fault message.
|
|
Check if the pagefault occured at a special place: At some places in the kernel we want to ensure that a specific address is mapped. The regular case is "mapped", the exception or slow case is "not mapped". The fastest way to check this is to touch into the memory. If there is no mapping for the address we get a pagefault. Now the pagefault exception handler can recognize that situation by scanning the code. The trick is that the assembler instruction "andl $0xffffffff, %ss:(%ecx)" _clears_ the carry flag normally (see Intel reference manual). The pager wants to inform the code that there was a pagefault and therefore _sets_ the carry flag. So the code has only to check if the carry flag is set. If yes, there was a pagefault at this instruction.
|
|
|
|
Prepare an IPC-receive operation. This method must be called before do_receive() and, when carrying out a combined snd-and-receive operation, also before do_send().
|
|
Dequeue from present list. Remove this thread from present list. |
|
Enqueue in present list.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Raise a machine exception for the task. This function modifies a thread's user stack pointer and user instruction pointer to emulate a machine exception.
|
|
Receive startup message. Wait for startup IPC from pager and set ip and sp. |
|
Compute thread's receive timeout.
|
|
Compute remote pagefault address from the local pagefault address in the local Long-IPC window.
|
|
|
|
Resets the ipc window adresses. Should be called at the end of every long IPC to prevent unnecessary pagefaults. If we dont do this, the test if (EXPECT_TRUE (_vm_window0 == address)) in setup_ipc_window(unsigned win, Address address) is mostly successful. If the test is positive, we dont copy the PDE slots. Because pingpong uses the same ipc buffers again and again, then this so called "optimization" results in pagefaults for EVERY long ipc. Reason: pingpong sets for the first time the _vm_window*, do the long ipc and switch to the receiver. Then receiver switches back to the sender using another ipc. Remember: every thread switch flushes the ipc window pde slots. But, because we have same ipc buffer addresses as before, the test is always positive, and so we dont update the now empty pde slots. The result is, for EVERY long ipc, after the first long ipc, we get an pagefault. |
|
|
|
Round quantum up to the nearest supported value.
|
|
|
|
|
|
|
|
|
|
Move the task this thread belongs to to the given small address space.
|
|
Set the source UTCB pointer in the IPC reg's, if this was an intra task IPC. Necessary for efficient LIPC. It's a dummy on non LIPC kernels.
|
|
|
|
Define contents of IPC windows. The address range set for these ranges is mapped upon the next page fault in handle_page_fault().
|
|
|
|
Dummy function to hold code in thread-ia32-ux-v2x0 generic.
|
|
Return small address space the task is in.
|
|
|
|
Compute thread's send timeout.
|
|
Thread's space index.
|
|
L4 system call fpage_unmap.
|
|
L4 system call fpage_unmap.
|
|
L4 system call id_nearest.
|
|
L4 IPC system call. This is the `normal'' version of the IPC system call. It usually only gets called if ipc_short_cut() has failed.
|
|
IPC logging. called from interrupt gate. |
|
IPC tracing.
|
|
L4 system call task_new.
|
|
L4 system call lthread_ex_regs.
|
|
L4 system call thread_schedule.
|
|
L4 system-call thread_switch.
|
|
Task.
|
|
Thread lock. Overwrite Context's version of thread_lock() with a semantically equivalent, but more efficient version.
|
|
|
|
Unlock the Receiver locked with ipc_try_lock(). If the sender goes to wait for a registered message enable LIPC.
|
|
|
|
Try to upgrade the local IPC window with a mapping from the partner's address space.
|
|
|
|
Return to user. This function is the default routine run if a newly initialized context is being switch_exec()'ed. |
|
|
|
|
|
Reimplemented from Sender. |
|
|
|
|
|
|
|
|
|
Reimplemented from Context. |
|
Reimplemented from Sender. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Reimplemented from Context. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|