*
**************************************************************************/
-#if HAVE_GALLIUM_EXTRA_HUD
+#ifdef HAVE_GALLIUM_EXTRA_HUD
/* Purpose:
* Reading /sys/devices/system/cpu/cpu?/cpufreq/scaling_???_freq
#include "hud/hud_private.h"
#include "util/list.h"
-#include "os/os_time.h"
+#include "util/os_time.h"
+#include "os/os_thread.h"
#include "util/u_memory.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
-#define LOCAL_DEBUG 0
-
struct cpufreq_info
{
struct list_head list;
static int gcpufreq_count = 0;
static struct list_head gcpufreq_list;
+static mtx_t gcpufreq_mutex = _MTX_INITIALIZER_NP;
static struct cpufreq_info *
find_cfi_by_index(int cpu_index, int mode)
}
static void
-query_cfi_load(struct hud_graph *gr)
+query_cfi_load(struct hud_graph *gr, struct pipe_context *pipe)
{
struct cpufreq_info *cfi = gr->query_data;
}
}
-static void
-free_query_data(void *p)
-{
- struct cpufreq_info *cfi = (struct cpufreq_info *)p;
- list_del(&cfi->list);
- FREE(cfi);
-}
-
/**
* Create and initialize a new object for a specific CPU.
* \param pane parent context.
if (num_cpus <= 0)
return;
-#if LOCAL_DEBUG
- printf("%s(%d, %s) - Creating HUD object\n", __func__, cpu_index,
- mode == CPUFREQ_MINIMUM ? "MIN" :
- mode == CPUFREQ_CURRENT ? "CUR" :
- mode == CPUFREQ_MAXIMUM ? "MAX" : "UNDEFINED");
-#endif
-
cfi = find_cfi_by_index(cpu_index, mode);
if (!cfi)
return;
break;
case CPUFREQ_MAXIMUM:
snprintf(gr->name, sizeof(gr->name), "%s-Max", cfi->name);
+ break;
default:
+ free(gr);
return;
}
gr->query_data = cfi;
gr->query_new_value = query_cfi_load;
- /* Don't use free() as our callback as that messes up Gallium's
- * memory debugger. Use simple free_query_data() wrapper.
- */
- gr->free_query_data = free_query_data;
-
hud_pane_add_graph(pane, gr);
hud_pane_set_max_value(pane, 3000000 /* 3 GHz */);
}
int cpu_index;
/* Return the number of CPU metrics we support. */
- if (gcpufreq_count)
+ mtx_lock(&gcpufreq_mutex);
+ if (gcpufreq_count) {
+ mtx_unlock(&gcpufreq_mutex);
return gcpufreq_count;
+ }
/* Scan /sys/devices.../cpu, for every object type we support, create
* and persist an object to represent its different metrics.
*/
list_inithead(&gcpufreq_list);
DIR *dir = opendir("/sys/devices/system/cpu");
- if (!dir)
+ if (!dir) {
+ mtx_unlock(&gcpufreq_mutex);
return 0;
+ }
while ((dp = readdir(dir)) != NULL) {
- /* Avoid 'lo' and '..' and '.' */
- if (strlen(dp->d_name) <= 2)
+ size_t d_name_len = strlen(dp->d_name);
+
+ /* Avoid 'lo' and '..' and '.', and avoid overlong names that
+ * would result in a buffer overflow in add_object.
+ */
+ if (d_name_len <= 2 || d_name_len > 15)
continue;
if (sscanf(dp->d_name, "cpu%d\n", &cpu_index) != 1)
snprintf(fn, sizeof(fn), "%s/cpufreq/scaling_max_freq", basename);
add_object(dp->d_name, fn, CPUFREQ_MAXIMUM, cpu_index);
}
+ closedir(dir);
if (displayhelp) {
list_for_each_entry(struct cpufreq_info, cfi, &gcpufreq_list, list) {
}
}
+ mtx_unlock(&gcpufreq_mutex);
return gcpufreq_count;
}