AltiVec runtime detection in Linux

Submitted by markos on Thu, 04/10/2008 - 14:01.
Progress: 
DONE

After a little search I did on Google to find how to detect AltiVec runtime in Linux (I used keywords such as runtime altivec detection and similar), I found that there is no single nice article anywhere that describes something so simple. Thankfully, I got a few good answers from benh and dwmw2 in #mklinux/FreeNode, and I decided to put these down in a cleaned up form.

So here is a little function (also as an attachment) that is tested to work (and will also be in some form part of libfreevec and will also be used for AltiVec detection in SIMDx86 as well). Resubmitted with permission from David Woodhouse.
NOTE: According to David, any methods that use SIGILL handlers (executing AltiVec code and catching the signal when AltiVec is not supported) should be avoided, as they lead to problems such as this one. Use this method instead.

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/auxvec.h>
#include <asm/cputable.h>
 
int have_altivec() {
    static int available = -1;
    int new_avail = 0;
    char fname[64];
    unsigned long buf[64];
    ssize_t count;
    pid_t pid;
    int fd, i;
 
    if (available != -1)
            return available;
 
    pid = getpid();
    snprintf(fname, sizeof(fname)-1, "/proc/%d/auxv", pid);
 
    fd = open(fname, O_RDONLY);
    if (fd < 0)
            goto out;
 more:
    count = read(fd, buf, sizeof(buf));
    if (count < 0)
            goto out_close;
 
    for (i=0; i < (count / sizeof(unsigned long)); i += 2) {
            if (buf[i] == AT_HWCAP) {
            new_avail = !!(buf[i+1] & PPC_FEATURE_HAS_ALTIVEC);
                    goto out_close;
            } else if (buf[i] == AT_NULL) {
                    goto out_close;
            }
    }
 
    if (count == sizeof(buf))
            goto more;
 out_close:
    close(fd);
 out:
    available = new_avail;
    return available;
}
 
int main() {
        int altivec_support = have_altivec();
        printf("Altivec support: %d\n", altivec_support);
        return(0);
}

SIMD

AttachmentSize
altivec_detect.c1.04 KB