From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933152Ab1ETGQA (ORCPT ); Fri, 20 May 2011 02:16:00 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:64512 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932787Ab1ETGP6 (ORCPT ); Fri, 20 May 2011 02:15:58 -0400 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:mime-version:content-type :content-disposition:user-agent; b=ufi6FvsMOg75vYrtayPRsXs2m8kAJbpsl30w4CnQ8OvCx5kE7pleoC7PJqcrkMTFKc u/ywmCkh91fiMGBmRm3MNnamtd66Fw1j1s8l/XObiKfRyXTO/Gb5JaRhEHsrvdCcaNzj gQUvvmcwbPXJdfnmLWkMWTqihdb/C7hwWGfOw= Date: Fri, 20 May 2011 09:15:55 +0300 From: Alexey Dobriyan To: akpm@linux-foundation.org Cc: linux-kernel@vger.kernel.org, arnd@arndb.de, mmarek@suse.cz, linux-kbuild@vger.kernel.org Subject: [PATCH] kstrtox: drop kstrtol()/kstrtoul() when possible Message-ID: <20110520061259.GA13483@p183> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org If "long" and "long long" types are identical at runtime, kstrtol() can be aliased to kstrtoll(). Unfortunately, one can't write #if sizeof(long) == sizeof(long long) ... To solve this, generate header file with sizes and alignment of interesting types like we do with bounds.h and asm-offsets.h. Everything above applies to "unsigned long" and kstrtoul(). Signed-off-by: Alexey Dobriyan --- Kbuild | 45 +++++++++++++++++++++++++++++++++++++++------ include/linux/kernel.h | 27 ++++++++------------------- kernel/sizeof.c | 10 ++++++++++ lib/kstrtox.c | 19 +++++++++++++------ 4 files changed, 70 insertions(+), 31 deletions(-) --- a/Kbuild +++ b/Kbuild @@ -5,13 +5,16 @@ # 2) Generate asm-offsets.h (may need bounds.h) # 3) Check for missing system calls +always := +targets := + ##### -# 1) Generate bounds.h +# Generate bounds.h bounds-file := include/generated/bounds.h -always := $(bounds-file) -targets := $(bounds-file) kernel/bounds.s +always += $(bounds-file) +targets += $(bounds-file) kernel/bounds.s quiet_cmd_bounds = GEN $@ define cmd_bounds @@ -39,8 +42,38 @@ $(obj)/$(bounds-file): kernel/bounds.s Kbuild $(Q)mkdir -p $(dir $@) $(call cmd,bounds) +# generated/sizeof.h +sizeof-file := include/generated/sizeof.h + +always += $(sizeof-file) +targets += $(sizeof-file) kernel/sizeof.s + +quiet_cmd_sizeof = GEN $@ +define cmd_sizeof + ( \ + set -e; \ + echo "#ifndef _LINUX_SIZEOF_H"; \ + echo "#define _LINUX_SIZEOF_H"; \ + echo "/*"; \ + echo " * This file is automatically generated from kernel/sizeof.c .";\ + echo " * Modifying is futile."; \ + echo " */"; \ + sed -ne $(sed-y) $<; \ + echo "#endif" \ + ) >$@ +endef + +# We use internal kbuild rules to avoid the "is up to date" message from make +kernel/sizeof.s: kernel/sizeof.c FORCE + $(Q)mkdir -p $(dir $@) + $(call if_changed_dep,cc_s_c) + +$(obj)/$(sizeof-file): kernel/sizeof.s Kbuild + $(Q)mkdir -p $(dir $@) + $(call cmd,sizeof) + ##### -# 2) Generate asm-offsets.h +# Generate asm-offsets.h # offsets-file := include/generated/asm-offsets.h @@ -85,7 +118,7 @@ $(obj)/$(offsets-file): arch/$(SRCARCH)/kernel/asm-offsets.s Kbuild $(call cmd,offsets) ##### -# 3) Check for missing system calls +# Check for missing system calls # quiet_cmd_syscalls = CALL $< @@ -96,4 +129,4 @@ missing-syscalls: scripts/checksyscalls.sh FORCE $(call cmd,syscalls) # Keep these two files during make clean -no-clean-files := $(bounds-file) $(offsets-file) +no-clean-files := $(bounds-file) $(offsets-file) $(sizeof-file) --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -8,6 +8,7 @@ #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) #ifdef __KERNEL__ +#include #include #include @@ -194,32 +195,20 @@ int __must_check _kstrtol(const char *s, unsigned int base, long *res); int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res); int __must_check kstrtoll(const char *s, unsigned int base, long long *res); +#if SIZEOF_LONG == SIZEOF_LONG_LONG && ALIGNOF_LONG == ALIGNOF_LONG_LONG static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res) { - /* - * We want to shortcut function call, but - * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0. - */ - if (sizeof(unsigned long) == sizeof(unsigned long long) && - __alignof__(unsigned long) == __alignof__(unsigned long long)) - return kstrtoull(s, base, (unsigned long long *)res); - else - return _kstrtoul(s, base, res); + return kstrtoull(s, base, (unsigned long long *)res); } static inline int __must_check kstrtol(const char *s, unsigned int base, long *res) { - /* - * We want to shortcut function call, but - * __builtin_types_compatible_p(long, long long) = 0. - */ - if (sizeof(long) == sizeof(long long) && - __alignof__(long) == __alignof__(long long)) - return kstrtoll(s, base, (long long *)res); - else - return _kstrtol(s, base, res); + return kstrtoll(s, base, (long long *)res); } - +#else +int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res); +int __must_check kstrtol(const char *s, unsigned int base, long *res); +#endif int __must_check kstrtouint(const char *s, unsigned int base, unsigned int *res); int __must_check kstrtoint(const char *s, unsigned int base, int *res); new file mode 100644 --- /dev/null +++ b/kernel/sizeof.c @@ -0,0 +1,10 @@ +#include + +void f(void) +{ + DEFINE(SIZEOF_LONG, sizeof(long)); + DEFINE(ALIGNOF_LONG, __alignof__(long)); + + DEFINE(SIZEOF_LONG_LONG, sizeof(long long)); + DEFINE(ALIGNOF_LONG_LONG, __alignof__(long long)); +} --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -11,6 +11,7 @@ * * If -E is returned, result is not touched. */ +#include #include #include #include @@ -101,8 +102,14 @@ int kstrtoll(const char *s, unsigned int base, long long *res) } EXPORT_SYMBOL(kstrtoll); -/* Internal, do not use. */ -int _kstrtoul(const char *s, unsigned int base, unsigned long *res) +#if SIZEOF_LONG == SIZEOF_LONG_LONG && ALIGNOF_LONG == ALIGNOF_LONG_LONG +/* + * Shortcut function call if types are indistinguishable at runtime. + * FYI, both __builtin_types_compatible_p(unsigned long, unsigned long long) + * and __builtin_types_compatible_p(long, long long) are always 0. + */ +#else +int kstrtoul(const char *s, unsigned int base, unsigned long *res) { unsigned long long tmp; int rv; @@ -115,10 +122,9 @@ int _kstrtoul(const char *s, unsigned int base, unsigned long *res) *res = tmp; return 0; } -EXPORT_SYMBOL(_kstrtoul); +EXPORT_SYMBOL(kstrtoul); -/* Internal, do not use. */ -int _kstrtol(const char *s, unsigned int base, long *res) +int kstrtol(const char *s, unsigned int base, long *res) { long long tmp; int rv; @@ -131,7 +137,8 @@ int _kstrtol(const char *s, unsigned int base, long *res) *res = tmp; return 0; } -EXPORT_SYMBOL(_kstrtol); +EXPORT_SYMBOL(kstrtol); +#endif int kstrtouint(const char *s, unsigned int base, unsigned int *res) {