From patchwork Sat Aug 24 04:13:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Zammit X-Patchwork-Id: 34260 Received: (qmail 117593 invoked by alias); 24 Aug 2019 04:14:05 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 117585 invoked by uid 89); 24 Aug 2019 04:14:04 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 spammy=dimensions, 8488 X-HELO: mail-pf1-f182.google.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zamaudio-com.20150623.gappssmtp.com; s=20150623; h=to:from:subject:openpgp:autocrypt:message-id:date:user-agent :mime-version:content-language; bh=cvG4DMXe6c0Xy2xMvvIMMiUrAtkRTUzVFLKuGY1UlAc=; b=ctgUDoZG4WgXMYGu0sFzkzgbmQIbxRaEcP+pfEWBUwfl8SnalS6sTeyRXLpEjNRrTH wjVMsmXOqfgSUsf4tmXiJyYTc+mjIqNx+cSgYNXyJXe/4vWhJi902cjWOLq+IqW545DZ 1DqI6LRyJrDgObQudsa3sWL2B2cLZ9Eb3VNQ+dfr68VoyU3lPnb+BzL09biuRlBpZrLz pOT29sWjMzZXg/AUACkxx9YsdxNT6sKahGyOspTdbIttKg7WLTBswOKGebwysmm98YuT X8bSbLMrlHE9avqp3mYFNhgwmnI3n+474J9QZ3eS5jsPAidirLuaqs2CZlykRUe9p3WO gHww== Return-Path: To: libc-alpha From: Damien Zammit Subject: Host endian independence Openpgp: preference=signencrypt Message-ID: <18c8a820-b2c4-8ab2-58d1-8d8c851dbf01@zamaudio.com> Date: Sat, 24 Aug 2019 14:13:55 +1000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 MIME-Version: 1.0 Hi there, Given that GCC is smart enough to optimize bitshifts of bytes to casts followed by bswaps if necessary on machines that have such instructions, I propose to remove most (if not all) dependence on BYTE_ORDER in glibc so that the same code can be written for any host - this will fix some edge cases for middle endian machines and make the code easier to read. There does not seem to be any performance hit (at least on x86 achitectures) by making the code host endian independent by choosing a particular endian for streams and interpreting all streams in the correct endian using bitshifts when streams are 4-byte aligned. (0x11 << 8) | 0x22 = 0x1122 on any host endian machine. Please see attached patches for proof of concept, which remove dependence on BYTE_ORDER for two subfolders of glibc. If this is a desirable change, please let me know and I can continue this work. Thanks, Damien Zammit From 32a3f800b3977bb7c0826e231c89c8a242cc5e69 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Thu, 22 Aug 2019 20:15:51 +1000 Subject: [PATCH 3/3] catgets: Remove dependence on BYTE_ORDER --- catgets/gencat.c | 42 +++++++++++++++++++----------------------- catgets/open_catalog.c | 31 ++++++++++++------------------- 2 files changed, 31 insertions(+), 42 deletions(-) diff --git a/catgets/gencat.c b/catgets/gencat.c index f0d47ae0..e4b73e5d 100644 --- a/catgets/gencat.c +++ b/catgets/gencat.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,10 +44,6 @@ #include "catgetsinfo.h" - -#define SWAPU32(w) \ - (((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24)) - struct message_list { int number; @@ -852,7 +848,8 @@ write_out (struct catalog *catalog, const char *output_name, struct obstack string_pool; const char *strings; size_t strings_size; - uint32_t *array1, *array2; + uint32_t *array1; + uint8_t buf[8]; size_t cnt; int fd; @@ -932,8 +929,6 @@ write_out (struct catalog *catalog, const char *output_name, array1 = (uint32_t *) alloca (best_size * best_depth * sizeof (uint32_t) * 3); memset (array1, '\0', best_size * best_depth * sizeof (uint32_t) * 3); - array2 - = (uint32_t *) alloca (best_size * best_depth * sizeof (uint32_t) * 3); obstack_init (&string_pool); set_run = catalog->all_sets; @@ -969,10 +964,6 @@ write_out (struct catalog *catalog, const char *output_name, strings_size = obstack_object_size (&string_pool); strings = obstack_finish (&string_pool); - /* Compute ARRAY2 by changing the byte order. */ - for (cnt = 0; cnt < best_size * best_depth * 3; ++cnt) - array2[cnt] = SWAPU32 (array1[cnt]); - /* Now we can write out the whole data. */ if (strcmp (output_name, "-") == 0 || strcmp (output_name, "/dev/stdout") == 0) @@ -986,19 +977,24 @@ write_out (struct catalog *catalog, const char *output_name, } /* Write out header. */ - write (fd, &obj, sizeof (obj)); + write_le32 (buf, obj.magic); + write (fd, buf, sizeof (uint32_t)); + write_le32 (buf, obj.plane_size); + write (fd, buf, sizeof (uint32_t)); + write_le32 (buf, obj.plane_depth); + write (fd, buf, sizeof (uint32_t)); + /* Nothing to write for obj.name_ptr - it is 0 bytes itself */ /* We always write out the little endian version of the index - arrays. */ -#if __BYTE_ORDER == __LITTLE_ENDIAN - write (fd, array1, best_size * best_depth * sizeof (uint32_t) * 3); - write (fd, array2, best_size * best_depth * sizeof (uint32_t) * 3); -#elif __BYTE_ORDER == __BIG_ENDIAN - write (fd, array2, best_size * best_depth * sizeof (uint32_t) * 3); - write (fd, array1, best_size * best_depth * sizeof (uint32_t) * 3); -#else -# error Cannot handle __BYTE_ORDER byte order -#endif + array (LE then BE) */ + for (cnt = 0; cnt < best_size * best_depth * 3; ++cnt) { + write_le32 (buf, array1[cnt]); + write (fd, buf, sizeof (uint32_t)); + } + for (cnt = 0; cnt < best_size * best_depth * 3; ++cnt) { + write_be32 (buf, array1[cnt]); + write (fd, buf, sizeof (uint32_t)); + } /* Finally write the strings. */ write (fd, strings, strings_size); diff --git a/catgets/open_catalog.c b/catgets/open_catalog.c index 9aa6a09f..5c124073 100644 --- a/catgets/open_catalog.c +++ b/catgets/open_catalog.c @@ -16,8 +16,7 @@ License along with the GNU C Library; if not, see . */ -#include -#include +#include #include #include #include @@ -32,9 +31,6 @@ #include -#define SWAPU32(w) bswap_32 (w) - - int __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, __nl_catd catalog) @@ -255,11 +251,11 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, } /* Determine whether the file is a catalog file and if yes whether - it is written using the correct byte order. Else we have to swap - the values. */ - if (__glibc_likely (catalog->file_ptr->magic == CATGETS_MAGIC)) + it is written using the correct byte order. Else we have to read + the values in opposite endian. */ + if (__glibc_likely (read_le32 (&catalog->file_ptr->magic) == CATGETS_MAGIC)) swapping = 0; - else if (catalog->file_ptr->magic == SWAPU32 (CATGETS_MAGIC)) + else if (read_be32 (&catalog->file_ptr->magic) == CATGETS_MAGIC) swapping = 1; else { @@ -275,23 +271,20 @@ __open_catalog (const char *cat_name, const char *nlspath, const char *env_var, goto close_unlock_return; } -#define SWAP(x) (swapping ? SWAPU32 (x) : (x)) +#define READ32(x) (swapping ? read_be32 (x) : read_le32 (x)) /* Get dimensions of the used hashing table. */ - catalog->plane_size = SWAP (catalog->file_ptr->plane_size); - catalog->plane_depth = SWAP (catalog->file_ptr->plane_depth); + catalog->plane_size = READ32 (&catalog->file_ptr->plane_size); + catalog->plane_depth = READ32 (&catalog->file_ptr->plane_depth); /* The file contains two versions of the pointer tables. Pick the right one for the local byte order. */ -#if __BYTE_ORDER == __LITTLE_ENDIAN - catalog->name_ptr = &catalog->file_ptr->name_ptr[0]; -#elif __BYTE_ORDER == __BIG_ENDIAN - catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size + if (__glibc_unlikely (swapping)) + catalog->name_ptr = &catalog->file_ptr->name_ptr[catalog->plane_size * catalog->plane_depth * 3]; -#else -# error Cannot handle __BYTE_ORDER byte order -#endif + else + catalog->name_ptr = &catalog->file_ptr->name_ptr[0]; /* The rest of the file contains all the strings. They are addressed relative to the position of the first string. */ -- 2.13.1