blob: a215754b47be12ab0d329583fcc774ae9aa03b92 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fbl/unique_ptr.h>
#include <lib/zx/resource.h>
#include <zircon/device/sysinfo.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>
#include "stress_test.h"
namespace {
zx_status_t get_root_resource(zx::resource* root_resource) {
int fd = open("/dev/misc/sysinfo", O_RDWR);
if (fd < 0) {
fprintf(stderr, "ERROR: Cannot open sysinfo: %s (%d)\n",
strerror(errno), errno);
return ZX_ERR_NOT_FOUND;
}
zx_handle_t h;
ssize_t n = ioctl_sysinfo_get_root_resource(fd, &h);
close(fd);
if (n != sizeof(*root_resource)) {
if (n < 0) {
fprintf(stderr, "ERROR: Cannot obtain root resource: %s (%zd)\n",
zx_status_get_string((zx_status_t)n), n);
return (zx_status_t)n;
} else {
fprintf(stderr, "ERROR: Cannot obtain root resource (%zd != %zd)\n",
n, sizeof(root_resource));
return ZX_ERR_NOT_FOUND;
}
}
root_resource->reset(h);
return ZX_OK;
}
zx_status_t get_kmem_stats(zx_info_kmem_stats_t* kmem_stats) {
zx::resource root_resource;
zx_status_t ret = get_root_resource(&root_resource);
if (ret != ZX_OK) {
return ret;
}
zx_status_t err = zx_object_get_info(
root_resource.get(), ZX_INFO_KMEM_STATS, kmem_stats, sizeof(*kmem_stats), nullptr, nullptr);
if (err != ZX_OK) {
fprintf(stderr, "ZX_INFO_KMEM_STATS returns %d (%s)\n",
err, zx_status_get_string(err));
return err;
}
return ZX_OK;
}
void print_help(char** argv, FILE* f) {
fprintf(f, "Usage: %s [options]\n", argv[0]);
fprintf(f, "No options currently defined\n");
fprintf(f, "options:\n");
fprintf(f, "\t-h: This help\n");
fprintf(f, "\t-v: verbose, status output\n");
}
} // namespace
int main(int argc, char** argv) {
zx_status_t status;
bool verbose = false;
int c;
while ((c = getopt(argc, argv, "hv")) > 0) {
switch (c) {
case 'h':
print_help(argv, stdout);
return 0;
case 'v':
verbose = true;
break;
default:
fprintf(stderr, "Unknown option\n");
print_help(argv, stderr);
return 1;
}
}
// read some system stats for each test to use
zx_info_kmem_stats_t kmem_stats;
status = get_kmem_stats(&kmem_stats);
if (status != ZX_OK) {
fprintf(stderr, "error reading kmem stats\n");
return 1;
}
fbl::SinglyLinkedList<fbl::unique_ptr<StressTest>> test_list;
// create a single test and run it
//
// TODO: allow selecting more than one test and the timeout
{
auto test = CreateVmStressTest();
if (!test) {
fprintf(stderr, "error creating test\n");
return 1;
}
test_list.push_front(fbl::move(test));
}
// initialize all the tests
for (auto& test : test_list) {
status = test.Init(verbose, kmem_stats);
if (status != ZX_OK) {
fprintf(stderr, "error initializing test\n");
return 1;
}
}
// start all of them
for (auto& test : test_list) {
status = test.Start();
if (status != ZX_OK) {
fprintf(stderr, "error initializing test\n");
return 1;
}
}
// run forever for now
for (;;) {
zx_nanosleep(zx_deadline_after(ZX_SEC(5)));
}
// shut them down
for (auto& test : test_list) {
status = test.Stop();
if (status != ZX_OK) {
fprintf(stderr, "error stopping test\n");
return 1;
}
}
return 0;
}