diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/Makefile | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/sysconf.c | 96 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/test-powerpc-linux-sysconf.c | 73 |
4 files changed, 181 insertions, 0 deletions
@@ -1,3 +1,14 @@ +2017-06-09 Paul A. Clarke <pc@us.ibm.com> + + * sysdeps/unix/sysv/linux/powerpc/sysconf.c: New file. + Add powerpc-specific overrides for L1, L2, L3 CACHE_SIZEs, + CACHE_ASSOCs, and CACHE_LINESIZEs, retrieving from auxv. + * sysdeps/unix/sysv/linux/powerpc/test-powerpc-linux-sysconf.c: + New file. Invoke newly supported sysconf values for powerpc, + and report results. If none are supported, report so. + * sysdeps/unix/sysv/linux/powerpc/Makefile (tests): Add new test, + tst-sysconf. + 2017-06-09 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com> * include/sys/auxv.h (__getauxval): Add a prototype and its diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile index 2cfb46e..c16172c 100644 --- a/sysdeps/unix/sysv/linux/powerpc/Makefile +++ b/sysdeps/unix/sysv/linux/powerpc/Makefile @@ -29,6 +29,7 @@ ifeq ($(subdir),misc) sysdep_headers += bits/ppc.h sysdep_routines += get_timebase_freq tests += test-gettimebasefreq +tests += test-powerpc-linux-sysconf endif ifeq ($(subdir),nptl) diff --git a/sysdeps/unix/sysv/linux/powerpc/sysconf.c b/sysdeps/unix/sysv/linux/powerpc/sysconf.c new file mode 100644 index 0000000..10c4aa0 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/sysconf.c @@ -0,0 +1,96 @@ +/* Get system-specific information at run-time. Linux/powerpc version. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <unistd.h> +#include <sys/auxv.h> + +static long linux_sysconf (int name); + +static long +auxv2sysconf (unsigned long type) +{ + long rc; + rc = __getauxval (type); + if (rc == 0) + { + __set_errno (EINVAL); + rc = -1; + } + return rc; +} + +static long +auxv2sysconf_cache_associativity (unsigned long type) +{ + long rc; + rc = auxv2sysconf (type); + if (rc != -1) + rc = (rc & 0xffff0000) >> 16; + return rc; +} + +static long +auxv2sysconf_cache_linesize (unsigned long type) +{ + long rc; + rc = auxv2sysconf (type); + if (rc != -1) + rc = rc & 0xffff; + return rc; +} + +/* Get the value of the system variable NAME. */ +long int +__sysconf (int name) +{ + switch (name) + { + case _SC_LEVEL1_ICACHE_SIZE: + return auxv2sysconf (AT_L1I_CACHESIZE); + case _SC_LEVEL1_ICACHE_ASSOC: + return auxv2sysconf_cache_associativity (AT_L1I_CACHEGEOMETRY); + case _SC_LEVEL1_ICACHE_LINESIZE: + return auxv2sysconf_cache_linesize (AT_L1I_CACHEGEOMETRY); + case _SC_LEVEL1_DCACHE_SIZE: + return auxv2sysconf (AT_L1D_CACHESIZE); + case _SC_LEVEL1_DCACHE_ASSOC: + return auxv2sysconf_cache_associativity (AT_L1D_CACHEGEOMETRY); + case _SC_LEVEL1_DCACHE_LINESIZE: + return auxv2sysconf_cache_linesize (AT_L1D_CACHEGEOMETRY); + case _SC_LEVEL2_CACHE_SIZE: + return auxv2sysconf (AT_L2_CACHESIZE); + case _SC_LEVEL2_CACHE_ASSOC: + return auxv2sysconf_cache_associativity (AT_L2_CACHEGEOMETRY); + case _SC_LEVEL2_CACHE_LINESIZE: + return auxv2sysconf_cache_linesize (AT_L2_CACHEGEOMETRY); + case _SC_LEVEL3_CACHE_SIZE: + return auxv2sysconf (AT_L3_CACHESIZE); + case _SC_LEVEL3_CACHE_ASSOC: + return auxv2sysconf_cache_associativity (AT_L3_CACHEGEOMETRY); + case _SC_LEVEL3_CACHE_LINESIZE: + return auxv2sysconf_cache_linesize (AT_L3_CACHEGEOMETRY); + default: + return linux_sysconf (name); + } +} + +/* Now the generic Linux version. */ +#undef __sysconf +#define __sysconf static linux_sysconf +#include "../sysconf.c" diff --git a/sysdeps/unix/sysv/linux/powerpc/test-powerpc-linux-sysconf.c b/sysdeps/unix/sysv/linux/powerpc/test-powerpc-linux-sysconf.c new file mode 100644 index 0000000..94e9f41 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/test-powerpc-linux-sysconf.c @@ -0,0 +1,73 @@ +/* Check use of sysconf() for cache geometries. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* Test use of sysconf() to get cache sizes, cache set associativity + and cache line sizes. */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <support/test-driver.h> + +#define call_str(f, name) f(name, #name) + +long +do_sysconf (int name, const char * str) +{ + int rc = 0; + long val; + errno = 0; + val = sysconf (name); + if (val == -1) { + if (errno != EINVAL) { + printf("error: sysconf(%s): unexpected errno(%d)\n", str, errno); + exit (1); + } + printf ("info: sysconf(%s): unsupported\n", str); + rc = 1; + } else + printf ("sysconf(%s) = 0x%lx (%ld)\n", str, val, val); + return rc; +} + +static int +do_test (void) +{ + int rc = 0; + + rc += call_str (do_sysconf, _SC_LEVEL1_ICACHE_SIZE); + rc += call_str (do_sysconf, _SC_LEVEL1_ICACHE_ASSOC); + rc += call_str (do_sysconf, _SC_LEVEL1_ICACHE_LINESIZE); + rc += call_str (do_sysconf, _SC_LEVEL1_DCACHE_SIZE); + rc += call_str (do_sysconf, _SC_LEVEL1_DCACHE_ASSOC); + rc += call_str (do_sysconf, _SC_LEVEL1_DCACHE_LINESIZE); + rc += call_str (do_sysconf, _SC_LEVEL2_CACHE_SIZE); + rc += call_str (do_sysconf, _SC_LEVEL2_CACHE_ASSOC); + rc += call_str (do_sysconf, _SC_LEVEL2_CACHE_LINESIZE); + rc += call_str (do_sysconf, _SC_LEVEL3_CACHE_SIZE); + rc += call_str (do_sysconf, _SC_LEVEL3_CACHE_ASSOC); + rc += call_str (do_sysconf, _SC_LEVEL3_CACHE_LINESIZE); + + if (rc) + return EXIT_UNSUPPORTED; + return 0; +} + +#include <support/test-driver.c> |