Annotate branches in the syscall path

This in particular significantly shortens amd64_syscall, which otherwise
keeps jumping forward over 2KB of code in total.

Note some of these branches should be either eliminated altogether or
coalesced.
This commit is contained in:
Mateusz Guzik 2020-02-14 13:08:46 +00:00
parent e3741c01c6
commit 0e84a878c0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=357911
4 changed files with 21 additions and 19 deletions

View File

@ -69,7 +69,7 @@ syscallenter(struct thread *td)
if (__predict_false(td->td_cowgen != p->p_cowgen)) if (__predict_false(td->td_cowgen != p->p_cowgen))
thread_cow_update(td); thread_cow_update(td);
traced = (p->p_flag & P_TRACED) != 0; traced = (p->p_flag & P_TRACED) != 0;
if (traced || td->td_dbgflags & TDB_USERWR) { if (__predict_false(traced || td->td_dbgflags & TDB_USERWR)) {
PROC_LOCK(p); PROC_LOCK(p);
td->td_dbgflags &= ~TDB_USERWR; td->td_dbgflags &= ~TDB_USERWR;
if (traced) if (traced)
@ -85,19 +85,19 @@ syscallenter(struct thread *td)
(uintptr_t)td, "pid:%d", td->td_proc->p_pid, "arg0:%p", sa->args[0], (uintptr_t)td, "pid:%d", td->td_proc->p_pid, "arg0:%p", sa->args[0],
"arg1:%p", sa->args[1], "arg2:%p", sa->args[2]); "arg1:%p", sa->args[1], "arg2:%p", sa->args[2]);
if (error != 0) { if (__predict_false(error != 0)) {
td->td_errno = error; td->td_errno = error;
goto retval; goto retval;
} }
STOPEVENT(p, S_SCE, sa->narg); STOPEVENT(p, S_SCE, sa->narg);
if ((p->p_flag & P_TRACED) != 0) { if (__predict_false((p->p_flag & P_TRACED) != 0)) {
PROC_LOCK(p); PROC_LOCK(p);
if (p->p_ptevents & PTRACE_SCE) if (p->p_ptevents & PTRACE_SCE)
ptracestop((td), SIGTRAP, NULL); ptracestop((td), SIGTRAP, NULL);
PROC_UNLOCK(p); PROC_UNLOCK(p);
} }
if ((td->td_dbgflags & TDB_USERWR) != 0) { if (__predict_false((td->td_dbgflags & TDB_USERWR) != 0)) {
/* /*
* Reread syscall number and arguments if debugger * Reread syscall number and arguments if debugger
* modified registers or memory. * modified registers or memory.
@ -118,8 +118,8 @@ syscallenter(struct thread *td)
* In capability mode, we only allow access to system calls * In capability mode, we only allow access to system calls
* flagged with SYF_CAPENABLED. * flagged with SYF_CAPENABLED.
*/ */
if (IN_CAPABILITY_MODE(td) && if (__predict_false(IN_CAPABILITY_MODE(td) &&
!(sa->callp->sy_flags & SYF_CAPENABLED)) { !(sa->callp->sy_flags & SYF_CAPENABLED))) {
td->td_errno = error = ECAPMODE; td->td_errno = error = ECAPMODE;
goto retval; goto retval;
} }
@ -152,7 +152,7 @@ syscallenter(struct thread *td)
AUDIT_SYSCALL_EXIT(error, td); AUDIT_SYSCALL_EXIT(error, td);
/* Save the latest error return value. */ /* Save the latest error return value. */
if ((td->td_pflags & TDP_NERRNO) == 0) if (__predict_false((td->td_pflags & TDP_NERRNO) == 0))
td->td_errno = error; td->td_errno = error;
#ifdef KDTRACE_HOOKS #ifdef KDTRACE_HOOKS
@ -168,7 +168,7 @@ syscallenter(struct thread *td)
(uintptr_t)td, "pid:%d", td->td_proc->p_pid, "error:%d", error, (uintptr_t)td, "pid:%d", td->td_proc->p_pid, "error:%d", error,
"retval0:%#lx", td->td_retval[0], "retval1:%#lx", "retval0:%#lx", td->td_retval[0], "retval1:%#lx",
td->td_retval[1]); td->td_retval[1]);
if (traced) { if (__predict_false(traced)) {
PROC_LOCK(p); PROC_LOCK(p);
td->td_dbgflags &= ~TDB_SCE; td->td_dbgflags &= ~TDB_SCE;
PROC_UNLOCK(p); PROC_UNLOCK(p);
@ -189,9 +189,10 @@ syscallret(struct thread *td)
p = td->td_proc; p = td->td_proc;
sa = &td->td_sa; sa = &td->td_sa;
if ((trap_enotcap || (p->p_flag2 & P2_TRAPCAP) != 0) && if (__predict_false(td->td_errno == ENOTCAPABLE ||
IN_CAPABILITY_MODE(td)) { td->td_errno == ECAPMODE)) {
if (td->td_errno == ENOTCAPABLE || td->td_errno == ECAPMODE) { if ((trap_enotcap ||
(p->p_flag2 & P2_TRAPCAP) != 0) && IN_CAPABILITY_MODE(td)) {
ksiginfo_init_trap(&ksi); ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGTRAP; ksi.ksi_signo = SIGTRAP;
ksi.ksi_errno = td->td_errno; ksi.ksi_errno = td->td_errno;
@ -211,20 +212,21 @@ syscallret(struct thread *td)
} }
#endif #endif
if (p->p_flag & P_TRACED) { traced = 0;
if (__predict_false(p->p_flag & P_TRACED)) {
traced = 1; traced = 1;
PROC_LOCK(p); PROC_LOCK(p);
td->td_dbgflags |= TDB_SCX; td->td_dbgflags |= TDB_SCX;
PROC_UNLOCK(p); PROC_UNLOCK(p);
} else }
traced = 0;
/* /*
* This works because errno is findable through the * This works because errno is findable through the
* register set. If we ever support an emulation where this * register set. If we ever support an emulation where this
* is not the case, this code will need to be revisited. * is not the case, this code will need to be revisited.
*/ */
STOPEVENT(p, S_SCX, sa->code); STOPEVENT(p, S_SCX, sa->code);
if (traced || (td->td_dbgflags & (TDB_EXEC | TDB_FORK)) != 0) { if (__predict_false(traced ||
(td->td_dbgflags & (TDB_EXEC | TDB_FORK)) != 0)) {
PROC_LOCK(p); PROC_LOCK(p);
/* /*
* If tracing the execed process, trap to the debugger * If tracing the execed process, trap to the debugger

View File

@ -141,13 +141,13 @@ userret(struct thread *td, struct trapframe *frame)
* If this thread tickled GEOM, we need to wait for the giggling to * If this thread tickled GEOM, we need to wait for the giggling to
* stop before we return to userland * stop before we return to userland
*/ */
if (td->td_pflags & TDP_GEOM) if (__predict_false(td->td_pflags & TDP_GEOM))
g_waitidle(); g_waitidle();
/* /*
* Charge system time if profiling. * Charge system time if profiling.
*/ */
if (p->p_flag & P_PROFIL) if (__predict_false(p->p_flag & P_PROFIL))
addupc_task(td, TRAPF_PC(frame), td->td_pticks * psratio); addupc_task(td, TRAPF_PC(frame), td->td_pticks * psratio);
#ifdef HWPMC_HOOKS #ifdef HWPMC_HOOKS

View File

@ -378,7 +378,7 @@ void audit_thread_free(struct thread *td);
} while (0) } while (0)
#define AUDIT_SYSCALL_ENTER(code, td) do { \ #define AUDIT_SYSCALL_ENTER(code, td) do { \
if (audit_syscalls_enabled) { \ if (__predict_false(audit_syscalls_enabled)) { \
audit_syscall_enter(code, td); \ audit_syscall_enter(code, td); \
} \ } \
} while (0) } while (0)

View File

@ -73,7 +73,7 @@ struct ktr_header {
#define KTRPOINT(td, type) (__predict_false(KTRCHECK((td), (type)))) #define KTRPOINT(td, type) (__predict_false(KTRCHECK((td), (type))))
#define KTRCHECKDRAIN(td) (!(STAILQ_EMPTY(&(td)->td_proc->p_ktr))) #define KTRCHECKDRAIN(td) (!(STAILQ_EMPTY(&(td)->td_proc->p_ktr)))
#define KTRUSERRET(td) do { \ #define KTRUSERRET(td) do { \
if (KTRCHECKDRAIN(td)) \ if (__predict_false(KTRCHECKDRAIN(td))) \
ktruserret(td); \ ktruserret(td); \
} while (0) } while (0)