diff options
author | mjg <mjg@FreeBSD.org> | 2014-10-26 19:42:44 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2014-10-26 19:42:44 +0000 |
commit | a9faac8f4b75a3a8c3d752a2c56e3709438f5a94 (patch) | |
tree | dab547b54bf840f54b99e4b2af2ddd062990face /sys | |
parent | 4ee18dab174120853a3d2d38c7745f4b1489ae7b (diff) | |
download | FreeBSD-src-a9faac8f4b75a3a8c3d752a2c56e3709438f5a94.zip FreeBSD-src-a9faac8f4b75a3a8c3d752a2c56e3709438f5a94.tar.gz |
Avoid dynamic syscall overhead for statically compiled modules.
The kernel tracks syscall users so that modules can safely unregister them.
But if the module is not unloadable or was compiled into the kernel, there is
no need to do this.
Achieve this by adding SY_THR_STATIC_KLD macro which expands to SY_THR_STATIC
during kernel build and 0 otherwise.
Reviewed by: kib (previous version)
MFC after: 2 weeks
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/freebsd32/freebsd32_misc.c | 23 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_util.h | 4 | ||||
-rw-r--r-- | sys/kern/kern_syscalls.c | 26 | ||||
-rw-r--r-- | sys/kern/sysv_msg.c | 4 | ||||
-rw-r--r-- | sys/kern/sysv_sem.c | 4 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 4 | ||||
-rw-r--r-- | sys/kern/uipc_mqueue.c | 4 | ||||
-rw-r--r-- | sys/kern/uipc_sem.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_aio.c | 4 | ||||
-rw-r--r-- | sys/kgssapi/gss_impl.c | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_syscalls.c | 4 | ||||
-rw-r--r-- | sys/nfs/nfs_nfssvc.c | 2 | ||||
-rw-r--r-- | sys/nlm/nlm_prot_impl.c | 2 | ||||
-rw-r--r-- | sys/sys/sysent.h | 10 |
14 files changed, 59 insertions, 38 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index d909a71..8ec949f 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -2628,8 +2628,12 @@ freebsd32_xxx(struct thread *td, struct freebsd32_xxx_args *uap) int syscall32_register(int *offset, struct sysent *new_sysent, - struct sysent *old_sysent) + struct sysent *old_sysent, int flags) { + + if ((flags & ~SY_THR_STATIC) != 0) + return (EINVAL); + if (*offset == NO_SYSCALL) { int i; @@ -2648,16 +2652,19 @@ syscall32_register(int *offset, struct sysent *new_sysent, *old_sysent = freebsd32_sysent[*offset]; freebsd32_sysent[*offset] = *new_sysent; - return 0; + atomic_store_rel_32(&freebsd32_sysent[*offset].sy_thrcnt, flags); + return (0); } int syscall32_deregister(int *offset, struct sysent *old_sysent) { - if (*offset) - freebsd32_sysent[*offset] = *old_sysent; - return 0; + if (*offset == 0) + return (0); + + freebsd32_sysent[*offset] = *old_sysent; + return (0); } int @@ -2670,7 +2677,7 @@ syscall32_module_handler(struct module *mod, int what, void *arg) switch (what) { case MOD_LOAD: error = syscall32_register(data->offset, data->new_sysent, - &data->old_sysent); + &data->old_sysent, SY_THR_STATIC_KLD); if (error) { /* Leave a mark so we know to safely unload below. */ data->offset = NULL; @@ -2707,14 +2714,14 @@ syscall32_module_handler(struct module *mod, int what, void *arg) } int -syscall32_helper_register(struct syscall_helper_data *sd) +syscall32_helper_register(struct syscall_helper_data *sd, int flags) { struct syscall_helper_data *sd1; int error; for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) { error = syscall32_register(&sd1->syscall_no, &sd1->new_sysent, - &sd1->old_sysent); + &sd1->old_sysent, flags); if (error != 0) { syscall32_helper_unregister(sd); return (error); diff --git a/sys/compat/freebsd32/freebsd32_util.h b/sys/compat/freebsd32/freebsd32_util.h index a5945cf..d62bca1 100644 --- a/sys/compat/freebsd32/freebsd32_util.h +++ b/sys/compat/freebsd32/freebsd32_util.h @@ -98,10 +98,10 @@ SYSCALL32_MODULE(syscallname, \ } int syscall32_register(int *offset, struct sysent *new_sysent, - struct sysent *old_sysent); + struct sysent *old_sysent, int flags); int syscall32_deregister(int *offset, struct sysent *old_sysent); int syscall32_module_handler(struct module *mod, int what, void *arg); -int syscall32_helper_register(struct syscall_helper_data *sd); +int syscall32_helper_register(struct syscall_helper_data *sd, int flags); int syscall32_helper_unregister(struct syscall_helper_data *sd); struct iovec32; diff --git a/sys/kern/kern_syscalls.c b/sys/kern/kern_syscalls.c index 03f6088..78d2a85 100644 --- a/sys/kern/kern_syscalls.c +++ b/sys/kern/kern_syscalls.c @@ -105,10 +105,13 @@ syscall_thread_exit(struct thread *td, struct sysent *se) int syscall_register(int *offset, struct sysent *new_sysent, - struct sysent *old_sysent) + struct sysent *old_sysent, int flags) { int i; + if ((flags & ~SY_THR_STATIC) != 0) + return (EINVAL); + if (*offset == NO_SYSCALL) { for (i = 1; i < SYS_MAXSYSCALL; ++i) if (sysent[i].sy_call == (sy_call_t *)lkmnosys) @@ -127,18 +130,23 @@ syscall_register(int *offset, struct sysent *new_sysent, *old_sysent = sysent[*offset]; new_sysent->sy_thrcnt = SY_THR_ABSENT; sysent[*offset] = *new_sysent; - atomic_store_rel_32(&sysent[*offset].sy_thrcnt, 0); + atomic_store_rel_32(&sysent[*offset].sy_thrcnt, flags); return (0); } int syscall_deregister(int *offset, struct sysent *old_sysent) { + struct sysent *se; - if (*offset) { - syscall_thread_drain(&sysent[*offset]); - sysent[*offset] = *old_sysent; - } + if (*offset == 0) + return (0); /* XXX? */ + + se = &sysent[*offset]; + if ((se->sy_thrcnt & SY_THR_STATIC) != 0) + return (EINVAL); + syscall_thread_drain(se); + sysent[*offset] = *old_sysent; return (0); } @@ -152,7 +160,7 @@ syscall_module_handler(struct module *mod, int what, void *arg) switch (what) { case MOD_LOAD: error = syscall_register(data->offset, data->new_sysent, - &data->old_sysent); + &data->old_sysent, SY_THR_STATIC_KLD); if (error) { /* Leave a mark so we know to safely unload below. */ data->offset = NULL; @@ -190,14 +198,14 @@ syscall_module_handler(struct module *mod, int what, void *arg) } int -syscall_helper_register(struct syscall_helper_data *sd) +syscall_helper_register(struct syscall_helper_data *sd, int flags) { struct syscall_helper_data *sd1; int error; for (sd1 = sd; sd1->syscall_no != NO_SYSCALL; sd1++) { error = syscall_register(&sd1->syscall_no, &sd1->new_sysent, - &sd1->old_sysent); + &sd1->old_sysent, flags); if (error != 0) { syscall_helper_unregister(sd); return (error); diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c index a572a0e..acc44710 100644 --- a/sys/kern/sysv_msg.c +++ b/sys/kern/sysv_msg.c @@ -252,11 +252,11 @@ msginit() } mtx_init(&msq_mtx, "msq", NULL, MTX_DEF); - error = syscall_helper_register(msg_syscalls); + error = syscall_helper_register(msg_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); #ifdef COMPAT_FREEBSD32 - error = syscall32_helper_register(msg32_syscalls); + error = syscall32_helper_register(msg32_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); #endif diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index c632902..6ff5789 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -278,11 +278,11 @@ seminit(void) semexit_tag = EVENTHANDLER_REGISTER(process_exit, semexit_myhook, NULL, EVENTHANDLER_PRI_ANY); - error = syscall_helper_register(sem_syscalls); + error = syscall_helper_register(sem_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); #ifdef COMPAT_FREEBSD32 - error = syscall32_helper_register(sem32_syscalls); + error = syscall32_helper_register(sem32_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); #endif diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 3480d11..15ee910 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -910,11 +910,11 @@ shminit() shmexit_hook = &shmexit_myhook; shmfork_hook = &shmfork_myhook; - error = syscall_helper_register(shm_syscalls); + error = syscall_helper_register(shm_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); #ifdef COMPAT_FREEBSD32 - error = syscall32_helper_register(shm32_syscalls); + error = syscall32_helper_register(shm32_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); #endif diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index 154c1e7..e3fb149 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -2809,11 +2809,11 @@ mqinit(void) { int error; - error = syscall_helper_register(mq_syscalls); + error = syscall_helper_register(mq_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); #ifdef COMPAT_FREEBSD32 - error = syscall32_helper_register(mq32_syscalls); + error = syscall32_helper_register(mq32_syscalls, SY_THR_STATIC_KLD); if (error != 0) return (error); #endif diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index 63b1cec..935a245 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -993,11 +993,11 @@ ksem_module_init(void) p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX); p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX); - error = syscall_helper_register(ksem_syscalls); + error = syscall_helper_register(ksem_syscalls, SY_THR_STATIC_KLD); if (error) return (error); #ifdef COMPAT_FREEBSD32 - error = syscall32_helper_register(ksem32_syscalls); + error = syscall32_helper_register(ksem32_syscalls, SY_THR_STATIC_KLD); if (error) return (error); #endif diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index b47d713..c7e602e 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -511,11 +511,11 @@ aio_onceonly(void) p31b_setcfg(CTL_P1003_1B_AIO_MAX, MAX_AIO_QUEUE); p31b_setcfg(CTL_P1003_1B_AIO_PRIO_DELTA_MAX, 0); - error = syscall_helper_register(aio_syscalls); + error = syscall_helper_register(aio_syscalls, SY_THR_STATIC_KLD); if (error) return (error); #ifdef COMPAT_FREEBSD32 - error = syscall32_helper_register(aio32_syscalls); + error = syscall32_helper_register(aio32_syscalls, SY_THR_STATIC_KLD); if (error) return (error); #endif diff --git a/sys/kgssapi/gss_impl.c b/sys/kgssapi/gss_impl.c index 172471a..ab6e55b 100644 --- a/sys/kgssapi/gss_impl.c +++ b/sys/kgssapi/gss_impl.c @@ -70,7 +70,7 @@ kgss_init(void *dummy) LIST_INIT(&kgss_mechs); error = syscall_register(&gssd_syscall_offset, &gssd_syscall_sysent, - &gssd_syscall_prev_sysent); + &gssd_syscall_prev_sysent, SY_THR_STATIC_KLD); if (error) printf("Can't register GSSD syscall\n"); else diff --git a/sys/netinet/sctp_syscalls.c b/sys/netinet/sctp_syscalls.c index 3d0f549..3161abc 100644 --- a/sys/netinet/sctp_syscalls.c +++ b/sys/netinet/sctp_syscalls.c @@ -94,11 +94,11 @@ sctp_syscalls_init(void *unused __unused) { int error; - error = syscall_helper_register(sctp_syscalls); + error = syscall_helper_register(sctp_syscalls, SY_THR_STATIC); KASSERT((error == 0), ("%s: syscall_helper_register failed for sctp syscalls", __func__)); #ifdef COMPAT_FREEBSD32 - error = syscall32_helper_register(sctp_syscalls); + error = syscall32_helper_register(sctp_syscalls, SY_THR_STATIC); KASSERT((error == 0), ("%s: syscall32_helper_register failed for sctp syscalls", __func__)); diff --git a/sys/nfs/nfs_nfssvc.c b/sys/nfs/nfs_nfssvc.c index 3f925a1..c0d78e0 100644 --- a/sys/nfs/nfs_nfssvc.c +++ b/sys/nfs/nfs_nfssvc.c @@ -123,7 +123,7 @@ nfssvc_modevent(module_t mod, int type, void *data) switch (type) { case MOD_LOAD: error = syscall_register(&nfssvc_offset, &nfssvc_sysent, - &nfssvc_prev_sysent); + &nfssvc_prev_sysent, SY_THR_STATIC_KLD); if (error) break; registered = 1; diff --git a/sys/nlm/nlm_prot_impl.c b/sys/nlm/nlm_prot_impl.c index 74fae87..5f20206 100644 --- a/sys/nlm/nlm_prot_impl.c +++ b/sys/nlm/nlm_prot_impl.c @@ -295,7 +295,7 @@ nlm_init(void *dummy) TAILQ_INIT(&nlm_hosts); error = syscall_register(&nlm_syscall_offset, &nlm_syscall_sysent, - &nlm_syscall_prev_sysent); + &nlm_syscall_prev_sysent, SY_THR_STATIC_KLD); if (error) NLM_ERR("Can't register NLM syscall\n"); else diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h index 0f1c256..dabc8e8 100644 --- a/sys/sys/sysent.h +++ b/sys/sys/sysent.h @@ -76,6 +76,12 @@ struct sysent { /* system call table */ #define SY_THR_ABSENT 0x4 #define SY_THR_INCR 0x8 +#ifdef KLD_MODULE +#define SY_THR_STATIC_KLD 0 +#else +#define SY_THR_STATIC_KLD SY_THR_STATIC +#endif + struct image_params; struct __sigset; struct syscall_args; @@ -242,10 +248,10 @@ struct syscall_helper_data { } int syscall_register(int *offset, struct sysent *new_sysent, - struct sysent *old_sysent); + struct sysent *old_sysent, int flags); int syscall_deregister(int *offset, struct sysent *old_sysent); int syscall_module_handler(struct module *mod, int what, void *arg); -int syscall_helper_register(struct syscall_helper_data *sd); +int syscall_helper_register(struct syscall_helper_data *sd, int flags); int syscall_helper_unregister(struct syscall_helper_data *sd); struct proc; |