diff options
Diffstat (limited to 'sys/kern/kern_syscalls.c')
-rw-r--r-- | sys/kern/kern_syscalls.c | 26 |
1 files changed, 17 insertions, 9 deletions
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); |