mirror of
git://sourceware.org/git/glibc.git
synced 2025-02-23 13:09:58 +08:00
powerpc: add sysconf support for cache geometries
There is currently no "cross-platform" (x86 and POWER) support for determining the cacheline size. This patch adds support to sysconf() to correctly report cacheline sizes based on the information in the auxilliary vector. Thus, using sysconf() is a cross-platform (x86 and POWER) solution for determining cacheline sizes. Support is added (on powerpc) for: _SC_LEVEL1_ICACHE_SIZE _SC_LEVEL1_ICACHE_ASSOC _SC_LEVEL1_ICACHE_LINESIZE _SC_LEVEL1_DCACHE_SIZE _SC_LEVEL1_DCACHE_ASSOC _SC_LEVEL1_DCACHE_LINESIZE _SC_LEVEL2_CACHE_SIZE _SC_LEVEL2_CACHE_ASSOC _SC_LEVEL2_CACHE_LINESIZE _SC_LEVEL3_CACHE_SIZE _SC_LEVEL3_CACHE_ASSOC _SC_LEVEL3_CACHE_LINESIZE * 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.
This commit is contained in:
parent
d6bd839b9a
commit
cdfbe5037f
11
ChangeLog
11
ChangeLog
@ -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>
|
2017-06-09 Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
|
||||||
|
|
||||||
* include/sys/auxv.h (__getauxval): Add a prototype and its
|
* include/sys/auxv.h (__getauxval): Add a prototype and its
|
||||||
|
@ -29,6 +29,7 @@ ifeq ($(subdir),misc)
|
|||||||
sysdep_headers += bits/ppc.h
|
sysdep_headers += bits/ppc.h
|
||||||
sysdep_routines += get_timebase_freq
|
sysdep_routines += get_timebase_freq
|
||||||
tests += test-gettimebasefreq
|
tests += test-gettimebasefreq
|
||||||
|
tests += test-powerpc-linux-sysconf
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(subdir),nptl)
|
ifeq ($(subdir),nptl)
|
||||||
|
96
sysdeps/unix/sysv/linux/powerpc/sysconf.c
Normal file
96
sysdeps/unix/sysv/linux/powerpc/sysconf.c
Normal file
@ -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"
|
73
sysdeps/unix/sysv/linux/powerpc/test-powerpc-linux-sysconf.c
Normal file
73
sysdeps/unix/sysv/linux/powerpc/test-powerpc-linux-sysconf.c
Normal file
@ -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>
|
Loading…
Reference in New Issue
Block a user