11#include <sys/sysinfo.h>
14#define CHECK(condition) \
17 fprintf(stderr, "SYSINFO-CONTRACT: line=%d errno=%d\n", __LINE__, errno); \
22static uint64_t seconds(
void) {
24 return clock_gettime(CLOCK_MONOTONIC, &now) ? UINT64_MAX : (uint64_t)now.tv_sec;
28 struct sysinfo first, second;
29 int result = 1, gates[2] = {-1, -1};
31 const long page = sysconf(_SC_PAGESIZE);
32 void* boundary = MAP_FAILED;
33 void* memory = MAP_FAILED;
35 _Static_assert(offsetof(
struct sysinfo, mem_unit) == 104,
"amd64 sysinfo prefix");
36 memset(&first, 0xa5,
sizeof(first));
37 const uint64_t before = seconds();
38 CHECK(sysinfo(&first) == 0 && first.mem_unit == 1 && first.procs > 0);
39 const uint64_t after = seconds();
40 CHECK(first.totalram > 0 && first.freeram <= first.totalram && first.freeswap <= first.totalswap);
41 CHECK(before != UINT64_MAX && after != UINT64_MAX);
42 CHECK(first.uptime >= before && first.uptime <= after + 1);
43 for (
size_t i = 112; i <
sizeof(first); ++i)
44 CHECK(((
const unsigned char*)&first)[i] == 0xa5);
46 CHECK(sysinfo(NULL) == -1 && errno == EFAULT);
47 boundary = mmap(NULL, 2 * page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
48 CHECK(boundary != MAP_FAILED);
49 CHECK(mprotect((
char*)boundary + page, page, PROT_NONE) == 0);
50 CHECK(sysinfo((
struct sysinfo*)((
char*)boundary + page - 112)) == 0);
52 CHECK(sysinfo((
struct sysinfo*)((
char*)boundary + page - 111)) == -1 && errno == EFAULT);
53 CHECK(mprotect(boundary, page, PROT_READ) == 0);
55 CHECK(sysinfo(boundary) == -1 && errno == EFAULT);
56 memory = mmap(NULL, 32 * page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
57 CHECK(memory != MAP_FAILED);
58 for (
size_t offset = 0; offset < 32 * (size_t)page; offset += page)
59 ((
volatile unsigned char*)memory)[offset] = 0x5c;
60 CHECK(sysinfo(&second) == 0 && second.totalram == first.totalram &&
61 second.freeram <= second.totalram && second.uptime >= first.uptime);
62 CHECK(pipe(gates) == 0);
63 CHECK(sysinfo(&first) == 0);
68 if (write(gates[1],
"r", 1) != 1)
70 const uint64_t started = seconds();
71 if (started == UINT64_MAX)
73 const uint64_t end = started + 7;
74 volatile uint64_t work = 0;
75 while (seconds() < end) {
76 for (
unsigned i = 0; i < 100000; ++i)
82 CHECK(read(gates[0], &ready, 1) == 1);
83 CHECK(sysinfo(&second) == 0 && second.procs > first.procs);
84 struct timespec delay = {6, 0};
87 slept = nanosleep(&delay, &delay);
88 }
while (slept && errno == EINTR);
90 CHECK(sysinfo(&second) == 0 && second.loads[0] > 0 && second.loads[1] > 0 && second.loads[2] > 0);
92 CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 0);
97 waitpid(child, NULL, 0);
102 if (boundary != MAP_FAILED)
103 munmap(boundary, 2 * page);
104 if (memory != MAP_FAILED)
105 munmap(memory, 32 * page);
106 puts(result ?
"SYSINFO-CONTRACT: FAIL" :
"SYSINFO-CONTRACT: PASS");