#ifndef _KERN_THREAD_ACT_H_
#define _KERN_THREAD_ACT_H_
#include <mach/mach_types.h>
#include <mach/rpc.h>
#include <mach/vm_param.h>
#include <mach/thread_info.h>
#include <mach/exception_types.h>
#ifdef MACH_KERNEL_PRIVATE
#include <mach_assert.h>
#include <thread_swapper.h>
#include <cputypes.h>
#include <kern/lock.h>
#include <kern/queue.h>
#include <kern/etap_macros.h>
#include <kern/exception.h>
#include <kern/thread.h>
#include <kern/thread_pool.h>
#include <ipc/ipc_port.h>
#include <machine/thread_act.h>
typedef struct ReturnHandler {
struct ReturnHandler *next;
void (*handler)(struct ReturnHandler *rh,
struct thread_activation *thr_act);
} ReturnHandler;
typedef struct thread_activation {
queue_chain_t thr_acts;
boolean_t kernel_loaded;
boolean_t kernel_loading;
struct MachineThrAct mact;
decl_mutex_data(,lock)
decl_simple_lock_data(,sched_lock)
int ref_count;
struct task *task;
vm_map_t map;
struct ipc_port *pool_port;
struct thread_activation *thread_pool_next;
union {
struct {
rpc_subsystem_t r_subsystem;
#if 0
mach_rpc_id_t r_routine_num;
mach_rpc_signature_t r_sig_ptr;
mach_rpc_size_t r_sig_size;
#else
rpc_id_t r_routine_num;
rpc_signature_t r_sig_ptr;
rpc_size_t r_sig_size;
struct rpc_signature r_sigbuf;
routine_descriptor_t r_sigbufp;
vm_size_t r_sigbuf_size;
#endif
vm_offset_t r_new_argv;
vm_offset_t *r_arg_buf;
vm_offset_t r_arg_buf_data[RPC_KBUF_SIZE];
rpc_copy_state_t r_state;
rpc_copy_state_data_t r_state_data[RPC_DESC_COUNT];
unsigned int r_port_flags;
ipc_port_t r_local_port;
void *r_kkt_args;
} regular;
struct {
ipc_port_t r_port;
ipc_port_t r_exc_port;
int r_exc_flavor;
mach_msg_type_number_t r_ostate_cnt;
exception_data_type_t r_code[EXCEPTION_CODE_MAX];
#if ETAP_EVENT_MONITOR
exception_type_t r_exception;
#endif
} exception;
} rpc_state;
struct thread_shuttle *thread;
struct thread_activation *higher, *lower;
unsigned alerts;
unsigned alert_mask;
#if 0
policy_t saved_policy;
integer_t saved_base_priority;
unsigned int saved_sched_change_stamp;
#endif
int suspend_count;
int user_stop_count;
int ast;
#if THREAD_SWAPPER
int swap_state;
queue_chain_t swap_queue;
#if MACH_ASSERT
boolean_t kernel_stack_swapped_in;
#endif
#endif
int active;
ReturnHandler *handlers;
ReturnHandler special_handler;
struct ipc_port *ith_self;
struct ipc_port *ith_sself;
struct exception_action exc_actions[EXC_TYPES_COUNT];
queue_head_t held_ulocks;
#if MACH_PROF
boolean_t act_profiled;
boolean_t act_profiled_own;
struct prof_data *profil_buffer;
#endif
#ifdef MACH_BSD
void *uthread;
#endif
} Thread_Activation;
#define r_subsystem rpc_state.regular.r_subsystem
#define r_routine_num rpc_state.regular.r_routine_num
#define r_sig_ptr rpc_state.regular.r_sig_ptr
#define r_sig_size rpc_state.regular.r_sig_size
#define r_sigbuf rpc_state.regular.r_sigbuf
#define r_sigbufp rpc_state.regular.r_sigbufp
#define r_sigbuf_size rpc_state.regular.r_sigbuf_size
#define r_new_argv rpc_state.regular.r_new_argv
#define r_arg_buf rpc_state.regular.r_arg_buf
#define r_arg_buf_data rpc_state.regular.r_arg_buf_data
#define r_state rpc_state.regular.r_state
#define r_state_data rpc_state.regular.r_state_data
#define r_port_flags rpc_state.regular.r_port_flags
#define r_local_port rpc_state.regular.r_local_port
#define r_kkt_args rpc_state.regular.r_kkt_args
#define r_port rpc_state.exception.r_port
#define r_exc_port rpc_state.exception.r_exc_port
#define r_exc_flavor rpc_state.exception.r_exc_flavor
#define r_ostate_cnt rpc_state.exception.r_ostate_cnt
#define r_code rpc_state.exception.r_code
#define r_exception rpc_state.exception.r_exception
#define SERVER_TERMINATED 0x01
#define ORPHANED 0x02
#define CLIENT_TERMINATED 0x04
#define TIME_CONSTRAINT_UNSATISFIED 0x08
#if THREAD_SWAPPER
#define act_switch_swapcheck(thread, port) \
MACRO_BEGIN \
thread_act_t __act__ = thread->top_act; \
\
while (__act__->lower) { \
thread_act_t __l__ = __act__->lower; \
\
if (__l__->swap_state == TH_SW_IN || \
__l__->swap_state == TH_SW_UNSWAPPABLE) \
break; \
\
if (port) \
ip_unlock(port); \
if (!thread_swapin_blocking(__l__)) \
panic("act_switch_swapcheck: !active"); \
if (port) \
ip_lock(port); \
if (__act__->lower == __l__) \
break; \
} \
MACRO_END
#else
#define act_switch_swapcheck(thread, port)
#endif
#define act_lock_init(thr_act) mutex_init(&(thr_act)->lock, ETAP_THREAD_ACT)
#define act_lock(thr_act) mutex_lock(&(thr_act)->lock)
#define act_lock_try(thr_act) mutex_try(&(thr_act)->lock)
#define act_unlock(thr_act) mutex_unlock(&(thr_act)->lock)
#define ACT_MAX_REFERENCES \
(unsigned)(~0 ^ (1 << (sizeof(int)*BYTE_SIZE - 1)))
#define act_reference_fast(thr_act) \
MACRO_BEGIN \
if (thr_act) { \
act_lock(thr_act); \
assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
(thr_act)->ref_count++; \
act_unlock(thr_act); \
} \
MACRO_END
#define act_reference(thr_act) act_reference_fast(thr_act)
#define act_locked_act_reference(thr_act) \
MACRO_BEGIN \
if (thr_act) { \
assert((thr_act)->ref_count < ACT_MAX_REFERENCES); \
(thr_act)->ref_count++; \
} \
MACRO_END
#define sigbuf_dealloc(thr_act) \
if ((thr_act->r_sigbufp) && (thr_act->r_sigbuf_size > \
sizeof(thr_act->r_sigbuf))) \
{ \
kfree((vm_offset_t)thr_act->r_sigbufp, \
thr_act->r_sigbuf_size); \
thr_act->r_sigbuf_size = 0; \
}
#define act_deallocate_fast(thr_act) \
MACRO_BEGIN \
if (thr_act) { \
int new_value; \
act_lock(thr_act); \
assert((thr_act)->ref_count > 0 && \
(thr_act)->ref_count <= ACT_MAX_REFERENCES); \
new_value = --(thr_act)->ref_count; \
act_unlock(thr_act); \
if (new_value == 0) \
act_free(thr_act); \
} \
MACRO_END
#define act_deallocate(thr_act) act_deallocate_fast(thr_act)
#define act_locked_act_deallocate(thr_act) \
MACRO_BEGIN \
if (thr_act) { \
int new_value; \
assert((thr_act)->ref_count > 0 && \
(thr_act)->ref_count <= ACT_MAX_REFERENCES); \
new_value = --(thr_act)->ref_count; \
if (new_value == 0) { \
panic("a_l_act_deallocate: would free act"); \
} \
} \
MACRO_END
extern void act_init(void);
extern kern_return_t act_disable_task_locked(thread_act_t);
extern void thread_release(thread_act_t);
extern kern_return_t thread_dowait(thread_act_t, boolean_t);
extern void thread_hold(thread_act_t);
extern void nudge(thread_act_t);
extern kern_return_t act_set_thread_pool(thread_act_t, ipc_port_t);
extern kern_return_t act_locked_act_set_thread_pool(thread_act_t, ipc_port_t);
extern kern_return_t thread_get_special_port(thread_act_t, int,
ipc_port_t *);
extern kern_return_t thread_set_special_port(thread_act_t, int,
ipc_port_t);
extern thread_t act_lock_thread(thread_act_t);
extern void act_unlock_thread(thread_act_t);
extern void install_special_handler(thread_act_t);
extern thread_act_t thread_lock_act(thread_t);
extern void thread_unlock_act(thread_t);
extern void act_attach(thread_act_t, thread_t, unsigned);
extern void act_execute_returnhandlers(void);
extern void act_detach(thread_act_t);
extern void act_free(thread_act_t);
extern void act_machine_return(kern_return_t);
extern void act_machine_init(void);
extern kern_return_t act_machine_create(struct task *, thread_act_t);
extern void act_machine_destroy(thread_act_t);
extern kern_return_t act_machine_set_state(thread_act_t,
thread_flavor_t, thread_state_t,
mach_msg_type_number_t );
extern kern_return_t act_machine_get_state(thread_act_t,
thread_flavor_t, thread_state_t,
mach_msg_type_number_t *);
extern void act_machine_switch_pcb(thread_act_t);
extern void act_virtual_machine_destroy(thread_act_t);
extern kern_return_t act_create(task_t, thread_act_t *);
extern kern_return_t act_get_state(thread_act_t, int, thread_state_t,
mach_msg_type_number_t *);
extern kern_return_t act_set_state(thread_act_t, int, thread_state_t,
mach_msg_type_number_t);
extern int dump_act(thread_act_t);
#define current_act_fast() (current_thread()->top_act)
#define current_act_slow() ((current_thread()) ? \
current_act_fast() : \
THR_ACT_NULL)
#define current_act() current_act_slow()
#else
extern thread_act_t current_act(void);
extern void act_reference(thread_act_t);
extern void act_deallocate(thread_act_t);
#endif
extern kern_return_t act_alert(thread_act_t, unsigned);
extern kern_return_t act_alert_mask(thread_act_t, unsigned );
extern kern_return_t post_alert(thread_act_t, unsigned);
extern kern_return_t thread_abort(thread_act_t);
extern kern_return_t thread_abort_safely(thread_act_t);
extern kern_return_t thread_resume(thread_act_t);
extern kern_return_t thread_suspend(thread_act_t);
extern kern_return_t thread_terminate(thread_act_t);
typedef void (thread_apc_handler_t)(thread_act_t);
extern kern_return_t thread_apc_set(thread_act_t, thread_apc_handler_t);
extern kern_return_t thread_apc_clear(thread_act_t, thread_apc_handler_t);
extern vm_map_t swap_act_map(thread_act_t, vm_map_t);
extern void *get_bsdthread_info(thread_act_t);
extern void set_bsdthread_info(thread_act_t, void *);
extern task_t get_threadtask(thread_act_t);
#endif