Skip to content

Commit 4265a86

Browse files
Patryk Wlazlynlenb
authored andcommitted
tools/power turbostat: Add PMT directory iterator helper
PMT directories exposed in sysfs use the following pattern: telem%u for example: telem0, telem2, telem3, ..., telem15, telem16 This naming scheme preserves the ordering from the PCIe discovery, which is important to correctly map the telemetry directory to the specific domain (cpu, core, package etc). Because readdir() traverses the entries in alphabetical order, causing for example "telem13" to be traversed before "telem3", it is necessary to use scandir() with custom compare() callback to preserve the PCIe ordering. Signed-off-by: Patryk Wlazlyn <[email protected]> Signed-off-by: Len Brown <[email protected]>
1 parent 089134c commit 4265a86

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

tools/power/x86/turbostat/turbostat.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,93 @@ struct pmt_counter {
15891589
struct pmt_domain_info *domains;
15901590
};
15911591

1592+
/*
1593+
* PMT telemetry directory iterator.
1594+
* Used to iterate telemetry files in sysfs in correct order.
1595+
*/
1596+
struct pmt_diriter_t
1597+
{
1598+
DIR *dir;
1599+
struct dirent **namelist;
1600+
unsigned int num_names;
1601+
unsigned int current_name_idx;
1602+
};
1603+
1604+
int pmt_telemdir_filter(const struct dirent *e)
1605+
{
1606+
unsigned int dummy;
1607+
return sscanf(e->d_name, "telem%u", &dummy);
1608+
}
1609+
1610+
int pmt_telemdir_sort(const struct dirent **a, const struct dirent **b)
1611+
{
1612+
unsigned int aidx = 0, bidx = 0;
1613+
1614+
sscanf((*a)->d_name, "telem%u", &aidx);
1615+
sscanf((*b)->d_name, "telem%u", &bidx);
1616+
1617+
return aidx >= bidx;
1618+
}
1619+
1620+
const struct dirent* pmt_diriter_next(struct pmt_diriter_t *iter)
1621+
{
1622+
const struct dirent *ret = NULL;
1623+
1624+
if (!iter->dir)
1625+
return NULL;
1626+
1627+
if (iter->current_name_idx >= iter->num_names)
1628+
return NULL;
1629+
1630+
ret = iter->namelist[iter->current_name_idx];
1631+
++iter->current_name_idx;
1632+
1633+
return ret;
1634+
}
1635+
1636+
const struct dirent* pmt_diriter_begin(struct pmt_diriter_t *iter, const char *pmt_root_path)
1637+
{
1638+
int num_names = iter->num_names;
1639+
1640+
if (!iter->dir) {
1641+
iter->dir = opendir(pmt_root_path);
1642+
if (iter->dir == NULL)
1643+
return NULL;
1644+
1645+
num_names = scandir(pmt_root_path, &iter->namelist, pmt_telemdir_filter, pmt_telemdir_sort);
1646+
if (num_names == -1)
1647+
return NULL;
1648+
}
1649+
1650+
iter->current_name_idx = 0;
1651+
iter->num_names = num_names;
1652+
1653+
return pmt_diriter_next(iter);
1654+
}
1655+
1656+
void pmt_diriter_init(struct pmt_diriter_t *iter)
1657+
{
1658+
memset(iter, 0, sizeof(*iter));
1659+
}
1660+
1661+
void pmt_diriter_remove(struct pmt_diriter_t *iter)
1662+
{
1663+
if (iter->namelist) {
1664+
for (unsigned int i = 0; i < iter->num_names; i++) {
1665+
free(iter->namelist[i]);
1666+
iter->namelist[i] = NULL;
1667+
}
1668+
}
1669+
1670+
free(iter->namelist);
1671+
iter->namelist = NULL;
1672+
iter->num_names = 0;
1673+
iter->current_name_idx = 0;
1674+
1675+
closedir(iter->dir);
1676+
iter->dir = NULL;
1677+
}
1678+
15921679
unsigned int pmt_counter_get_width(const struct pmt_counter *p)
15931680
{
15941681
return (p->msb - p->lsb) + 1;

0 commit comments

Comments
 (0)