/* * Mach Operating System * Copyright (c) 1993-1987 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. */ /* * File: thread.h * Author: Avadis Tevanian, Jr. * * This file contains the structure definitions for threads. * */ #ifndef _KERN_THREAD_H_ #define _KERN_THREAD_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* event_t, continuation_t */ #include #include #include #include /* for current_space(), current_map() */ #include #include struct thread { /* Run queues */ queue_chain_t links; /* current run queue links */ run_queue_t runq; /* run queue p is on SEE BELOW */ /* * NOTE: The runq field in the thread structure has an unusual * locking protocol. If its value is RUN_QUEUE_NULL, then it is * locked by the thread_lock, but if its value is something else * (i.e. a run_queue) then it is locked by that run_queue's lock. */ /* Task information */ task_t task; /* Task to which I belong */ queue_chain_t thread_list; /* list of threads in task */ /* Flags */ /* The flags are grouped here, but documented at the original position. */ union { struct { unsigned state:16; unsigned wake_active:1; unsigned active:1; }; event_t event_key; /* These keys can be used with thread_wakeup and friends. */ #define TH_EV_WAKE_ACTIVE(t) ((event_t) (&(t)->event_key + 0)) #define TH_EV_STATE(t) ((event_t) (&(t)->event_key + 1)) }; /* Thread bookkeeping */ queue_chain_t pset_threads; /* list of all threads in proc set*/ /* Self-preservation */ decl_simple_lock_data(,lock) int ref_count; /* number of references to me */ /* Hardware state */ pcb_t pcb; /* hardware pcb & machine state */ vm_offset_t kernel_stack; /* accurate only if the thread is not swapped and not executing */ vm_offset_t stack_privilege;/* reserved kernel stack */ /* Swapping information */ continuation_t swap_func; /* start here after swapin */ /* Blocking information */ event_t wait_event; /* event we are waiting on */ int suspend_count; /* internal use only */ kern_return_t wait_result; /* outcome of wait - may be examined by this thread WITHOUT locking */ /* Defined above */ /* boolean_t wake_active; someone is waiting for this thread to become suspended */ /* int state; Thread state: */ /* * Thread states [bits or'ed] */ #define TH_WAIT 0x01 /* thread is queued for waiting */ #define TH_SUSP 0x02 /* thread has been asked to stop */ #define TH_RUN 0x04 /* thread is running or on runq */ #define TH_UNINT 0x08 /* thread is waiting uninteruptibly */ #define TH_HALTED 0x10 /* thread is halted at clean point ? */ #define TH_IDLE 0x80 /* thread is an idle thread */ #define TH_SCHED_STATE (TH_WAIT|TH_SUSP|TH_RUN|TH_UNINT) #define TH_SWAPPED 0x0100 /* thread has no kernel stack */ #define TH_SW_COMING_IN 0x0200 /* thread is waiting for kernel stack */ #define TH_SWAP_STATE (TH_SWAPPED | TH_SW_COMING_IN) /* Scheduling information */ int priority; /* thread's priority */ int max_priority; /* maximum priority */ int sched_pri; /* scheduled (computed) priority */ #if MACH_FIXPRI int sched_data; /* for use by policy */ int policy; /* scheduling policy */ #endif /* MACH_FIXPRI */ int depress_priority; /* depressed from this priority */ unsigned int cpu_usage; /* exp. decaying cpu usage [%cpu] */ unsigned int sched_usage; /* load-weighted cpu usage [sched] */ unsigned int sched_stamp; /* last time priority was updated */ /* VM global variables */ vm_offset_t recover; /* page fault recovery (copyin/out) */ unsigned int vm_privilege; /* Can use reserved memory? Implemented as a counter */ /* User-visible scheduling state */ int user_stop_count; /* outstanding stops */ /* IPC data structures */ struct thread *ith_next, *ith_prev; mach_msg_return_t ith_state; union { mach_msg_size_t msize; /* max size for recvd msg */ struct ipc_kmsg *kmsg; /* received message */ } data; mach_port_seqno_t ith_seqno; /* seqno of recvd message */ /* This queue is used only when destroying messages: it prevents nasty recursion problems when destroying one message causes other messages to be destroyed. This queue should always be empty under normal circumstances. See ipc_kmsg_destroy() for more details. */ struct ipc_kmsg_queue ith_messages; decl_simple_lock_data(, ith_lock_data) struct ipc_port *ith_self; /* not a right, doesn't hold ref */ struct ipc_port *ith_sself; /* a send right */ struct ipc_port *ith_exception; /* a send right */ mach_port_t ith_mig_reply; /* reply port for mig */ struct ipc_port *ith_rpc_reply; /* reply port for kernel RPCs */ /* State saved when thread's stack is discarded */ union { struct { mach_msg_header_t *msg; mach_msg_option_t option; mach_msg_size_t rcv_size; mach_msg_timeout_t timeout; mach_port_t notify; struct ipc_object *object; struct ipc_mqueue *mqueue; } receive; struct { struct ipc_port *port; int exc; int code; int subcode; } exception; void *other; /* catch-all for other state */ } saved; /* Timing data structures */ timer_data_t user_timer; /* user mode timer */ timer_data_t system_timer; /* system mode timer */ timer_save_data_t user_timer_save; /* saved user timer value */ timer_save_data_t system_timer_save; /* saved sys timer val. */ unsigned int cpu_delta; /* cpu usage since last update */ unsigned int sched_delta; /* weighted cpu usage since update */ /* Creation time stamp */ time_value_t creation_time; /* Time-outs */ timer_elt_data_t timer; /* timer for thread */ timer_elt_data_t depress_timer; /* timer for priority depression */ /* Ast/Halt data structures */ /* Defined above */ /* boolean_t active; how alive is the thread */ int ast; /* ast's needed. See ast.h */ /* Processor data structures */ processor_set_t processor_set; /* assigned processor set */ processor_t bound_processor; /* bound to processor ?*/ sample_control_t pc_sample; #if MACH_HOST boolean_t may_assign; /* may assignment change? */ boolean_t assign_active; /* someone waiting for may_assign */ #endif /* MACH_HOST */ #if NCPUS > 1 processor_t last_processor; /* processor this last ran on */ #endif /* NCPUS > 1 */ }; /* typedef of thread_t is in kern/kern_types.h */ typedef struct thread_shuttle *thread_shuttle_t; #define THREAD_NULL ((thread_t) 0) #define THREAD_SHUTTLE_NULL ((thread_shuttle_t)0) #define ith_msize data.msize #define ith_kmsg data.kmsg #define ith_wait_result wait_result #define ith_msg saved.receive.msg #define ith_option saved.receive.option #define ith_rcv_size saved.receive.rcv_size #define ith_timeout saved.receive.timeout #define ith_notify saved.receive.notify #define ith_object saved.receive.object #define ith_mqueue saved.receive.mqueue #define ith_port saved.exception.port #define ith_exc saved.exception.exc #define ith_exc_code saved.exception.code #define ith_exc_subcode saved.exception.subcode #define ith_other saved.other #ifndef _KERN_KERN_TYPES_H_ typedef struct thread *thread_t; #define THREAD_NULL ((thread_t) 0) typedef mach_port_t *thread_array_t; #endif /* _KERN_KERN_TYPES_H_ */ extern thread_t active_threads[NCPUS]; /* active threads */ extern vm_offset_t active_stacks[NCPUS]; /* active kernel stacks */ #ifdef KERNEL /* * User routines */ extern kern_return_t thread_create( task_t parent_task, thread_t *child_thread); extern kern_return_t thread_terminate( thread_t thread); extern kern_return_t thread_terminate_release( thread_t thread, task_t task, mach_port_t thread_name, mach_port_t reply_port, vm_offset_t address, vm_size_t size); extern kern_return_t thread_suspend( thread_t thread); extern kern_return_t thread_resume( thread_t thread); extern kern_return_t thread_abort( thread_t thread); extern void thread_start( thread_t thread, continuation_t start); extern thread_t kernel_thread( task_t task, continuation_t start, void *arg); extern kern_return_t thread_priority( thread_t thread, int priority, boolean_t set_max); extern void thread_set_own_priority( int priority); extern kern_return_t thread_max_priority( thread_t thread, processor_set_t pset, int max_priority); extern kern_return_t thread_policy( thread_t thread, int policy, int data); extern void consider_thread_collect( void); extern void stack_privilege( thread_t thread); extern kern_return_t thread_get_state( thread_t thread, int flavor, thread_state_t old_state, natural_t *old_state_count); extern kern_return_t thread_set_state( thread_t thread, int flavor, thread_state_t new_state, natural_t new_state_count); extern kern_return_t thread_get_special_port( thread_t thread, int which, struct ipc_port **portp); extern kern_return_t thread_set_special_port( thread_t thread, int which, struct ipc_port *port); extern kern_return_t thread_info( thread_t thread, int flavor, thread_info_t thread_info_out, natural_t *thread_info_count); extern kern_return_t thread_assign( thread_t thread, processor_set_t new_pset); extern kern_return_t thread_assign_default( thread_t thread); extern void stack_collect(void); #endif /* * Kernel-only routines */ extern void thread_init(void); extern void thread_reference(thread_t); extern void thread_deallocate(thread_t); extern void thread_hold(thread_t); extern kern_return_t thread_dowait( thread_t thread, boolean_t must_halt); extern void thread_release(thread_t); extern kern_return_t thread_halt( thread_t thread, boolean_t must_halt); extern void thread_halt_self(continuation_t); extern void thread_force_terminate(thread_t); extern thread_t kernel_thread( task_t task, void (*start)(void), void * arg); extern void reaper_thread(void) __attribute__((noreturn)); #if MACH_HOST extern void thread_freeze( thread_t thread); extern void thread_doassign( thread_t thread, processor_set_t new_pset, boolean_t release_freeze); extern void thread_unfreeze( thread_t thread); #endif /* MACH_HOST */ /* * Macro-defined routines */ #define thread_pcb(th) ((th)->pcb) #define thread_lock(th) simple_lock(&(th)->lock) #define thread_unlock(th) simple_unlock(&(th)->lock) #define thread_should_halt(thread) \ ((thread)->ast & (AST_HALT|AST_TERMINATE)) /* * Machine specific implementations of the current thread macro * designate this by defining CURRENT_THREAD. */ #ifndef CURRENT_THREAD #define current_thread() (active_threads[cpu_number()]) #endif /* CURRENT_THREAD */ #define current_stack() (active_stacks[cpu_number()]) #define current_task() (current_thread()->task) #define current_space() (current_task()->itk_space) #define current_map() (current_task()->map) #if MACH_DEBUG void stack_init(vm_offset_t stack); void stack_finalize(vm_offset_t stack); #endif /* MACH_DEBUG */ #endif /* _KERN_THREAD_H_ */