diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libkse/arch/ia64/ia64/context.S | 14 | ||||
-rw-r--r-- | lib/libkse/arch/ia64/include/pthread_md.h | 36 | ||||
-rw-r--r-- | lib/libpthread/arch/ia64/ia64/context.S | 14 | ||||
-rw-r--r-- | lib/libpthread/arch/ia64/include/pthread_md.h | 36 |
4 files changed, 82 insertions, 18 deletions
diff --git a/lib/libkse/arch/ia64/ia64/context.S b/lib/libkse/arch/ia64/ia64/context.S index 6c0c082..49fe42e 100644 --- a/lib/libkse/arch/ia64/ia64/context.S +++ b/lib/libkse/arch/ia64/ia64/context.S @@ -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) diff --git a/lib/libkse/arch/ia64/include/pthread_md.h b/lib/libkse/arch/ia64/include/pthread_md.h index d6aa130..95f1d2d 100644 --- a/lib/libkse/arch/ia64/include/pthread_md.h +++ b/lib/libkse/arch/ia64/include/pthread_md.h @@ -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); } diff --git a/lib/libpthread/arch/ia64/ia64/context.S b/lib/libpthread/arch/ia64/ia64/context.S index 6c0c082..49fe42e 100644 --- a/lib/libpthread/arch/ia64/ia64/context.S +++ b/lib/libpthread/arch/ia64/ia64/context.S @@ -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) diff --git a/lib/libpthread/arch/ia64/include/pthread_md.h b/lib/libpthread/arch/ia64/include/pthread_md.h index d6aa130..95f1d2d 100644 --- a/lib/libpthread/arch/ia64/include/pthread_md.h +++ b/lib/libpthread/arch/ia64/include/pthread_md.h @@ -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); } |