Home | History | Annotate | Download | only in powerpc
      1 /*
      2  * Copyright 2013-2015, Michael Ellerman, IBM Corp.
      3  * Licensed under GPLv2.
      4  */
      5 
      6 #define _GNU_SOURCE	/* For CPU_ZERO etc. */
      7 
      8 #include <elf.h>
      9 #include <errno.h>
     10 #include <fcntl.h>
     11 #include <link.h>
     12 #include <sched.h>
     13 #include <stdio.h>
     14 #include <sys/stat.h>
     15 #include <sys/types.h>
     16 #include <unistd.h>
     17 
     18 #include "utils.h"
     19 
     20 static char auxv[4096];
     21 
     22 int read_auxv(char *buf, ssize_t buf_size)
     23 {
     24 	ssize_t num;
     25 	int rc, fd;
     26 
     27 	fd = open("/proc/self/auxv", O_RDONLY);
     28 	if (fd == -1) {
     29 		perror("open");
     30 		return -errno;
     31 	}
     32 
     33 	num = read(fd, buf, buf_size);
     34 	if (num < 0) {
     35 		perror("read");
     36 		rc = -EIO;
     37 		goto out;
     38 	}
     39 
     40 	if (num > buf_size) {
     41 		printf("overflowed auxv buffer\n");
     42 		rc = -EOVERFLOW;
     43 		goto out;
     44 	}
     45 
     46 	rc = 0;
     47 out:
     48 	close(fd);
     49 	return rc;
     50 }
     51 
     52 void *find_auxv_entry(int type, char *auxv)
     53 {
     54 	ElfW(auxv_t) *p;
     55 
     56 	p = (ElfW(auxv_t) *)auxv;
     57 
     58 	while (p->a_type != AT_NULL) {
     59 		if (p->a_type == type)
     60 			return p;
     61 
     62 		p++;
     63 	}
     64 
     65 	return NULL;
     66 }
     67 
     68 void *get_auxv_entry(int type)
     69 {
     70 	ElfW(auxv_t) *p;
     71 
     72 	if (read_auxv(auxv, sizeof(auxv)))
     73 		return NULL;
     74 
     75 	p = find_auxv_entry(type, auxv);
     76 	if (p)
     77 		return (void *)p->a_un.a_val;
     78 
     79 	return NULL;
     80 }
     81 
     82 int pick_online_cpu(void)
     83 {
     84 	cpu_set_t mask;
     85 	int cpu;
     86 
     87 	CPU_ZERO(&mask);
     88 
     89 	if (sched_getaffinity(0, sizeof(mask), &mask)) {
     90 		perror("sched_getaffinity");
     91 		return -1;
     92 	}
     93 
     94 	/* We prefer a primary thread, but skip 0 */
     95 	for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8)
     96 		if (CPU_ISSET(cpu, &mask))
     97 			return cpu;
     98 
     99 	/* Search for anything, but in reverse */
    100 	for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--)
    101 		if (CPU_ISSET(cpu, &mask))
    102 			return cpu;
    103 
    104 	printf("No cpus in affinity mask?!\n");
    105 	return -1;
    106 }
    107