Grok async contexts. When a thread is interrupted and an upcall
happens, the context of the interrupted thread is exported to userland. Unlike most contexts, it will be an async context and we cannot easily use our existing functions to set such a context. To avoid a lot of complexity that may possibly interfere with the common case, we simply let the kernel deal with it. However, we don't use the EPC based syscall path to invoke setcontext(2). No, we use the break-based syscall path. That way the trapframe will be compatible with the context we're trying to restore and we save the kernel a lot of trouble. The kind of trouble we did not want to go though ourselves... However, we also need to set the threads mailbox and there's no syscall to help us out. To avoid creating a new syscall, we use the context itself to pass the information to the kernel so that the kernel can update the mailbox. This involves setting a flag (_MC_FLAGS_KSE_SET_MBOX) and setting ifa (the address) and isr (the value).
This commit is contained in:
parent
b88da9d9aa
commit
0dae148272
@ -27,6 +27,8 @@
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#define SIZEOF_SPECIAL (18*8)
|
||||
|
||||
/*
|
||||
@ -335,3 +337,15 @@ ENTRY(_ia64_save_context, 1)
|
||||
;;
|
||||
}
|
||||
END(_ia64_save_context)
|
||||
|
||||
/*
|
||||
* void _ia64_break_setcontext(ucontext_t *ucp);
|
||||
*/
|
||||
ENTRY(_ia64_break_setcontext, 1)
|
||||
{ .mib
|
||||
mov r15=SYS_setcontext
|
||||
break 0x100000
|
||||
br.ret.sptk rp
|
||||
;;
|
||||
}
|
||||
END(_ia64_break_setcontext)
|
||||
|
@ -34,8 +34,14 @@
|
||||
#include <ucontext.h>
|
||||
|
||||
#define THR_GETCONTEXT(ucp) _ia64_save_context(&(ucp)->uc_mcontext)
|
||||
#define THR_SETCONTEXT(ucp) _ia64_restore_context(&(ucp)->uc_mcontext, \
|
||||
0, NULL)
|
||||
#define THR_SETCONTEXT(ucp) \
|
||||
do { \
|
||||
if ((ucp)->uc_mcontext.mc_flags & _MC_FLAGS_ASYNC_CONTEXT) \
|
||||
_ia64_break_setcontext(ucp); \
|
||||
else \
|
||||
_ia64_restore_context(&(ucp)->uc_mcontext, 0, \
|
||||
NULL); \
|
||||
} while (0)
|
||||
|
||||
#define PER_THREAD
|
||||
|
||||
@ -194,6 +200,7 @@ _get_curkse(void)
|
||||
return (_tcb->tcb_curkcb->kcb_kse);
|
||||
}
|
||||
|
||||
void _ia64_break_setcontext(ucontext_t *ucp);
|
||||
void _ia64_enter_uts(kse_func_t uts, struct kse_mailbox *km, void *stack,
|
||||
size_t stacksz);
|
||||
int _ia64_restore_context(mcontext_t *mc, intptr_t val, intptr_t *loc);
|
||||
@ -218,14 +225,25 @@ _thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
|
||||
static __inline int
|
||||
_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
|
||||
{
|
||||
mcontext_t *mc;
|
||||
|
||||
_tcb_set(kcb, tcb);
|
||||
if (setmbox != 0)
|
||||
_ia64_restore_context(&tcb->tcb_tmbx.tm_context.uc_mcontext,
|
||||
(intptr_t)&tcb->tcb_tmbx,
|
||||
(intptr_t *)&kcb->kcb_kmbx.km_curthread);
|
||||
else
|
||||
_ia64_restore_context(&tcb->tcb_tmbx.tm_context.uc_mcontext,
|
||||
0, NULL);
|
||||
mc = &tcb->tcb_tmbx.tm_context.uc_mcontext;
|
||||
if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) {
|
||||
if (setmbox) {
|
||||
mc->mc_flags |= _MC_FLAGS_KSE_SET_MBOX;
|
||||
mc->mc_special.ifa =
|
||||
(intptr_t)&kcb->kcb_kmbx.km_curthread;
|
||||
mc->mc_special.isr = (intptr_t)&tcb->tcb_tmbx;
|
||||
}
|
||||
_ia64_break_setcontext(&tcb->tcb_tmbx.tm_context);
|
||||
} else {
|
||||
if (setmbox)
|
||||
_ia64_restore_context(mc, (intptr_t)&tcb->tcb_tmbx,
|
||||
(intptr_t *)&kcb->kcb_kmbx.km_curthread);
|
||||
else
|
||||
_ia64_restore_context(mc, 0, NULL);
|
||||
}
|
||||
/* We should not reach here. */
|
||||
return (-1);
|
||||
}
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#define SIZEOF_SPECIAL (18*8)
|
||||
|
||||
/*
|
||||
@ -335,3 +337,15 @@ ENTRY(_ia64_save_context, 1)
|
||||
;;
|
||||
}
|
||||
END(_ia64_save_context)
|
||||
|
||||
/*
|
||||
* void _ia64_break_setcontext(ucontext_t *ucp);
|
||||
*/
|
||||
ENTRY(_ia64_break_setcontext, 1)
|
||||
{ .mib
|
||||
mov r15=SYS_setcontext
|
||||
break 0x100000
|
||||
br.ret.sptk rp
|
||||
;;
|
||||
}
|
||||
END(_ia64_break_setcontext)
|
||||
|
@ -34,8 +34,14 @@
|
||||
#include <ucontext.h>
|
||||
|
||||
#define THR_GETCONTEXT(ucp) _ia64_save_context(&(ucp)->uc_mcontext)
|
||||
#define THR_SETCONTEXT(ucp) _ia64_restore_context(&(ucp)->uc_mcontext, \
|
||||
0, NULL)
|
||||
#define THR_SETCONTEXT(ucp) \
|
||||
do { \
|
||||
if ((ucp)->uc_mcontext.mc_flags & _MC_FLAGS_ASYNC_CONTEXT) \
|
||||
_ia64_break_setcontext(ucp); \
|
||||
else \
|
||||
_ia64_restore_context(&(ucp)->uc_mcontext, 0, \
|
||||
NULL); \
|
||||
} while (0)
|
||||
|
||||
#define PER_THREAD
|
||||
|
||||
@ -194,6 +200,7 @@ _get_curkse(void)
|
||||
return (_tcb->tcb_curkcb->kcb_kse);
|
||||
}
|
||||
|
||||
void _ia64_break_setcontext(ucontext_t *ucp);
|
||||
void _ia64_enter_uts(kse_func_t uts, struct kse_mailbox *km, void *stack,
|
||||
size_t stacksz);
|
||||
int _ia64_restore_context(mcontext_t *mc, intptr_t val, intptr_t *loc);
|
||||
@ -218,14 +225,25 @@ _thread_enter_uts(struct tcb *tcb, struct kcb *kcb)
|
||||
static __inline int
|
||||
_thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
|
||||
{
|
||||
mcontext_t *mc;
|
||||
|
||||
_tcb_set(kcb, tcb);
|
||||
if (setmbox != 0)
|
||||
_ia64_restore_context(&tcb->tcb_tmbx.tm_context.uc_mcontext,
|
||||
(intptr_t)&tcb->tcb_tmbx,
|
||||
(intptr_t *)&kcb->kcb_kmbx.km_curthread);
|
||||
else
|
||||
_ia64_restore_context(&tcb->tcb_tmbx.tm_context.uc_mcontext,
|
||||
0, NULL);
|
||||
mc = &tcb->tcb_tmbx.tm_context.uc_mcontext;
|
||||
if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) {
|
||||
if (setmbox) {
|
||||
mc->mc_flags |= _MC_FLAGS_KSE_SET_MBOX;
|
||||
mc->mc_special.ifa =
|
||||
(intptr_t)&kcb->kcb_kmbx.km_curthread;
|
||||
mc->mc_special.isr = (intptr_t)&tcb->tcb_tmbx;
|
||||
}
|
||||
_ia64_break_setcontext(&tcb->tcb_tmbx.tm_context);
|
||||
} else {
|
||||
if (setmbox)
|
||||
_ia64_restore_context(mc, (intptr_t)&tcb->tcb_tmbx,
|
||||
(intptr_t *)&kcb->kcb_kmbx.km_curthread);
|
||||
else
|
||||
_ia64_restore_context(mc, 0, NULL);
|
||||
}
|
||||
/* We should not reach here. */
|
||||
return (-1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user