summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormjg <mjg@FreeBSD.org>2014-10-26 19:42:44 +0000
committermjg <mjg@FreeBSD.org>2014-10-26 19:42:44 +0000
commita9faac8f4b75a3a8c3d752a2c56e3709438f5a94 (patch)
treedab547b54bf840f54b99e4b2af2ddd062990face /sys
parent4ee18dab174120853a3d2d38c7745f4b1489ae7b (diff)
downloadFreeBSD-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.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 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;
OpenPOWER on IntegriCloud