From owner-svn-src-all@FreeBSD.ORG Mon Jun 28 18:06:47 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2DFEA106566C; Mon, 28 Jun 2010 18:06:47 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 1CC4F8FC13; Mon, 28 Jun 2010 18:06:47 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o5SI6lIB077828; Mon, 28 Jun 2010 18:06:47 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o5SI6kAH077821; Mon, 28 Jun 2010 18:06:46 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201006281806.o5SI6kAH077821@svn.freebsd.org> From: Konstantin Belousov Date: Mon, 28 Jun 2010 18:06:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r209579 - in head/sys: compat/freebsd32 kern sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Jun 2010 18:06:47 -0000 Author: kib Date: Mon Jun 28 18:06:46 2010 New Revision: 209579 URL: http://svn.freebsd.org/changeset/base/209579 Log: Count number of threads that enter and leave dynamically registered syscalls. On the dynamic syscall deregistration, wait until all threads leave the syscall code. This somewhat increases the safety of the loadable modules unloading. Reviewed by: jhb Tested by: pho MFC after: 1 month Modified: head/sys/compat/freebsd32/syscalls.master head/sys/kern/kern_syscalls.c head/sys/kern/makesyscalls.sh head/sys/kern/subr_trap.c head/sys/kern/syscalls.master head/sys/sys/sysent.h Modified: head/sys/compat/freebsd32/syscalls.master ============================================================================== --- head/sys/compat/freebsd32/syscalls.master Mon Jun 28 17:59:45 2010 (r209578) +++ head/sys/compat/freebsd32/syscalls.master Mon Jun 28 18:06:46 2010 (r209579) @@ -386,16 +386,16 @@ ; ; The following are reserved for loadable syscalls ; -210 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -211 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -212 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -213 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -214 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -215 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -216 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -217 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -218 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -219 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int +210 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +211 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +212 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +213 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +214 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +215 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +216 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +217 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +218 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +219 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int ; ; The following were introduced with NetBSD/4.4Lite-2 Modified: head/sys/kern/kern_syscalls.c ============================================================================== --- head/sys/kern/kern_syscalls.c Mon Jun 28 17:59:45 2010 (r209578) +++ head/sys/kern/kern_syscalls.c Mon Jun 28 18:06:46 2010 (r209579) @@ -28,12 +28,15 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include #include #include #include +#include +#include /* * Acts like "nosys" but can be identified in sysent for dynamic call @@ -55,6 +58,51 @@ lkmressys(struct thread *td, struct nosy return (nosys(td, args)); } +static void +syscall_thread_drain(struct sysent *se) +{ + u_int32_t cnt, oldcnt; + + do { + oldcnt = se->sy_thrcnt; + KASSERT((oldcnt & SY_THR_STATIC) == 0, + ("drain on static syscall")); + cnt = oldcnt | SY_THR_DRAINING; + } while (atomic_cmpset_acq_32(&se->sy_thrcnt, oldcnt, cnt) == 0); + while (atomic_cmpset_32(&se->sy_thrcnt, SY_THR_DRAINING, + SY_THR_ABSENT) == 0) + pause("scdrn", hz/2); +} + +int +syscall_thread_enter(struct thread *td, struct sysent *se) +{ + u_int32_t cnt, oldcnt; + + do { + oldcnt = se->sy_thrcnt; + if ((oldcnt & SY_THR_STATIC) != 0) + return (0); + if ((oldcnt & (SY_THR_DRAINING | SY_THR_ABSENT)) != 0) + return (ENOSYS); + cnt = oldcnt + SY_THR_INCR; + } while (atomic_cmpset_acq_32(&se->sy_thrcnt, oldcnt, cnt) == 0); + return (0); +} + +void +syscall_thread_exit(struct thread *td, struct sysent *se) +{ + u_int32_t cnt, oldcnt; + + do { + oldcnt = se->sy_thrcnt; + if ((oldcnt & SY_THR_STATIC) != 0) + return; + cnt = oldcnt - SY_THR_INCR; + } while (atomic_cmpset_rel_32(&se->sy_thrcnt, oldcnt, cnt) == 0); +} + int syscall_register(int *offset, struct sysent *new_sysent, struct sysent *old_sysent) @@ -74,8 +122,12 @@ syscall_register(int *offset, struct sys sysent[*offset].sy_call != (sy_call_t *)lkmressys) return (EEXIST); + KASSERT(sysent[*offset].sy_thrcnt == SY_THR_ABSENT, + ("dynamic syscall is not protected")); *old_sysent = sysent[*offset]; + new_sysent->sy_thrcnt = SY_THR_ABSENT; sysent[*offset] = *new_sysent; + atomic_store_rel_32(&sysent[*offset].sy_thrcnt, 0); return (0); } @@ -83,8 +135,10 @@ int syscall_deregister(int *offset, struct sysent *old_sysent) { - if (*offset) + if (*offset) { + syscall_thread_drain(&sysent[*offset]); sysent[*offset] = *old_sysent; + } return (0); } Modified: head/sys/kern/makesyscalls.sh ============================================================================== --- head/sys/kern/makesyscalls.sh Mon Jun 28 17:59:45 2010 (r209578) +++ head/sys/kern/makesyscalls.sh Mon Jun 28 18:06:46 2010 (r209579) @@ -253,6 +253,10 @@ s/\$//g f=4 # toss number, type, audit event argc= 0; argssize = "0" + thr_flag = "SY_THR_STATIC" + if (flag("NOTSTATIC")) { + thr_flag = "SY_THR_ABSENT" + } if ($NF != "}") { funcalias=$(NF-2) argalias=$(NF-1) @@ -401,10 +405,10 @@ s/\$//g printf("\t{ %s, (sy_call_t *)", argssize) > sysent column = 8 + 2 + length(argssize) + 15 if (flag("NOSTD")) { - printf("%s },", "lkmressys, AUE_NULL, NULL, 0, 0, 0") > sysent + printf("%s },", "lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT") > sysent column = column + length("lkmressys") + length("AUE_NULL") + 3 } else { - printf("%s, %s, NULL, 0, 0, %s },", funcname, auditev, flags) > sysent + printf("%s, %s, NULL, 0, 0, %s, %s },", funcname, auditev, flags, thr_flag) > sysent column = column + length(funcname) + length(auditev) + length(flags) + 3 } align_sysent_comment(column) @@ -472,13 +476,13 @@ s/\$//g prefix, funcname, auditev) > sysaue } if (flag("NOSTD")) { - printf("\t{ %s, (sy_call_t *)%s, %s, NULL, 0, 0, 0 },", + printf("\t{ %s, (sy_call_t *)%s, %s, NULL, 0, 0, 0, SY_THR_ABSENT },", "0", "lkmressys", "AUE_NULL") > sysent align_sysent_comment(8 + 2 + length("0") + 15 + \ length("lkmressys") + length("AUE_NULL") + 3) } else { - printf("\t{ %s(%s,%s), %s, NULL, 0, 0, %s },", - wrap, argssize, funcname, auditev, flags) > sysent + printf("\t{ %s(%s,%s), %s, NULL, 0, 0, %s, %s },", + wrap, argssize, funcname, auditev, flags, thr_flag) > sysent align_sysent_comment(8 + 9 + length(argssize) + 1 + \ length(funcname) + length(auditev) + \ length(flags) + 4) @@ -498,7 +502,7 @@ s/\$//g next } type("OBSOL") { - printf("\t{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0 },") > sysent + printf("\t{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },") > sysent align_sysent_comment(34) printf("/* %d = obsolete %s */\n", syscall, comment) > sysent printf("\t\"obs_%s\",\t\t\t/* %d = obsolete %s */\n", @@ -509,7 +513,7 @@ s/\$//g next } type("UNIMPL") { - printf("\t{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0 },\t\t\t/* %d = %s */\n", + printf("\t{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT },\t\t\t/* %d = %s */\n", syscall, comment) > sysent printf("\t\"#%d\",\t\t\t/* %d = %s */\n", syscall, syscall, comment) > sysnames Modified: head/sys/kern/subr_trap.c ============================================================================== --- head/sys/kern/subr_trap.c Mon Jun 28 17:59:45 2010 (r209578) +++ head/sys/kern/subr_trap.c Mon Jun 28 18:06:46 2010 (r209579) @@ -298,6 +298,9 @@ syscallenter(struct thread *td, struct s if (error != 0) goto retval; } + error = syscall_thread_enter(td, sa->callp); + if (error != 0) + goto retval; #ifdef KDTRACE_HOOKS /* @@ -327,6 +330,7 @@ syscallenter(struct thread *td, struct s (*systrace_probe_func)(sa->callp->sy_return, sa->code, sa->callp, sa->args); #endif + syscall_thread_exit(td, sa->callp); CTR4(KTR_SYSC, "syscall: p=%p error=%d return %#lx %#lx", p, error, td->td_retval[0], td->td_retval[1]); } Modified: head/sys/kern/syscalls.master ============================================================================== --- head/sys/kern/syscalls.master Mon Jun 28 17:59:45 2010 (r209578) +++ head/sys/kern/syscalls.master Mon Jun 28 18:06:46 2010 (r209579) @@ -40,7 +40,7 @@ ; NOPROTO same as STD except do not create structure or ; function prototype in sys/sysproto.h. Does add a ; definition to syscall.h besides adding a sysent. - +; NONSTATIC syscall is loadable ; ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master @@ -403,16 +403,16 @@ ; ; The following are reserved for loadable syscalls ; -210 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -211 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -212 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -213 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -214 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -215 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -216 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -217 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -218 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int -219 AUE_NULL NODEF lkmnosys lkmnosys nosys_args int +210 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +211 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +212 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +213 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +214 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +215 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +216 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +217 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +218 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int +219 AUE_NULL NODEF|NOTSTATIC lkmnosys lkmnosys nosys_args int ; ; The following were introduced with NetBSD/4.4Lite-2 Modified: head/sys/sys/sysent.h ============================================================================== --- head/sys/sys/sysent.h Mon Jun 28 17:59:45 2010 (r209578) +++ head/sys/sys/sysent.h Mon Jun 28 18:06:46 2010 (r209579) @@ -61,8 +61,15 @@ struct sysent { /* system call table * u_int32_t sy_entry; /* DTrace entry ID for systrace. */ u_int32_t sy_return; /* DTrace return ID for systrace. */ u_int32_t sy_flags; /* General flags for system calls. */ + u_int32_t sy_thrcnt; }; +#define SY_THR_FLAGMASK 0x7 +#define SY_THR_STATIC 0x1 +#define SY_THR_DRAINING 0x2 +#define SY_THR_ABSENT 0x4 +#define SY_THR_INCR 0x8 + struct image_params; struct __sigset; struct syscall_args; @@ -211,6 +218,9 @@ struct nosys_args; int lkmnosys(struct thread *, struct nosys_args *); int lkmressys(struct thread *, struct nosys_args *); +int syscall_thread_enter(struct thread *td, struct sysent *se); +void syscall_thread_exit(struct thread *td, struct sysent *se); + #endif /* _KERNEL */ #endif /* !_SYS_SYSENT_H_ */