May 13, 2011

How to detect Altivec availability on linux/ppc at runtime

by orzel
Categories: Gentoo, Linux kernel
Tags: ,
Comments: Leave a Comment

It is easy to find information on how to detect the availability of the different SSE instructions sets on the x86 platform.. but this get trickier when you’re looking after AltiVec.

This page provide some code and a link explaining why methods based on try and catch exception are bad:

http://freevec.org/function/altivec_runtime_detection_linux

I did few modifications to this code, that I consider enhancements:

  • use /proc/self/ instead of /proc/%d/ based on getpid() to simplify the code, as suggested in comment
  • use of bool for the result variable and the return value
  • clean ugly use of goto when possible
  • do not cache the result in a static variable
#include <fcntl.h>
#include <linux/auxvec.h>
#include <asm/cputable.h>

// from http://freevec.org/function/altivec_runtime_detection_linux
static inline bool altivecAvailable(void)
{
    bool result = false;
    unsigned long buf[64];
    ssize_t count;
    int fd, i;

    fd = open("/proc/self/auxv", O_RDONLY);
    if (fd < 0) {
        return false;
    }
    // loop on reading
    do {
        count = read(fd, buf, sizeof(buf));
        if (count < 0){                                                                                                                                                     
            break;                                                                                                                                                          
        for (i=0; i < (count / sizeof(unsigned long)); i += 2) {                                                                                                            
            if (buf[i] == AT_HWCAP) {                                                                                                                                       
                result = !!(buf[i+1] & PPC_FEATURE_HAS_ALTIVEC);                                                                                                            
                goto out_close;
            } else if (buf[i] == AT_NULL)
                goto out_close;
        }
    } while (count == sizeof(buf));
out_close:
    close(fd);
    return result;
}