aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2014-10-26 19:42:44 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2014-10-26 19:42:44 +0000
commite015b1ab0a428e65297e44471d257d7eb589b383 (patch)
treedab547b54bf840f54b99e4b2af2ddd062990face
parentf0c8263e558c86bcd68646157ac8738d75923c9b (diff)
downloadsrc-e015b1ab0a428e65297e44471d257d7eb589b383.tar.gz
src-e015b1ab0a428e65297e44471d257d7eb589b383.zip
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
Notes
Notes: svn path=/head/; revision=273707
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c23
-rw-r--r--sys/compat/freebsd32/freebsd32_util.h4
-rw-r--r--sys/kern/kern_syscalls.c26
-rw-r--r--sys/kern/sysv_msg.c4
-rw-r--r--sys/kern/sysv_sem.c4
-rw-r--r--sys/kern/sysv_shm.c4
-rw-r--r--sys/kern/uipc_mqueue.c4
-rw-r--r--sys/kern/uipc_sem.c4
-rw-r--r--sys/kern/vfs_aio.c4
-rw-r--r--sys/kgssapi/gss_impl.c2
-rw-r--r--sys/netinet/sctp_syscalls.c4
-rw-r--r--sys/nfs/nfs_nfssvc.c2
-rw-r--r--sys/nlm/nlm_prot_impl.c2
-rw-r--r--sys/sys/sysent.h10
14 files changed, 59 insertions, 38 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index d909a71ff270..8ec949f9d803 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 a5945cfbbe7e..d62bca1fa8f9 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 03f6088403de..78d2a852cfb2 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 a572a0e0c145..acc44710a78a 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 c63290240799..6ff578926a51 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 3480d1140070..15ee910971ec 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 154c1e76613d..e3fb1491f8c1 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 63b1cec0e036..935a245632e6 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 b47d713c0825..c7e602e2eb86 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 172471aa4826..ab6e55bc377d 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 3d0f549997a7..3161abcc2c01 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 3f925a13170a..c0d78e0280c8 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 74fae870efa3..5f202066ab70 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 0f1c256135f1..dabc8e843300 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;