/* * Copyright (C) 2018 Philippe Gerum * * SPDX-License-Identifier: MIT */ #include #include #include #include #include #include "memcheck/memcheck.h" smokey_test_plugin(memory_coreheap, MEMCHECK_ARGS, "Check for the Cobalt core allocator sanity.\n" MEMCHECK_HELP_STRINGS ); #define MIN_HEAP_SIZE 8192 #define MAX_HEAP_SIZE (1024 * 1024 * 2) #define RANDOM_ROUNDS 1024 #define PATTERN_HEAP_SIZE (128*1024) #define PATTERN_ROUNDS 128 static int kernel_test_seq(struct memcheck_descriptor *md, size_t heap_size, size_t block_size, int flags) { struct rttst_heap_stathdr sthdr; struct rttst_heap_parms parms; struct rttst_heap_stats *p; struct memcheck_stat *st; struct sched_param param; int fd, ret, n; fd = __RT(open("/dev/rtdm/heapcheck", O_RDWR)); if (fd < 0) return -ENOSYS; /* This switches to real-time mode over Cobalt. */ param.sched_priority = 1; pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m); parms.heap_size = heap_size; parms.block_size = block_size; parms.flags = flags; ret = __RT(ioctl(fd, RTTST_RTIOC_HEAP_CHECK, &parms)); if (ret) goto out; if (parms.nrstats == 0) goto out; sthdr.nrstats = parms.nrstats; sthdr.buf = __STD(malloc(sizeof(*sthdr.buf) * parms.nrstats)); if (sthdr.buf == NULL) { ret = -ENOMEM; goto out; } ret = __RT(ioctl(fd, RTTST_RTIOC_HEAP_STAT_COLLECT, &sthdr)); if (ret) goto out; for (n = sthdr.nrstats, p = sthdr.buf; n > 0; n--, p++) { st = __STD(malloc(sizeof(*st))); if (st == NULL) { ret = -ENOMEM; goto out; } st->heap_size = p->heap_size; st->user_size = p->user_size; st->block_size = p->block_size; st->nrblocks = p->nrblocks; st->alloc_avg_ns = p->alloc_avg_ns; st->alloc_max_ns = p->alloc_max_ns; st->free_avg_ns = p->free_avg_ns; st->free_max_ns = p->free_max_ns; st->maximum_free = p->maximum_free; st->largest_free = p->largest_free; st->flags = p->flags; memcheck_log_stat(st); } out: __RT(close(fd)); param.sched_priority = 0; pthread_setschedparam(pthread_self(), SCHED_OTHER, ¶m); return ret; } static struct memcheck_descriptor coreheap_descriptor = { .name = "coreheap", .seq_min_heap_size = MIN_HEAP_SIZE, .seq_max_heap_size = MAX_HEAP_SIZE, .random_rounds = RANDOM_ROUNDS, .pattern_heap_size = PATTERN_HEAP_SIZE, .pattern_rounds = PATTERN_ROUNDS, .valid_flags = MEMCHECK_ALL_FLAGS, .test_seq = kernel_test_seq, }; static int run_memory_coreheap(struct smokey_test *t, int argc, char *const argv[]) { return memcheck_run(&coreheap_descriptor, t, argc, argv); }