AltiVec runtime detection in Linux

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. 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.
UPDATE: Found this page, which points back to this one and I admit I agree with the author, his version looks cleaner, but converted it to work with ints instead of bools (no bool in C). Thanks to Thomas Capricelli.

#include <stdio.h>
#include <fcntl.h>
#include <linux/auxvec.h>
#include <asm/cputable.h>
 
static inline int altivecAvailable(void)
{
    int result = 0;
    unsigned long buf[64];
    ssize_t count;
    int fd, i;
 
    fd = open("/proc/self/auxv", O_RDONLY);
    if (fd < 0) {
        return 0;
    }
    // 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;
}
 
int main() {
        int altivec_support = altivecAvailable();
        printf("Altivec support: %d\n", altivec_support);
        return(altivec_support);
}

AttachmentSize
File altivec_detect.c1.08 KB
Tags: