1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
// SPDX-License-Identifier: MIT
/*
* Copyright 2020 Advanced Micro Devices, Inc.
* Copyright 2025 Advanced Micro Devices, Inc.
*/
#include <fcntl.h>
#include "igt.h"
#include "amd_mem_leak.h"
enum mem_leak_cmd {
CMD_SCAN = 0, /* as index */
CMD_CLEAR = 1,
CMD_MAX,
};
/* return non zero fp write successfully or null if failure */
static
FILE *mem_leak_cmd(enum mem_leak_cmd cmd)
{
const struct mem_leak_cmd_arr {
const char *str_cmd;
enum mem_leak_cmd cmd;
} memleak_arr[] = {
{"scan", CMD_SCAN },
{"clear", CMD_CLEAR },
{"", CMD_MAX },
{NULL, 0}
};
FILE *fp;
int len;
fp = fopen("/sys/kernel/debug/kmemleak", "r+");
if (fp) {
len = strlen(memleak_arr[cmd].str_cmd);
if (fwrite(memleak_arr[cmd].str_cmd, 1, len, fp) != len) {
fclose(fp);
fp = NULL;
}
}
return fp;
}
/* return True if scan successfully written to kmemleak */
static
bool send_scan_memleak(void)
{
FILE *fp;
fp = mem_leak_cmd(CMD_SCAN);
if (fp != NULL) {
fclose(fp);
return true;
}
return false;
}
/* return True if clear successfully sent to kmemleak */
static
bool send_clear_memleak(void)
{
FILE *fp;
fp = mem_leak_cmd(CMD_CLEAR);
if (fp != NULL) {
fclose(fp);
return true;
}
return false;
}
/* return true if kmemleak is enabled and then clear earlier leak records */
bool clear_memleak(bool is_more_than_one)
{
if (!send_scan_memleak() || !send_clear_memleak())
return false;
if (is_more_than_one) {
if (!send_scan_memleak() || !send_clear_memleak())
return false;
}
return true;
}
/* return true if kmemleak did not pick up any memory leaks */
bool is_no_memleak(void)
{
FILE *fp;
const char *buf[1];
char read_buf[1024];
fp = mem_leak_cmd(CMD_SCAN);
if (fp != NULL) {
/* read back to see if any leak */
if (fread(buf, 1, 1, fp) == 0) {
fclose(fp);
return true;
}
}
/* Dump contents of kmemleak */
fseek(fp, 0L, SEEK_SET);
while (fgets(read_buf, sizeof(read_buf) - 1, fp) != NULL)
igt_info("MEM_LEAK: %s", read_buf);
fclose(fp);
return false;
}
|