#include <cpus.h>
#include <task_swapper.h>
#include <mach/kern_return.h>
#include <mach/alert.h>
#include <kern/etap_macros.h>
#include <kern/mach_param.h>
#include <kern/zalloc.h>
#include <kern/thread.h>
#include <kern/thread_swap.h>
#include <kern/task.h>
#include <kern/task_swap.h>
#include <kern/thread_act.h>
#include <kern/sched_prim.h>
#include <kern/misc_protos.h>
#include <kern/assert.h>
#include <kern/exception.h>
#include <kern/ipc_mig.h>
#include <kern/ipc_tt.h>
#include <kern/profile.h>
#include <kern/machine.h>
#include <kern/spl.h>
#include <kern/syscall_subr.h>
#include <kern/sync_lock.h>
#include <kern/mk_sp.h>
#include <kern/processor.h>
#include <mach_prof.h>
#include <mach/rpc.h>
int act_free_swapin = 0;
kern_return_t act_abort( thread_act_t, boolean_t);
void special_handler(ReturnHandler *, thread_act_t);
kern_return_t act_set_state_locked(thread_act_t, int,
thread_state_t,
mach_msg_type_number_t);
kern_return_t act_get_state_locked(thread_act_t, int,
thread_state_t,
mach_msg_type_number_t *);
void act_set_astbsd(thread_act_t);
void act_set_apc(thread_act_t);
void act_ulock_release_all(thread_act_t thr_act);
void install_special_handler_locked(thread_act_t);
static void act_disable(thread_act_t);
kern_return_t
thread_terminate_internal(
register thread_act_t act)
{
kern_return_t result;
thread_t thread;
thread = act_lock_thread(act);
if (!act->active) {
act_unlock_thread(act);
return (KERN_TERMINATED);
}
act_disable(act);
result = act_abort(act, FALSE);
if (thread != current_thread()) {
act_unlock(act);
if (thread_stop(thread))
thread_unstop(thread);
else
result = KERN_ABORTED;
act_lock(act);
}
clear_wait(thread, act->started? THREAD_INTERRUPTED: THREAD_AWAKENED);
act_unlock_thread(act);
return (result);
}
kern_return_t
thread_terminate(
register thread_act_t act)
{
kern_return_t result;
if (act == THR_ACT_NULL)
return (KERN_INVALID_ARGUMENT);
if ( act->task == kernel_task &&
act != current_act() )
return (KERN_FAILURE);
result = thread_terminate_internal(act);
if (act->task == kernel_task) {
ml_set_interrupts_enabled(FALSE);
assert(act == current_act());
ast_taken(AST_APC, TRUE);
panic("thread_terminate");
}
return (result);
}
void
thread_hold(
register thread_act_t act)
{
thread_t thread = act->thread;
if (act->suspend_count++ == 0) {
install_special_handler(act);
if ( act->started &&
thread != THREAD_NULL &&
thread->top_act == act )
thread_wakeup_one(&act->suspend_count);
}
}
void
thread_release(
register thread_act_t act)
{
thread_t thread = act->thread;
if ( act->suspend_count > 0 &&
--act->suspend_count == 0 &&
thread != THREAD_NULL &&
thread->top_act == act ) {
if (!act->started) {
clear_wait(thread, THREAD_AWAKENED);
act->started = TRUE;
}
else
thread_wakeup_one(&act->suspend_count);
}
}
kern_return_t
thread_suspend(
register thread_act_t act)
{
thread_t thread;
if (act == THR_ACT_NULL || act->task == kernel_task)
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(act);
if (!act->active) {
act_unlock_thread(act);
return (KERN_TERMINATED);
}
if ( act->user_stop_count++ == 0 &&
act->suspend_count++ == 0 ) {
install_special_handler(act);
if ( thread != current_thread() &&
thread != THREAD_NULL &&
thread->top_act == act ) {
assert(act->started);
thread_wakeup_one(&act->suspend_count);
act_unlock_thread(act);
thread_wait(thread);
}
else
act_unlock_thread(act);
}
else
act_unlock_thread(act);
return (KERN_SUCCESS);
}
kern_return_t
thread_resume(
register thread_act_t act)
{
kern_return_t result = KERN_SUCCESS;
thread_t thread;
if (act == THR_ACT_NULL || act->task == kernel_task)
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(act);
if (act->active) {
if (act->user_stop_count > 0) {
if ( --act->user_stop_count == 0 &&
--act->suspend_count == 0 &&
thread != THREAD_NULL &&
thread->top_act == act ) {
if (!act->started) {
clear_wait(thread, THREAD_AWAKENED);
act->started = TRUE;
}
else
thread_wakeup_one(&act->suspend_count);
}
}
else
result = KERN_FAILURE;
}
else
result = KERN_TERMINATED;
act_unlock_thread(act);
return (result);
}
kern_return_t
thread_depress_abort(
register thread_act_t thr_act)
{
register thread_t thread;
kern_return_t result;
if (thr_act == THR_ACT_NULL)
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(thr_act);
if (!thr_act->active) {
act_unlock_thread(thr_act);
return (KERN_TERMINATED);
}
result = _mk_sp_thread_depress_abort(thread, FALSE);
act_unlock_thread(thr_act);
return (result);
}
kern_return_t
act_abort(
thread_act_t act,
boolean_t chain_break )
{
thread_t thread = act->thread;
spl_t s = splsched();
assert(thread->top_act == act);
thread_lock(thread);
if (!(thread->state & TH_ABORT)) {
thread->state |= TH_ABORT;
install_special_handler_locked(act);
} else {
thread->state &= ~TH_ABORT_SAFELY;
}
thread_unlock(thread);
splx(s);
return (KERN_SUCCESS);
}
kern_return_t
thread_abort(
register thread_act_t act)
{
kern_return_t result;
thread_t thread;
if (act == THR_ACT_NULL)
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(act);
if (!act->active) {
act_unlock_thread(act);
return (KERN_TERMINATED);
}
result = act_abort(act, FALSE);
clear_wait(thread, THREAD_INTERRUPTED);
act_unlock_thread(act);
return (result);
}
kern_return_t
thread_abort_safely(
thread_act_t act)
{
thread_t thread;
kern_return_t ret;
spl_t s;
if ( act == THR_ACT_NULL )
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(act);
if (!act->active) {
act_unlock_thread(act);
return (KERN_TERMINATED);
}
s = splsched();
thread_lock(thread);
if (!thread->at_safe_point ||
clear_wait_internal(thread, THREAD_INTERRUPTED) != KERN_SUCCESS) {
if (!(thread->state & TH_ABORT)) {
thread->state |= (TH_ABORT|TH_ABORT_SAFELY);
install_special_handler_locked(act);
}
}
thread_unlock(thread);
splx(s);
act_unlock_thread(act);
return (KERN_SUCCESS);
}
#include <mach/thread_info.h>
#include <mach/thread_special_ports.h>
#include <ipc/ipc_port.h>
#include <mach/thread_act_server.h>
kern_return_t
thread_info(
thread_act_t thr_act,
thread_flavor_t flavor,
thread_info_t thread_info_out,
mach_msg_type_number_t *thread_info_count)
{
register thread_t thread;
kern_return_t result;
if (thr_act == THR_ACT_NULL)
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(thr_act);
if (!thr_act->active) {
act_unlock_thread(thr_act);
return (KERN_TERMINATED);
}
result = thread_info_shuttle(thr_act, flavor,
thread_info_out, thread_info_count);
act_unlock_thread(thr_act);
return (result);
}
kern_return_t
thread_get_special_port(
thread_act_t thr_act,
int which,
ipc_port_t *portp)
{
ipc_port_t *whichp;
ipc_port_t port;
thread_t thread;
if (!thr_act)
return KERN_INVALID_ARGUMENT;
thread = act_lock_thread(thr_act);
switch (which) {
case THREAD_KERNEL_PORT:
whichp = &thr_act->ith_sself;
break;
default:
act_unlock_thread(thr_act);
return KERN_INVALID_ARGUMENT;
}
if (!thr_act->active) {
act_unlock_thread(thr_act);
return KERN_FAILURE;
}
port = ipc_port_copy_send(*whichp);
act_unlock_thread(thr_act);
*portp = port;
return KERN_SUCCESS;
}
kern_return_t
thread_set_special_port(
thread_act_t thr_act,
int which,
ipc_port_t port)
{
ipc_port_t *whichp;
ipc_port_t old;
thread_t thread;
if (thr_act == 0)
return KERN_INVALID_ARGUMENT;
thread = act_lock_thread(thr_act);
switch (which) {
case THREAD_KERNEL_PORT:
whichp = &thr_act->ith_self;
break;
default:
act_unlock_thread(thr_act);
return KERN_INVALID_ARGUMENT;
}
if (!thr_act->active) {
act_unlock_thread(thr_act);
return KERN_FAILURE;
}
old = *whichp;
*whichp = port;
act_unlock_thread(thr_act);
if (IP_VALID(old))
ipc_port_release_send(old);
return KERN_SUCCESS;
}
kern_return_t
thread_get_state(
register thread_act_t act,
int flavor,
thread_state_t state,
mach_msg_type_number_t *state_count)
{
kern_return_t result = KERN_SUCCESS;
thread_t thread;
if (act == THR_ACT_NULL || act == current_act())
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(act);
if (!act->active) {
act_unlock_thread(act);
return (KERN_TERMINATED);
}
thread_hold(act);
for (;;) {
thread_t thread1;
if ( thread == THREAD_NULL ||
thread->top_act != act )
break;
act_unlock_thread(act);
if (!thread_stop(thread)) {
result = KERN_ABORTED;
(void)act_lock_thread(act);
thread = THREAD_NULL;
break;
}
thread1 = act_lock_thread(act);
if (thread1 == thread)
break;
thread_unstop(thread);
thread = thread1;
}
if (result == KERN_SUCCESS)
result = machine_thread_get_state(act, flavor, state, state_count);
if ( thread != THREAD_NULL &&
thread->top_act == act )
thread_unstop(thread);
thread_release(act);
act_unlock_thread(act);
return (result);
}
kern_return_t
thread_set_state(
register thread_act_t act,
int flavor,
thread_state_t state,
mach_msg_type_number_t state_count)
{
kern_return_t result = KERN_SUCCESS;
thread_t thread;
if (act == THR_ACT_NULL || act == current_act())
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(act);
if (!act->active) {
act_unlock_thread(act);
return (KERN_TERMINATED);
}
thread_hold(act);
for (;;) {
thread_t thread1;
if ( thread == THREAD_NULL ||
thread->top_act != act )
break;
act_unlock_thread(act);
if (!thread_stop(thread)) {
result = KERN_ABORTED;
(void)act_lock_thread(act);
thread = THREAD_NULL;
break;
}
thread1 = act_lock_thread(act);
if (thread1 == thread)
break;
thread_unstop(thread);
thread = thread1;
}
if (result == KERN_SUCCESS)
result = machine_thread_set_state(act, flavor, state, state_count);
if ( thread != THREAD_NULL &&
thread->top_act == act )
thread_unstop(thread);
thread_release(act);
act_unlock_thread(act);
return (result);
}
kern_return_t
thread_dup(
register thread_act_t target)
{
kern_return_t result = KERN_SUCCESS;
thread_act_t self = current_act();
thread_t thread;
if (target == THR_ACT_NULL || target == self)
return (KERN_INVALID_ARGUMENT);
thread = act_lock_thread(target);
if (!target->active) {
act_unlock_thread(target);
return (KERN_TERMINATED);
}
thread_hold(target);
for (;;) {
thread_t thread1;
if ( thread == THREAD_NULL ||
thread->top_act != target )
break;
act_unlock_thread(target);
if (!thread_stop(thread)) {
result = KERN_ABORTED;
(void)act_lock_thread(target);
thread = THREAD_NULL;
break;
}
thread1 = act_lock_thread(target);
if (thread1 == thread)
break;
thread_unstop(thread);
thread = thread1;
}
if (result == KERN_SUCCESS)
result = machine_thread_dup(self, target);
if ( thread != THREAD_NULL &&
thread->top_act == target )
thread_unstop(thread);
thread_release(target);
act_unlock_thread(target);
return (result);
}
kern_return_t
thread_setstatus(
register thread_act_t act,
int flavor,
thread_state_t tstate,
mach_msg_type_number_t count)
{
kern_return_t result = KERN_SUCCESS;
thread_t thread;
thread = act_lock_thread(act);
if ( act != current_act() &&
(act->suspend_count == 0 ||
thread == THREAD_NULL ||
(thread->state & TH_RUN) ||
thread->top_act != act) )
result = KERN_FAILURE;
if (result == KERN_SUCCESS)
result = machine_thread_set_state(act, flavor, tstate, count);
act_unlock_thread(act);
return (result);
}
kern_return_t
thread_getstatus(
register thread_act_t act,
int flavor,
thread_state_t tstate,
mach_msg_type_number_t *count)
{
kern_return_t result = KERN_SUCCESS;
thread_t thread;
thread = act_lock_thread(act);
if ( act != current_act() &&
(act->suspend_count == 0 ||
thread == THREAD_NULL ||
(thread->state & TH_RUN) ||
thread->top_act != act) )
result = KERN_FAILURE;
if (result == KERN_SUCCESS)
result = machine_thread_get_state(act, flavor, tstate, count);
act_unlock_thread(act);
return (result);
}
void
act_reference(
thread_act_t act)
{
if (act == NULL)
return;
act_lock(act);
act_reference_locked(act);
act_unlock(act);
}
void
act_deallocate(
thread_act_t act)
{
task_t task;
thread_t thread;
void *task_proc;
if (act == NULL)
return;
act_lock(act);
if (--act->act_ref_count > 0) {
act_unlock(act);
return;
}
assert(!act->active);
thread = act->thread;
assert(thread != NULL);
thread->top_act = NULL;
act_unlock(act);
task = act->task;
task_lock(task);
task_proc = task->bsd_info;
{
time_value_t user_time, system_time;
thread_read_times(thread, &user_time, &system_time);
time_value_add(&task->total_user_time, &user_time);
time_value_add(&task->total_system_time, &system_time);
queue_remove(&task->threads, act, thread_act_t, task_threads);
act->task_threads.next = NULL;
task->thread_count--;
task->res_thread_count--;
}
task_unlock(task);
act_prof_deallocate(act);
ipc_thr_act_terminate(act);
#ifdef MACH_BSD
{
extern void uthread_free(task_t, void *, void *, void *);
void *ut = act->uthread;
uthread_free(task, act, ut, task_proc);
act->uthread = NULL;
}
#endif
task_deallocate(task);
thread_deallocate(thread);
}
void
act_attach(
thread_act_t act,
thread_t thread)
{
thread_act_t lower;
act->act_ref_count++;
act->thread = thread;
act->higher = THR_ACT_NULL;
lower = act->lower = thread->top_act;
if (lower != THR_ACT_NULL)
lower->higher = act;
thread->top_act = act;
}
void
act_detach(
thread_act_t cur_act)
{
thread_t cur_thread = cur_act->thread;
cur_thread->top_act = cur_act->lower;
cur_act->thread = 0;
cur_act->act_ref_count--;
assert(cur_act->act_ref_count > 0);
#if MACH_ASSERT
cur_act->lower = cur_act->higher = THR_ACT_NULL;
if (cur_thread->top_act)
cur_thread->top_act->higher = THR_ACT_NULL;
#endif
return;
}
thread_t
act_lock_thread(
thread_act_t thr_act)
{
act_lock(thr_act);
return (thr_act->thread);
}
void
act_unlock_thread(thread_act_t thr_act)
{
act_unlock(thr_act);
}
thread_act_t
thread_lock_act(
thread_t thread)
{
thread_act_t thr_act;
while (1) {
thr_act = thread->top_act;
if (!thr_act)
break;
if (!act_lock_try(thr_act)) {
mutex_pause();
continue;
}
break;
}
return (thr_act);
}
void
thread_unlock_act(
thread_t thread)
{
thread_act_t thr_act;
if (thr_act = thread->top_act) {
act_unlock(thr_act);
}
}
thread_act_t
switch_act(
thread_act_t act)
{
thread_act_t old, new;
thread_t thread;
disable_preemption();
thread = current_thread();
old = thread->top_act;
if (act) {
new = act;
new->thread = thread;
}
else {
new = old->lower;
}
assert(new != THR_ACT_NULL);
assert(current_processor()->active_thread == thread);
machine_switch_act(thread, old, new);
if (act) {
act_attach(new, thread);
}
else {
act_detach(old);
}
enable_preemption();
return(old);
}
void
install_special_handler(
thread_act_t thr_act)
{
spl_t spl;
thread_t thread = thr_act->thread;
spl = splsched();
thread_lock(thread);
install_special_handler_locked(thr_act);
thread_unlock(thread);
splx(spl);
}
void
install_special_handler_locked(
thread_act_t act)
{
thread_t thread = act->thread;
ReturnHandler **rh;
for (rh = &act->handlers; *rh; rh = &(*rh)->next)
continue;
if (rh != &act->special_handler.next)
*rh = &act->special_handler;
if (act == thread->top_act) {
if (thread->sched_mode & TH_MODE_ISDEPRESSED)
compute_priority(thread, TRUE);
}
thread_ast_set(act, AST_APC);
if (act == current_act())
ast_propagate(act->ast);
else {
processor_t processor = thread->last_processor;
if ( processor != PROCESSOR_NULL &&
processor->state == PROCESSOR_RUNNING &&
processor->active_thread == thread )
cause_ast_check(processor);
}
}
kern_return_t
thread_apc_set(
thread_act_t act,
thread_apc_handler_t apc)
{
extern thread_apc_handler_t bsd_ast;
assert(apc == bsd_ast);
return (KERN_FAILURE);
}
kern_return_t
thread_apc_clear(
thread_act_t act,
thread_apc_handler_t apc)
{
extern thread_apc_handler_t bsd_ast;
assert(apc == bsd_ast);
return (KERN_FAILURE);
}
void
act_execute_returnhandlers(void)
{
thread_act_t act = current_act();
thread_ast_clear(act, AST_APC);
spllo();
for (;;) {
ReturnHandler *rh;
thread_t thread = act_lock_thread(act);
(void)splsched();
thread_lock(thread);
rh = act->handlers;
if (!rh) {
thread_unlock(thread);
spllo();
act_unlock_thread(act);
return;
}
act->handlers = rh->next;
thread_unlock(thread);
spllo();
act_unlock_thread(act);
(*rh->handler)(rh, act);
}
}
void
special_handler_continue(void)
{
thread_act_t self = current_act();
if (self->suspend_count > 0)
install_special_handler(self);
else {
thread_t thread = self->thread;
spl_t s = splsched();
thread_lock(thread);
if (thread->sched_mode & TH_MODE_ISDEPRESSED) {
processor_t myprocessor = thread->last_processor;
thread->sched_pri = DEPRESSPRI;
myprocessor->current_pri = thread->sched_pri;
thread->sched_mode &= ~TH_MODE_PREEMPT;
}
thread_unlock(thread);
splx(s);
}
thread_exception_return();
}
void
special_handler(
ReturnHandler *rh,
thread_act_t self)
{
thread_t thread = act_lock_thread(self);
spl_t s;
assert(thread != THREAD_NULL);
s = splsched();
thread_lock(thread);
thread->state &= ~(TH_ABORT|TH_ABORT_SAFELY);
thread_unlock(thread);
splx(s);
if (!self->active) {
act_unlock_thread(self);
thread_terminate_self();
}
if (self->suspend_count > 0) {
if (self->handlers == NULL) {
assert_wait(&self->suspend_count, THREAD_ABORTSAFE);
act_unlock_thread(self);
thread_block(special_handler_continue);
}
act_unlock_thread(self);
special_handler_continue();
}
act_unlock_thread(self);
}
static void
act_disable(
thread_act_t thr_act)
{
thr_act->active = 0;
act_deallocate_locked(thr_act);
}
typedef struct GetSetState {
struct ReturnHandler rh;
int flavor;
void *state;
int *pcount;
int result;
} GetSetState;
kern_return_t get_set_state(
thread_act_t thr_act, int flavor,
thread_state_t state, int *pcount,
void (*handler)(ReturnHandler *rh, thread_act_t thr_act));
void get_state_handler(ReturnHandler *rh, thread_act_t thr_act);
void set_state_handler(ReturnHandler *rh, thread_act_t thr_act);
kern_return_t
get_set_state(
thread_act_t act,
int flavor,
thread_state_t state,
int *pcount,
void (*handler)(
ReturnHandler *rh,
thread_act_t act))
{
GetSetState gss;
gss.rh.handler = handler;
gss.flavor = flavor;
gss.state = state;
gss.pcount = pcount;
gss.result = KERN_ABORTED;
gss.rh.next = act->handlers;
act->handlers = &gss.rh;
act_set_apc(act);
assert(act->thread);
assert(act != current_act());
for (;;) {
wait_result_t result;
if ( act->started &&
act->thread->top_act == act )
thread_wakeup_one(&act->suspend_count);
result = assert_wait(&gss, THREAD_ABORTSAFE);
act_unlock_thread(act);
if (result == THREAD_WAITING)
result = thread_block(THREAD_CONTINUE_NULL);
assert(result != THREAD_WAITING);
if (gss.result != KERN_ABORTED) {
assert(result != THREAD_INTERRUPTED);
break;
}
if (current_act()->handlers)
act_execute_returnhandlers();
act_lock_thread(act);
}
return (gss.result);
}
void
set_state_handler(ReturnHandler *rh, thread_act_t thr_act)
{
GetSetState *gss = (GetSetState*)rh;
gss->result = machine_thread_set_state(thr_act, gss->flavor,
gss->state, *gss->pcount);
thread_wakeup((event_t)gss);
}
void
get_state_handler(ReturnHandler *rh, thread_act_t thr_act)
{
GetSetState *gss = (GetSetState*)rh;
gss->result = machine_thread_get_state(thr_act, gss->flavor,
gss->state,
(mach_msg_type_number_t *) gss->pcount);
thread_wakeup((event_t)gss);
}
kern_return_t
act_get_state_locked(thread_act_t thr_act, int flavor, thread_state_t state,
mach_msg_type_number_t *pcount)
{
return(get_set_state(thr_act, flavor, state, (int*)pcount, get_state_handler));
}
kern_return_t
act_set_state_locked(thread_act_t thr_act, int flavor, thread_state_t state,
mach_msg_type_number_t count)
{
return(get_set_state(thr_act, flavor, state, (int*)&count, set_state_handler));
}
kern_return_t
act_set_state(thread_act_t thr_act, int flavor, thread_state_t state,
mach_msg_type_number_t count)
{
if (thr_act == THR_ACT_NULL || thr_act == current_act())
return(KERN_INVALID_ARGUMENT);
act_lock_thread(thr_act);
return(act_set_state_locked(thr_act, flavor, state, count));
}
kern_return_t
act_get_state(thread_act_t thr_act, int flavor, thread_state_t state,
mach_msg_type_number_t *pcount)
{
if (thr_act == THR_ACT_NULL || thr_act == current_act())
return(KERN_INVALID_ARGUMENT);
act_lock_thread(thr_act);
return(act_get_state_locked(thr_act, flavor, state, pcount));
}
void
act_set_astbsd(
thread_act_t act)
{
spl_t s = splsched();
if (act == current_act()) {
thread_ast_set(act, AST_BSD);
ast_propagate(act->ast);
}
else {
thread_t thread = act->thread;
processor_t processor;
thread_lock(thread);
thread_ast_set(act, AST_BSD);
processor = thread->last_processor;
if ( processor != PROCESSOR_NULL &&
processor->state == PROCESSOR_RUNNING &&
processor->active_thread == thread )
cause_ast_check(processor);
thread_unlock(thread);
}
splx(s);
}
void
act_set_apc(
thread_act_t act)
{
spl_t s = splsched();
if (act == current_act()) {
thread_ast_set(act, AST_APC);
ast_propagate(act->ast);
}
else {
thread_t thread = act->thread;
processor_t processor;
thread_lock(thread);
thread_ast_set(act, AST_APC);
processor = thread->last_processor;
if ( processor != PROCESSOR_NULL &&
processor->state == PROCESSOR_RUNNING &&
processor->active_thread == thread )
cause_ast_check(processor);
thread_unlock(thread);
}
splx(s);
}
void
act_ulock_release_all(thread_act_t thr_act)
{
ulock_t ulock;
while (!queue_empty(&thr_act->held_ulocks)) {
ulock = (ulock_t) queue_first(&thr_act->held_ulocks);
(void) lock_make_unstable(ulock, thr_act);
(void) lock_release_internal(ulock, thr_act);
}
}
thread_act_t
thread_self(void)
{
thread_act_t self = current_act_fast();
act_reference(self);
return self;
}
thread_act_t
mach_thread_self(void)
{
thread_act_t self = current_act_fast();
act_reference(self);
return self;
}