From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756051AbcEaUbY (ORCPT ); Tue, 31 May 2016 16:31:24 -0400 Received: from science.sciencehorizons.net ([71.41.210.147]:14454 "HELO ns.sciencehorizons.net" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with SMTP id S1750813AbcEaUbX (ORCPT ); Tue, 31 May 2016 16:31:23 -0400 Date: 31 May 2016 16:31:22 -0400 Message-ID: <20160531203122.7243.qmail@ns.sciencehorizons.net> From: "George Spelvin" To: andriy.shevchenko@linux.intel.com Subject: [PATCH] lib/uuid.c: eliminate uuid_[bl]e_index arrays Cc: akpm@linux-foundation.org, bbjorn@mork.no, linux-kernel@vger.kernel.org, linux@sciencehorizons.net, tytso@mit.edu In-Reply-To: <20160530173208.930.qmail@ns.sciencehorizons.net> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org >>From a0d084b1225f2efcf4b5c81871c9c446155b9b13 Mon Sep 17 00:00:00 2001 From: George Spelvin Date: Tue, 31 May 2016 16:00:22 -0400 Subject: [PATCH] lib/uuid.c: eliminate uuid_[bl]e_index arrays Both input and output code is simplified if we instead use a mapping from binary UUID index to ASCII UUID position. This lets us combine hyphen-skipping and endian-swapping into one table. uuid_[bl]e_index were EXPORT_SYMBOLed for no obvious reason; there are no users outside of lib/. The replacement uuid_[bl]e_pos arrays are not exported pending finding a need. The arrays are combined in one contiguous uuid_byte_pos[2][16] array as a micro-optimization for uuid_string(). Choosing between the two can be done by adding 16 rather than loading a second full-word address. x86-64 code size reductions: uuid_string: was 228 bytes, now 134 __uuid_to_bin: was 119 bytes, now 85 Initialized data is also reduced by 16 bytes. Signed-off-by: George Spelvin --- Here's a patch implementing the suggestion I made earlier. This reduces code size, data size, and run time for input and output of UUIDs. This patch is on top of the upper/lower case hex optimization for lib/vsprintf.c I sent earlier. If you don't have it, just ignore the merge conflicts in uuid_string() and take the "after" version. include/linux/uuid.h | 6 ++++-- lib/uuid.c | 24 ++++++++++-------------- lib/vsprintf.c | 32 +++++++++++++------------------- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/include/linux/uuid.h b/include/linux/uuid.h index 2d095fc6..882d9ada 100644 --- a/include/linux/uuid.h +++ b/include/linux/uuid.h @@ -41,8 +41,10 @@ extern void uuid_be_gen(uuid_be *u); bool __must_check uuid_is_valid(const char *uuid); -extern const u8 uuid_le_index[16]; -extern const u8 uuid_be_index[16]; +/* For each binary byte, string offset in ASCII UUID where it appears */ +extern const u8 uuid_byte_pos[2][16]; +#define uuid_be_pos (uuid_byte_pos[0]) +#define uuid_le_pos (uuid_byte_pos[1]) int uuid_le_to_bin(const char *uuid, uuid_le *u); int uuid_be_to_bin(const char *uuid, uuid_be *u); diff --git a/lib/uuid.c b/lib/uuid.c index e116ae5f..8a439caf 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -21,10 +21,10 @@ #include #include -const u8 uuid_le_index[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15}; -EXPORT_SYMBOL(uuid_le_index); -const u8 uuid_be_index[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; -EXPORT_SYMBOL(uuid_be_index); +const u8 uuid_byte_pos[2][16] = { + {0,2,4,6,9,11,14,16,19,21,24,26,28,30,32,34}, /* uuid_be_pos */ + {6,4,2,0,11,9,16,14,19,21,24,26,28,30,32,34} /* uuid_le_pos */ +}; /*************************************************************** * Random UUID interface @@ -97,32 +97,28 @@ bool uuid_is_valid(const char *uuid) } EXPORT_SYMBOL(uuid_is_valid); -static int __uuid_to_bin(const char *uuid, __u8 b[16], const u8 ei[16]) +static int __uuid_to_bin(const char uuid[36], __u8 b[16], const u8 si[16]) { - static const u8 si[16] = {0,2,4,6,9,11,14,16,19,21,24,26,28,30,32,34}; unsigned int i; if (!uuid_is_valid(uuid)) return -EINVAL; - for (i = 0; i < 16; i++) { - int hi = hex_to_bin(uuid[si[i]] + 0); - int lo = hex_to_bin(uuid[si[i]] + 1); - - b[ei[i]] = (hi << 4) | lo; - } + for (i = 0; i < 16; i++) + if (hex2bin(b + i, uuid + si[i], 1) < 0) + return -EINVAL; return 0; } int uuid_le_to_bin(const char *uuid, uuid_le *u) { - return __uuid_to_bin(uuid, u->b, uuid_le_index); + return __uuid_to_bin(uuid, u->b, uuid_le_pos); } EXPORT_SYMBOL(uuid_le_to_bin); int uuid_be_to_bin(const char *uuid, uuid_be *u) { - return __uuid_to_bin(uuid, u->b, uuid_be_index); + return __uuid_to_bin(uuid, u->b, uuid_be_pos); } EXPORT_SYMBOL(uuid_be_to_bin); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 4ee07e89..44faddb1 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1313,38 +1313,32 @@ char *uuid_string(char *buf, char *end, const u8 *addr, struct printf_spec spec, const char *fmt) { char uuid[UUID_STRING_LEN + 1]; - char *p = uuid; int i; - const u8 *index = uuid_be_index; + const u8 *pos = uuid_be_pos; const char *hex = hex_asc; switch (fmt[1]) { + case 'l': + pos = uuid_le_pos; + break; case 'L': - hex = hex_asc_upper; /* fall-through */ - case 'l': - index = uuid_le_index; - break; + pos = uuid_le_pos; /* Fall-through */ case 'B': hex = hex_asc_upper; break; } + /* Format each byte of the raw uuid into the buffer */ for (i = 0; i < 16; i++) { - u8 byte = addr[index[i]]; + u8 byte = addr[i]; + char *p = uuid + pos[i]; - *p++ = hex[byte >> 4]; - *p++ = hex[byte & 0x0f]; - switch (i) { - case 3: - case 5: - case 7: - case 9: - *p++ = '-'; - break; - } + p[0] = hex[byte >> 4]; + p[1] = hex[byte & 0x0f]; } - - *p = 0; + /* Insert the fixed punctuation */ + uuid[23] = uuid[18] = uuid[13] = uuid[8] = '-'; + uuid[UUID_STRING_LEN] = '\0'; return string(buf, end, uuid, spec); } -- 2.8.1