2015-11-24 13:05:38 +11:00
/*
* Copyright 2013 - 2015 , Michael Ellerman , IBM Corp .
* Licensed under GPLv2 .
*/
2015-12-16 18:59:31 +11:00
# define _GNU_SOURCE /* For CPU_ZERO etc. */
2015-11-24 13:05:38 +11:00
# include <elf.h>
# include <errno.h>
# include <fcntl.h>
# include <link.h>
2015-12-16 18:59:31 +11:00
# include <sched.h>
2015-11-24 13:05:38 +11:00
# include <stdio.h>
2018-07-26 22:24:57 +10:00
# include <string.h>
2015-11-24 13:05:38 +11:00
# include <sys/stat.h>
# include <sys/types.h>
2018-07-26 22:24:57 +10:00
# include <sys/utsname.h>
2015-11-24 13:05:38 +11:00
# include <unistd.h>
# include "utils.h"
static char auxv [ 4096 ] ;
2017-02-06 21:13:27 +11:00
int read_auxv ( char * buf , ssize_t buf_size )
2015-11-24 13:05:38 +11:00
{
ssize_t num ;
2017-02-06 21:13:27 +11:00
int rc , fd ;
2015-11-24 13:05:38 +11:00
fd = open ( " /proc/self/auxv " , O_RDONLY ) ;
if ( fd = = - 1 ) {
perror ( " open " ) ;
2017-02-06 21:13:27 +11:00
return - errno ;
2015-11-24 13:05:38 +11:00
}
2017-02-06 21:13:27 +11:00
num = read ( fd , buf , buf_size ) ;
2015-11-24 13:05:38 +11:00
if ( num < 0 ) {
perror ( " read " ) ;
2017-02-06 21:13:27 +11:00
rc = - EIO ;
2015-11-24 13:05:38 +11:00
goto out ;
}
2017-02-06 21:13:27 +11:00
if ( num > buf_size ) {
printf ( " overflowed auxv buffer \n " ) ;
rc = - EOVERFLOW ;
2015-11-24 13:05:38 +11:00
goto out ;
}
2017-02-06 21:13:27 +11:00
rc = 0 ;
out :
close ( fd ) ;
return rc ;
}
void * find_auxv_entry ( int type , char * auxv )
{
ElfW ( auxv_t ) * p ;
2015-11-24 13:05:38 +11:00
p = ( ElfW ( auxv_t ) * ) auxv ;
while ( p - > a_type ! = AT_NULL ) {
2017-02-06 21:13:27 +11:00
if ( p - > a_type = = type )
return p ;
2015-11-24 13:05:38 +11:00
p + + ;
}
2017-02-06 21:13:27 +11:00
return NULL ;
}
void * get_auxv_entry ( int type )
{
ElfW ( auxv_t ) * p ;
if ( read_auxv ( auxv , sizeof ( auxv ) ) )
return NULL ;
p = find_auxv_entry ( type , auxv ) ;
if ( p )
return ( void * ) p - > a_un . a_val ;
return NULL ;
2015-11-24 13:05:38 +11:00
}
2015-12-16 18:59:31 +11:00
int pick_online_cpu ( void )
{
cpu_set_t mask ;
int cpu ;
CPU_ZERO ( & mask ) ;
if ( sched_getaffinity ( 0 , sizeof ( mask ) , & mask ) ) {
perror ( " sched_getaffinity " ) ;
return - 1 ;
}
/* We prefer a primary thread, but skip 0 */
for ( cpu = 8 ; cpu < CPU_SETSIZE ; cpu + = 8 )
if ( CPU_ISSET ( cpu , & mask ) )
return cpu ;
/* Search for anything, but in reverse */
for ( cpu = CPU_SETSIZE - 1 ; cpu > = 0 ; cpu - - )
if ( CPU_ISSET ( cpu , & mask ) )
return cpu ;
printf ( " No cpus in affinity mask?! \n " ) ;
return - 1 ;
}
2018-07-26 22:24:57 +10:00
bool is_ppc64le ( void )
{
struct utsname uts ;
int rc ;
errno = 0 ;
rc = uname ( & uts ) ;
if ( rc ) {
perror ( " uname " ) ;
return false ;
}
return strcmp ( uts . machine , " ppc64le " ) = = 0 ;
}