Beispiel #1
0
TreeNode*
tree_getNextNode(TreeNode* nodePtr)
{
    if (nodePtr == NULL)
    {
        ERROR_PLAIN_PRINT(Node invalid);
    }

    if (nodePtr->rlink == NULL)
    {
        return NULL;
    }

    return nodePtr->rlink;
}
Beispiel #2
0
int
pci_init(int initSocket_fd)
{
    uint16_t testDevice;
    int nr_sockets = 0;
    int i=0;
    int j=0;
    int ret = 0;
    int access_flags = 0;
    ownaccess = &access;
    ownopen = &open;

    for (i=0; i<MAX_NUM_NODES; i++ )
    {
        socket_bus[i] = "N-A";
        for(j=1;j<MAX_NUM_PCI_DEVICES;j++)
        {
            FD[i][j] = -2;
        }
    }
    /* PCI is only provided by Intel systems */
    if (!cpuid_info.isIntel)
    {
        DEBUG_PLAIN_PRINT(DEBUGLEV_DETAIL, PCI based Uncore performance monitoring only supported on Intel systems);
        return -ENODEV;
    }

    switch (cpuid_info.model)
    {
        case SANDYBRIDGE_EP:
            testDevice = 0x3c44;
            break;
        case IVYBRIDGE_EP:
            testDevice = 0x0e36;
            break;
        case HASWELL_EP:
            testDevice = 0x2f30;
            break;
        default:
            DEBUG_PRINT(DEBUGLEV_INFO,CPU model %s does not support PCI based Uncore performance monitoring, cpuid_info.name);
            return -ENODEV;
            break;
    }

#ifdef LIKWID_USE_HWLOC
        DEBUG_PLAIN_PRINT(DEBUGLEV_DETAIL, Using hwloc to find pci devices);
        ret = hwloc_pci_init(testDevice, socket_bus, &nr_sockets);
        if (ret)
        {
            ERROR_PLAIN_PRINT(Using hwloc to find pci devices failed);
            return -ENODEV;
        }
#else
        DEBUG_PLAIN_PRINT(DEBUGLEV_DETAIL, Using procfs to find pci devices);
        ret = proc_pci_init(testDevice, socket_bus, &nr_sockets);
        if (ret)
        {
            ERROR_PLAIN_PRINT(Using procfs to find pci devices failed);
            return -ENODEV;
        }
#endif

    if (accessClient_mode == ACCESSMODE_DIRECT)
    {
        access_flags = R_OK|W_OK;
    }
    else
    {
        access_flags = F_OK;
    }

    for(i=0;i<nr_sockets;i++)
    {
        for(j=1;j<MAX_NUM_PCI_DEVICES;j++)
        {
            if (pci_devices[j].path != NULL)
            {
                bstring filepath = bformat("%s%s%s",PCI_ROOT_PATH,
                                                    socket_bus[i],
                                                    pci_devices[j].path);
                if (!ownaccess(bdata(filepath),access_flags))
                {
                    FD[i][j] = 0;
                    pci_devices[j].online = 1;
                    if (i==0)
                    {
                        DEBUG_PRINT(DEBUGLEV_DETAIL, PCI device %s (%d) online for socket %d at path %s, pci_devices[j].name,j, i,bdata(filepath));
                    }
                }
                else
                {
Beispiel #3
0
static int
access_client_startDaemon(int cpu_id)
{
    /* Check the function of the daemon here */
    char* filepath;
    char *newargv[] = { NULL };
    char *newenv[] = { NULL };
    char *safeexeprog = TOSTRING(ACCESSDAEMON);
    char exeprog[1024];
    struct sockaddr_un address;
    size_t address_length;
    int  ret;
    pid_t pid;
    int timeout = 1000;
    int socket_fd = -1;

    if (config.daemonPath != NULL)
    {
        strcpy(exeprog, config.daemonPath);
    }
    else
    {
        strcpy(exeprog, safeexeprog);
    }

    if (access(exeprog, X_OK))
    {
        ERROR_PRINT(Failed to find the daemon '%s'\n, exeprog);
        exit(EXIT_FAILURE);
    }

    pid = fork();

    if (pid == 0)
    {
        if (cpu_id >= 0)
        {
            cpu_set_t cpuset;
            CPU_ZERO(&cpuset);
            CPU_SET(cpu_id, &cpuset);
            sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
        }
        ret = execve (exeprog, newargv, newenv);

        if (ret < 0)
        {
            //ERRNO_PRINT;
            ERROR_PRINT(Failed to execute the daemon '%s'\n, exeprog);
            exit(EXIT_FAILURE);
        }
    }
    else if (pid < 0)
    {
        ERROR_PLAIN_PRINT(Failed to fork);
    }

    EXIT_IF_ERROR(socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0), socket() failed);

    address.sun_family = AF_LOCAL;
    address_length = sizeof(address);
    snprintf(address.sun_path, sizeof(address.sun_path), "/tmp/likwid-%d", pid);
    filepath = strdup(address.sun_path);

    while (timeout > 0)
    {
        int res;
        usleep(1000);
        res = connect(socket_fd, (struct sockaddr *) &address, address_length);

        if (res == 0)
        {
            break;
        }

        timeout--;
        DEBUG_PRINT(DEBUGLEV_INFO, Still waiting for socket %s ..., filepath);
    }
    
    if (timeout <= 0)
    {
        ERRNO_PRINT;  /* should hopefully still work, as we make no syscalls in between. */
        fprintf(stderr, "Exiting due to timeout: The socket file at '%s' \
                could not be opened within 10 seconds.\n", filepath);
        fprintf(stderr, "Consult the error message above this to find out why.\n");
        fprintf(stderr, "If the error is 'no such file or directoy', \
                it usually means that likwid-accessD just failed to start.\n");
        exit(EXIT_FAILURE);
    }
Beispiel #4
0
int topology_setName(void)
{
    switch ( cpuid_info.family )
    {
        case P6_FAMILY:
            switch ( cpuid_info.model )
            {
                case PENTIUM_M_BANIAS:
                    cpuid_info.name = pentium_m_b_str;
                    cpuid_info.short_name = short_pm;
                    break;

                case PENTIUM_M_DOTHAN:
                    cpuid_info.name = pentium_m_d_str;
                    cpuid_info.short_name = short_pm;
                    break;

                case CORE_DUO:
                    cpuid_info.name = core_duo_str;
                    cpuid_info.short_name = short_core2;
                    break;

                case CORE2_65:
                    cpuid_info.name = core_2a_str;
                    cpuid_info.short_name = short_core2;
                    break;

                case CORE2_45:
                    cpuid_info.name = core_2b_str;
                    cpuid_info.short_name = short_core2;
                    break;

                case NEHALEM_BLOOMFIELD:
                    cpuid_info.name = nehalem_bloom_str;
                    cpuid_info.short_name = short_nehalem;
                    break;

                case NEHALEM_LYNNFIELD:
                    cpuid_info.name = nehalem_lynn_str;
                    cpuid_info.short_name = short_nehalem;
                    break;

                case NEHALEM_WESTMERE_M:

                case NEHALEM_WESTMERE:
                    cpuid_info.name = nehalem_west_str;
                    cpuid_info.short_name = short_westmere;
                    break;

                case SANDYBRIDGE:
                    cpuid_info.name = sandybridge_str;
                    cpuid_info.short_name = short_sandybridge;
                    break;

                case SANDYBRIDGE_EP:
                    cpuid_info.supportUncore = 1;
                    cpuid_info.name = sandybridge_ep_str;
                    cpuid_info.short_name = short_sandybridge_ep;
                    break;

                case IVYBRIDGE:
                    cpuid_info.name = ivybridge_str;
                    cpuid_info.short_name = short_ivybridge;
                    break;

                case IVYBRIDGE_EP:
                    cpuid_info.supportUncore = 1;
                    cpuid_info.name = ivybridge_ep_str;
                    cpuid_info.short_name = short_ivybridge_ep;
                    break;

                case HASWELL_EP:
                    cpuid_info.supportUncore = 1;
                    cpuid_info.name = haswell_ep_str;
                    cpuid_info.short_name = short_haswell_ep;
                    break;
                case HASWELL:
                case HASWELL_M1:
                case HASWELL_M2:
                    cpuid_info.name = haswell_str;
                    cpuid_info.short_name = short_haswell;
                    break;

                case BROADWELL:
                    cpuid_info.name = broadwell_str;
                    cpuid_info.short_name = short_broadwell;
                    break;
                case BROADWELL_D:
                    cpuid_info.name = broadwell_d_str;
                    cpuid_info.short_name = short_broadwell_d;
                    break;
                case BROADWELL_E:
                    cpuid_info.name = broadwell_ep_str;
                    cpuid_info.short_name = short_broadwell_ep;
                    break;

                case SKYLAKE1:
                case SKYLAKE2:
                    cpuid_info.name = skylake_str;
                    cpuid_info.short_name = short_skylake;
                    break;

                case XEON_PHI2:
                    cpuid_info.name = xeon_phi2_string;
                    cpuid_info.short_name = short_phi2;
                    break;

                case NEHALEM_EX:
                    cpuid_info.name = nehalem_ex_str;
                    cpuid_info.short_name = short_nehalemEX;
                    break;

                case WESTMERE_EX:
                    cpuid_info.name = westmere_ex_str;
                    cpuid_info.short_name = short_westmereEX;
                    break;

                case XEON_MP:
                    cpuid_info.name = xeon_mp_string;
                    cpuid_info.short_name = short_core2;
                    break;

                case ATOM_45:

                case ATOM:
                    cpuid_info.name = atom_45_str;
                    cpuid_info.short_name = short_atom;
                    break;

                case ATOM_32:
                    cpuid_info.name = atom_32_str;
                    cpuid_info.short_name = short_atom;
                    break;

                case ATOM_22:
                    cpuid_info.name = atom_22_str;
                    cpuid_info.short_name = short_atom;
                    break;

                case ATOM_SILVERMONT_E:
                case ATOM_SILVERMONT_C:
                case ATOM_SILVERMONT_Z1:
                case ATOM_SILVERMONT_Z2:
                case ATOM_SILVERMONT_F:
                    cpuid_info.name = atom_silvermont_str;
                    cpuid_info.short_name = short_silvermont;
                    break;
                case ATOM_SILVERMONT_AIR:
                    cpuid_info.name = atom_airmont_str;
                    cpuid_info.short_name = short_silvermont;
                    break;

                default:
                    cpuid_info.name = unknown_intel_str;
                    cpuid_info.short_name = short_unknown;
                    break;
            }
            break;

        case MIC_FAMILY:
            switch ( cpuid_info.model )
            {
                case XEON_PHI:
                    cpuid_info.name = xeon_phi_string;
                    cpuid_info.short_name = short_phi;
                    break;

            }
            break;

        case K8_FAMILY:

            if (cpuid_info.isIntel)
            {
                ERROR_PLAIN_PRINT(Netburst architecture is not supported);
            }

            switch ( cpuid_info.model )
            {
                case OPTERON_DC_E:
                    cpuid_info.name = opteron_dc_e_str;
                    break;

                case OPTERON_DC_F:
                    cpuid_info.name = opteron_dc_f_str;
                    break;

                case ATHLON64_X2:

                case ATHLON64_X2_F:
                    cpuid_info.name = athlon64_str;
                    break;

                case ATHLON64_F1:

                case ATHLON64_F2:
                    cpuid_info.name = athlon64_f_str;
                    break;

                case ATHLON64_X2_G:
                    cpuid_info.name = athlon64_X2_g_str;
                    break;

                case ATHLON64_G1:

                case ATHLON64_G2:
                    cpuid_info.name = athlon64_g_str;
                    break;

                case OPTERON_SC_1MB:
                    cpuid_info.name = opteron_sc_str;
                    break;

                default:
                    cpuid_info.name = amd_k8_str;
                    break;
            }
            cpuid_info.short_name = short_k8;
            break;

        case K10_FAMILY:
            switch ( cpuid_info.model )
            {
                case BARCELONA:
                    cpuid_info.name = barcelona_str;
                    break;

                case SHANGHAI:
                    cpuid_info.name = shanghai_str;
                    break;

                case ISTANBUL:
                    cpuid_info.name = istanbul_str;
                    break;

                case MAGNYCOURS:
                    cpuid_info.name = magnycours_str;
                    break;

                default:
                    cpuid_info.name = unknown_amd_str;
                    break;
            }
            cpuid_info.short_name = short_k10;
            break;

        case K15_FAMILY:
            cpuid_info.name = interlagos_str;
            cpuid_info.short_name = short_k15;
            break;

        case K16_FAMILY:
            cpuid_info.name = kabini_str;
            cpuid_info.short_name = short_k16;
            break;

        default:
            return EXIT_FAILURE;
            break;
    }
    return EXIT_SUCCESS;
}
Beispiel #5
0
void likwid_markerInit(void)
{
    int cpuId = likwid_getProcessorId();
    char* modeStr = getenv("LIKWID_MODE");
    char* maskStr = getenv("LIKWID_MASK");

    if ((modeStr != NULL) && (maskStr != NULL))
    {
        likwid_init = 1;
    }
    else
    {
        return;
    }

    if (!lock_check())
    {
        fprintf(stderr,"Access to performance counters is locked.\n");
        exit(EXIT_FAILURE);
    }

    cpuid_init();
    numa_init();
    affinity_init();
    timer_init();
    hashTable_init();

    for(int i=0; i<MAX_NUM_THREADS; i++) thread_socketFD[i] = -1;
    for(int i=0; i<MAX_NUM_NODES; i++) socket_lock[i] = LOCK_INIT;

    accessClient_mode = atoi(modeStr);
    str2BitMask(maskStr, &counterMask);

    if (accessClient_mode != DAEMON_AM_DIRECT)
    {
        accessClient_init(&thread_socketFD[cpuId]);
    }

    msr_init(thread_socketFD[cpuId]);
    thermal_init(cpuId);

    switch ( cpuid_info.family )
    {
        case P6_FAMILY:

            switch ( cpuid_info.model )
            {
                case PENTIUM_M_BANIAS:

                case PENTIUM_M_DOTHAN:

                    perfmon_counter_map = pm_counter_map;
                    perfmon_numCounters = NUM_COUNTERS_PM;
                    perfmon_numCountersCore = NUM_COUNTERS_CORE_PM;
                    break;

                case ATOM_45:

                case ATOM_32:

                case ATOM_22:

                case ATOM:

                    perfmon_counter_map = core2_counter_map;
                    perfmon_numCounters = NUM_COUNTERS_CORE2;
                    perfmon_numCountersCore = NUM_COUNTERS_CORE_CORE2;
                    break;

                case CORE_DUO:
                    ERROR_PLAIN_PRINT(Unsupported Processor);
                    break;

                case XEON_MP:

                case CORE2_65:

                case CORE2_45:

                    perfmon_counter_map = core2_counter_map;
                    perfmon_numCounters = NUM_COUNTERS_CORE2;
                    perfmon_numCountersCore = NUM_COUNTERS_CORE_CORE2;
                    break;

                case NEHALEM_EX:

                case WESTMERE_EX:

                    perfmon_counter_map = westmereEX_counter_map;
                    perfmon_numCounters = NUM_COUNTERS_WESTMEREEX;
                    perfmon_numCountersCore = NUM_COUNTERS_CORE_WESTMEREEX;
                    perfmon_numCountersUncore = NUM_COUNTERS_UNCORE_WESTMEREEX;
                    break;

                case NEHALEM_BLOOMFIELD:

                case NEHALEM_LYNNFIELD:

                case NEHALEM_WESTMERE_M:

                case NEHALEM_WESTMERE:

                    perfmon_counter_map = nehalem_counter_map;
                    perfmon_numCounters = NUM_COUNTERS_NEHALEM;
                    perfmon_numCountersCore = NUM_COUNTERS_CORE_NEHALEM;
                    perfmon_numCountersUncore = NUM_COUNTERS_UNCORE_NEHALEM;
                    break;

                case IVYBRIDGE:

                case IVYBRIDGE_EP:

                    {
                        int socket_fd = thread_socketFD[cpuId];
                        hasPCICounters = 1;
                        power_init(0); /* FIXME Static coreId is dangerous */
                        pci_init(socket_fd);
                        perfmon_counter_map = ivybridge_counter_map;
                        perfmon_numCounters = NUM_COUNTERS_IVYBRIDGE;
                        perfmon_numCountersCore = NUM_COUNTERS_CORE_IVYBRIDGE;
                        perfmon_numCountersUncore = NUM_COUNTERS_UNCORE_IVYBRIDGE;
                    }
                    break;

                case HASWELL:

                case HASWELL_EX:

                case HASWELL_M1:

                case HASWELL_M2:

                    power_init(0); /* FIXME Static coreId is dangerous */

                    perfmon_counter_map = haswell_counter_map;
                    perfmon_numCounters = NUM_COUNTERS_HASWELL;
                    perfmon_numCountersCore = NUM_COUNTERS_CORE_HASWELL;
                    break;

                case SANDYBRIDGE:

                case SANDYBRIDGE_EP:

                    {
                        int socket_fd = thread_socketFD[cpuId];
                        hasPCICounters = 1;
                        power_init(0); /* FIXME Static coreId is dangerous */
                        pci_init(socket_fd);
                        perfmon_counter_map = sandybridge_counter_map;
                        perfmon_numCounters = NUM_COUNTERS_SANDYBRIDGE;
                        perfmon_numCountersCore = NUM_COUNTERS_CORE_SANDYBRIDGE;
                        perfmon_numCountersUncore = NUM_COUNTERS_UNCORE_SANDYBRIDGE;
                    }
                    break;

                default:
                    ERROR_PLAIN_PRINT(Unsupported Processor);
                    break;
            }
            break;

        case MIC_FAMILY:

            switch ( cpuid_info.model )
            {
                case XEON_PHI:

                    perfmon_counter_map = phi_counter_map;
                    perfmon_numCounters = NUM_COUNTERS_PHI;
                    perfmon_numCountersCore = NUM_COUNTERS_CORE_PHI;
                    break;

                default:
                    ERROR_PLAIN_PRINT(Unsupported Processor);
                    break;
            }
            break;

        case K8_FAMILY:

            perfmon_counter_map = k10_counter_map;
            perfmon_numCounters = NUM_COUNTERS_K10;
            perfmon_numCountersCore = NUM_COUNTERS_CORE_K10;
            break;

        case K10_FAMILY:

            perfmon_counter_map = k10_counter_map;
            perfmon_numCounters = NUM_COUNTERS_K10;
            perfmon_numCountersCore = NUM_COUNTERS_CORE_K10;
            break;

        case K15_FAMILY:

            perfmon_counter_map = interlagos_counter_map;
            perfmon_numCounters = NUM_COUNTERS_INTERLAGOS;
            perfmon_numCountersCore = NUM_COUNTERS_CORE_INTERLAGOS;
            break;

        case K16_FAMILY:

            perfmon_counter_map = kabini_counter_map;
            perfmon_numCounters = NUM_COUNTERS_KABINI;
            perfmon_numCountersCore = NUM_COUNTERS_CORE_KABINI;
            break;

        default:
            ERROR_PLAIN_PRINT(Unsupported Processor);
            break;
    }
}
Beispiel #6
0
int
access_x86_pci_init(const int socket)
{
    int ret = 0;


    if (access_x86_initialized == 0)
    {
        uint16_t testDevice;
        ownaccess = &access;
        ownopen = &open;

        /* PCI is only provided by Intel systems */
        if (!cpuid_info.isIntel)
        {
            DEBUG_PLAIN_PRINT(DEBUGLEV_DETAIL, PCI based Uncore performance monitoring only supported on Intel systems);
            return -ENODEV;
        }
        switch (cpuid_info.model)
        {
            case SANDYBRIDGE_EP:
                testDevice = 0x3c44;
                break;
            case IVYBRIDGE_EP:
                testDevice = 0x0e36;
                break;
            case HASWELL_EP:
                testDevice = 0x2f30;
                break;
            case BROADWELL_D:
                testDevice = 0x6f30;
                break;
            default:
                DEBUG_PRINT(DEBUGLEV_INFO,CPU model %s does not support PCI based Uncore performance monitoring, cpuid_info.name);
                return -ENODEV;
                break;
        }
        if(geteuid() != 0)
        {
            fprintf(stderr, "WARNING\n");
            fprintf(stderr, "Direct access to the PCI Cfg Adressspace is only allowed for uid root!\n");
            fprintf(stderr, "This means you can use performance groups as MEM only as root in direct mode.\n");
            fprintf(stderr, "Alternatively you might want to look into (sys)daemonmode.\n\n");
            return -EPERM;
        }

        for(int i=0; i<MAX_NUM_NODES; i++)
        {
            for(int j=1;j<MAX_NUM_PCI_DEVICES;j++)
            {
                FD[i][j] = -2;
            }
        }

#ifdef LIKWID_USE_HWLOC
        DEBUG_PLAIN_PRINT(DEBUGLEV_DETAIL, Using hwloc to find pci devices);
        ret = hwloc_pci_init(testDevice, socket_bus, &nr_sockets);
        if (ret)
        {
            ERROR_PLAIN_PRINT(Using hwloc to find pci devices failed);
            return -ENODEV;
        }
#else
        DEBUG_PLAIN_PRINT(DEBUGLEV_DETAIL, Using procfs to find pci devices);
        ret = proc_pci_init(testDevice, socket_bus, &nr_sockets);
        if (ret)
        {
            ERROR_PLAIN_PRINT(Using procfs to find pci devices failed);
            return -ENODEV;
        }
#endif
    }


    for(int j=1;j<MAX_NUM_PCI_DEVICES;j++)
    {
        if ((pci_devices[j].path != NULL) && (FD[socket][j] == -2))
        {
            bstring filepath = bformat("%s%s%s",PCI_ROOT_PATH,
                                                socket_bus[socket],
                                                pci_devices[j].path);
            if (!ownaccess(bdata(filepath),X_OK))
            {
                FD[socket][j] = 0;
                pci_devices[j].online = 1;
                if (access_x86_initialized == 0)
                {
                    DEBUG_PRINT(DEBUGLEV_DETAIL, PCI device %s (%d) online for socket %d at path %s, pci_devices[j].name,j, socket,bdata(filepath));
                    if (!ownaccess(bdata(filepath),R_OK|W_OK))
                    {
                        ERROR_PRINT(PCI device %s (%d) online for socket %d at path %s but not accessible, pci_devices[j].name,j, socket,bdata(filepath));
                    }
                }
Beispiel #7
0
static int
nodeProcessorList(int node, uint32_t** list)
{
    FILE *fp;
    bstring filename;
    int count = 0;
    bstring src;
    int i,j;
    struct bstrList* tokens;
    unsigned long val;
    char* endptr;
    int cursor=0;
//    int unitSize = (int) (sizeof(unsigned long)*8);
    int unitSize = (int) 32; /* 8 nibbles */

    *list = (uint32_t*) malloc(MAX_NUM_THREADS * sizeof(uint32_t));
    if (!(*list))
    {
        return -ENOMEM;
    }

    /* the cpumap interface should be always there */
    filename = bformat("/sys/devices/system/node/node%d/cpumap", node); 

    if (NULL != (fp = fopen (bdata(filename), "r"))) 
    {

        src = bread ((bNread) fread, fp);
        tokens = bsplit(src,',');

        for (i=(tokens->qty-1); i>=0 ;i--)
        {
            val = strtoul((char*) tokens->entry[i]->data, &endptr, 16);

            if ((errno != 0 && val == LONG_MAX )
                    || (errno != 0 && val == 0)) 
            {
                return -EFAULT;
            }

            if (endptr == (char*) tokens->entry[i]->data) 
            {
                ERROR_PLAIN_PRINT(No digits were found);
                return -EFAULT;
            }

            if (val != 0UL)
            {
                for (j=0; j<unitSize; j++)
                {
                    if (val&(1UL<<j))
                    {
                        if (count < MAX_NUM_THREADS)
                        {
                            (*list)[count] = (j+cursor);
                        }
                        else
                        {
                            ERROR_PRINT(Number Of threads %d too large,count);
                            return -EFAULT;
                        }
                        count++;
                    }
                }
            }
            cursor += unitSize;
        }

        bstrListDestroy(tokens);
        bdestroy(src);
        bdestroy(filename);
        fclose(fp); 

        /* FIXME: CPU list here is not physical cores first but numerical sorted */


        return count;
    }

    /* something went wrong */
    return -1;
}
Beispiel #8
0
void hwloc_init_cacheTopology(void)
{
    int maxNumLevels=0;
    int id=0;
    CacheLevel* cachePool = NULL;
    hwloc_obj_t obj;
    int depth;
    int d;

    /* Sum up all depths with caches */
    depth = hwloc_topology_get_depth(hwloc_topology);
    for (d = 0; d < depth; d++)
    {
        if (hwloc_get_depth_type(hwloc_topology, d) == HWLOC_OBJ_CACHE)
            maxNumLevels++;
    }
    cachePool = (CacheLevel*) malloc(maxNumLevels * sizeof(CacheLevel));
    /* Start at the bottom of the tree to get all cache levels in order */
    depth = hwloc_topology_get_depth(hwloc_topology);
    id = 0;
    for(d=depth-1;d >= 0; d--)
    {
        /* We only need caches, so skip other levels */
        if (hwloc_get_depth_type(hwloc_topology, d) != HWLOC_OBJ_CACHE)
        {
            continue;
        }
        /* Get the cache object */
        obj = hwloc_get_obj_by_depth(hwloc_topology, d, 0);
        /* All caches have this attribute, so safe to access */
        switch (obj->attr->cache.type)
        {
            case HWLOC_OBJ_CACHE_DATA:
                cachePool[id].type = DATACACHE;
                break;
            case HWLOC_OBJ_CACHE_INSTRUCTION:
                cachePool[id].type = INSTRUCTIONCACHE;
                break;
            case HWLOC_OBJ_CACHE_UNIFIED:
                cachePool[id].type = UNIFIEDCACHE;
                break;
            default:
                cachePool[id].type = NOCACHE;
                break;
        }

        cachePool[id].associativity = obj->attr->cache.associativity;
        cachePool[id].level = obj->attr->cache.depth;
        cachePool[id].lineSize = obj->attr->cache.linesize;
        cachePool[id].size = obj->attr->cache.size;
        cachePool[id].sets = 0;
        if ((cachePool[id].associativity * cachePool[id].lineSize) != 0)
        {
            cachePool[id].sets = cachePool[id].size /
                (cachePool[id].associativity * cachePool[id].lineSize);
        }
        /* Count all HWThreads below the current cache */
        cachePool[id].threads = hwloc_record_objs_of_type_below_obj(
                        hwloc_topology, obj, HWLOC_OBJ_PU, NULL, NULL);
        /* We need to read the inclusiveness from CPUID, no possibility in hwloc */
        switch ( cpuid_info.family )
        {
            case MIC_FAMILY:
            case P6_FAMILY:
                cachePool[id].inclusive = readCacheInclusiveIntel(cachePool[id].level);
                break;
            case K16_FAMILY:
            case K15_FAMILY:
                cachePool[id].inclusive = readCacheInclusiveAMD(cachePool[id].level);
                break;
            /* For K8 and K10 it is known that they are inclusive */
            case K8_FAMILY:
            case K10_FAMILY:
                cachePool[id].inclusive = 1;
                break;
            default:
                ERROR_PLAIN_PRINT(Processor is not supported);
                break;
        }
        id++;
    }

    cpuid_topology.numCacheLevels = maxNumLevels;
    cpuid_topology.cacheLevels = cachePool;
    return;
}