Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / compiler-rt / test / profile / ContinuousSyncMode / darwin-proof-of-concept.c
blob85caca9a56b40286c1a4ed9519defec2322ac0c4
1 // Test whether mmap'ing profile counters onto an open file is feasible. As
2 // this involves some platform-specific logic, this test is designed to be a
3 // minimum viable proof-of-concept: it may be useful when porting the mmap()
4 // mode to a new platform, but is not in and of itself a test of the profiling
5 // runtime.
7 // REQUIRES: darwin
9 // Align counters and data to the maximum expected page size (16K).
10 // RUN: %clang -g -o %t %s \
11 // RUN: -Wl,-sectalign,__DATA,__pcnts,0x4000 \
12 // RUN: -Wl,-sectalign,__DATA,__pdata,0x4000
14 // Create a 'profile' using mmap() and validate it.
15 // RUN: %run %t create %t.tmpfile
16 // RUN: %run %t validate %t.tmpfile
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <sys/mman.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
25 __attribute__((section("__DATA,__pcnts"))) int counters[] = {0xbad};
26 extern int cnts_start __asm("section$start$__DATA$__pcnts");
27 const size_t cnts_len = 0x4000;
29 __attribute__((section("__DATA,__pdata"))) int data[] = {1, 2, 3};
30 extern int data_start __asm("section$start$__DATA$__pdata");
31 const size_t data_len = sizeof(int) * 3;
33 int create_tmpfile(char *path) {
34 // Create a temp file.
35 int fd = open(path, O_RDWR | O_TRUNC | O_CREAT, 0666);
36 if (fd == -1) {
37 perror("open");
38 return EXIT_FAILURE;
41 // Grow the file to hold data and counters.
42 if (0 != ftruncate(fd, cnts_len + data_len)) {
43 perror("ftruncate");
44 return EXIT_FAILURE;
47 // Write the data first (at offset 0x4000, after the counters).
48 if (data_len != pwrite(fd, &data, data_len, 0x4000)) {
49 perror("write");
50 return EXIT_FAILURE;
53 // Map the counters into the file, before the data.
55 // Requirements (on Darwin):
56 // - &cnts_start must be page-aligned.
57 // - The length and offset-into-fd must be page-aligned.
58 int *counter_map = (int *)mmap(&cnts_start, 0x4000, PROT_READ | PROT_WRITE,
59 MAP_FIXED | MAP_SHARED, fd, 0);
60 if (counter_map != &cnts_start) {
61 perror("mmap");
62 return EXIT_FAILURE;
65 // Update counters 1..9. These updates should be visible in the file.
66 // Expect counter 0 (0xbad), which is not updated, to be zero in the file.
67 for (int i = 1; i < 10; ++i)
68 counter_map[i] = i;
70 // Intentionally do not msync(), munmap(), or close().
71 return EXIT_SUCCESS;
74 int validate_tmpfile(char *path) {
75 int fd = open(path, O_RDONLY);
76 if (fd == -1) {
77 perror("open");
78 return EXIT_FAILURE;
81 // Verify that the file length is: sizeof(counters) + sizeof(data).
82 const size_t num_bytes = cnts_len + data_len;
83 int buf[num_bytes];
84 if (num_bytes != read(fd, &buf, num_bytes)) {
85 perror("read");
86 return EXIT_FAILURE;
89 // Verify the values of counters 1..9 (i.e. that the mmap() worked).
90 for (int i = 0; i < 10; ++i) {
91 if (buf[i] != i) {
92 fprintf(stderr,
93 "validate_tmpfile: Expected '%d' at pos=%d, but got '%d' instead.\n",
94 i, i, buf[i]);
95 return EXIT_FAILURE;
99 // Verify that the rest of the counters (after counter 9) are 0.
100 const int num_cnts = 0x4000 / sizeof(int);
101 for (int i = 10; i < num_cnts; ++i) {
102 if (buf[i] != 0) {
103 fprintf(stderr,
104 "validate_tmpfile: Expected '%d' at pos=%d, but got '%d' instead.\n",
105 0, i, buf[i]);
106 return EXIT_FAILURE;
110 // Verify that the data written after the counters is equal to the "data[]"
111 // array (i.e. {1, 2, 3}).
112 for (int i = num_cnts; i < num_cnts + 3; ++i) {
113 if (buf[i] != (i - num_cnts + 1)) {
114 fprintf(stderr,
115 "validate_tmpfile: Expected '%d' at pos=%d, but got '%d' instead.\n",
116 i - num_cnts + 1, i, buf[i]);
117 return EXIT_FAILURE;
121 // Intentionally do not close().
122 return EXIT_SUCCESS;
125 int main(int argc, char **argv) {
126 intptr_t cnts_start_int = (intptr_t)&cnts_start;
127 intptr_t data_start_int = (intptr_t)&data_start;
128 int pagesz = getpagesize();
130 if (cnts_start_int % pagesz != 0) {
131 fprintf(stderr, "__pcnts is not page-aligned: 0x%lx.\n", cnts_start_int);
132 return EXIT_FAILURE;
134 if (data_start_int % pagesz != 0) {
135 fprintf(stderr, "__pdata is not page-aligned: 0x%lx.\n", data_start_int);
136 return EXIT_FAILURE;
138 if (cnts_start_int + 0x4000 != data_start_int) {
139 fprintf(stderr, "__pdata not ordered after __pcnts.\n");
140 return EXIT_FAILURE;
143 char *action = argv[1];
144 char *path = argv[2];
145 if (0 == strcmp(action, "create"))
146 return create_tmpfile(path);
147 else if (0 == strcmp(action, "validate"))
148 return validate_tmpfile(path);
149 else
150 return EXIT_FAILURE;