1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2020 Oxide Computer Company
14  */
15 
16 /*
17  * Basic program that reads random sensors, mostly ignoring errors. This is in
18  * support of the stress test program.
19  */
20 
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <stdlib.h>
25 #include <sys/sensors.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <err.h>
29 #include <limits.h>
30 #include <strings.h>
31 
32 /*
33  * Wait for a random amount in 1500 ms, but make sure to wait at least 10ms.
34  */
35 static uint32_t timeout = 1500;
36 static uint32_t skew = 10;
37 
38 int
39 main(int argc, const char *argv[])
40 {
41 	int nsensors = 0, ninst = 0;
42 	uint32_t ms;
43 
44 	if (argc != 3) {
45 		errx(EXIT_FAILURE, "missing required args: ninstance, "
46 		    "nsensors");
47 	}
48 
49 	nsensors = atoi(argv[1]);
50 	ninst = atoi(argv[2]);
51 	if (nsensors <= 0 || ninst <= 0) {
52 		errx(EXIT_FAILURE, "got bad values for some of nesnsors (%u), "
53 		    "ninst (%u)", nsensors, ninst);
54 	}
55 
56 	for (;;) {
57 		int fd;
58 		char buf[PATH_MAX];
59 		uint32_t sens, inst;
60 		struct timespec ts;
61 		sensor_ioctl_temperature_t temp;
62 
63 		/* 0s based */
64 		sens = arc4random_uniform(nsensors);
65 		/* 1s based */
66 		inst = arc4random_uniform(ninst) + 1;
67 		(void) snprintf(buf, sizeof (buf),
68 		    "/dev/sensors/test/test.temp.%u.%u", sens, inst);
69 
70 		fd = open(buf, O_RDONLY);
71 		if (fd < 0) {
72 			warn("failed to open %s", buf);
73 			goto wait;
74 		}
75 
76 		bzero(&temp, sizeof (temp));
77 		if (ioctl(fd, SENSOR_IOCTL_TEMPERATURE, &temp) != 0) {
78 			warn("failed to get sensor temp on %s", buf);
79 		}
80 
81 		if (temp.sit_unit != SENSOR_UNIT_CELSIUS) {
82 			warnx("data from sensor %s looks off, expected sensor "
83 			    "to indicate Celsius, but instead %u",
84 			    temp.sit_unit);
85 		}
86 
87 		(void) close(fd);
88 wait:
89 		ms = arc4random_uniform(timeout) + skew;
90 		ts.tv_sec = ms / 1000;
91 		ts.tv_nsec = (ms % 1000) * (NANOSEC / MILLISEC);
92 		(void) nanosleep(&ts, NULL);
93 	}
94 	return (0);
95 }
96