• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24 
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <inttypes.h>
32 #include <errno.h>
33 #include <sys/stat.h>
34 #include <sys/ioctl.h>
35 #include <sys/resource.h>
36 #include <sys/time.h>
37 #include <time.h>
38 
39 #include "drm.h"
40 #include "ioctl_wrappers.h"
41 #include "drmtest.h"
42 #include "intel_io.h"
43 #include "igt_rand.h"
44 
45 #define CLOSE_DEVICE 0x1
46 
elapsed(const struct timespec * start,const struct timespec * end)47 static double elapsed(const struct timespec *start,
48 		      const struct timespec *end)
49 {
50 	return (end->tv_sec - start->tv_sec) + 1e-9*(end->tv_nsec - start->tv_nsec);
51 }
52 
loop(int nobj,int ndev,int nage,int ncpus,unsigned flags)53 static int loop(int nobj, int ndev, int nage, int ncpus, unsigned flags)
54 {
55 	uint32_t *handle;
56 	double *results;
57 	int parent;
58 	int size;
59 	int n;
60 
61 #if 0
62 	printf("nobj=%d, ndev=%d, nage=%d, ncpus=%d, flags=%x\n",
63 	       nobj, ndev, nage, ncpus, flags);
64 #endif
65 
66 	parent = drm_open_driver(DRIVER_INTEL);
67 
68 	size = ncpus * sizeof(*results);
69 	size = (size + 4095) & -4096;
70 	results = mmap(0, size, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
71 
72 	handle = malloc(nobj * sizeof(*handle));
73 	for (n = 0; n < nobj; n++)
74 		handle[n] = gem_create(parent, 4096);
75 
76 	igt_fork(child, ncpus) {
77 		struct timespec start, end;
78 		unsigned long count = 0;
79 		int *dev, *fd;
80 
81 		hars_petruska_f54_1_random_perturb(child);
82 
83 		fd = malloc(ndev * nage * sizeof(*fd));
84 		dev = malloc(ndev * sizeof(*dev));
85 		for (n = 0; n < ndev; n++)
86 			dev[n] = drm_open_driver(DRIVER_INTEL);
87 		memset(fd, 0xff, ndev * nage * sizeof(*fd));
88 
89 		clock_gettime(CLOCK_MONOTONIC, &start);
90 		do {
91 			for (n = 0; n < ndev; n++) {
92 				int h = hars_petruska_f54_1_random_unsafe() % nobj;
93 				int a = hars_petruska_f54_1_random_unsafe() % nage;
94 
95 				if (!(flags & CLOSE_DEVICE)) {
96 					int old = fd[n*nage + a];
97 					if (old != -1) {
98 						gem_close(dev[n], prime_fd_to_handle(dev[n], old));
99 						close(old);
100 					}
101 				}
102 
103 				fd[n*nage + a] =
104 					prime_handle_to_fd(parent, handle[h]);
105 				prime_fd_to_handle(dev[n], fd[n*nage + a]);
106 
107 				if (flags & CLOSE_DEVICE) {
108 					close(dev[n]);
109 					dev[n] = drm_open_driver(DRIVER_INTEL);
110 				}
111 			}
112 
113 			count++;
114 			clock_gettime(CLOCK_MONOTONIC, &end);
115 		} while (elapsed(&start, &end) < 2.);
116 		results[child] = 1e6*elapsed(&start, &end) / (ndev * count);
117 	}
118 	igt_waitchildren();
119 
120 	results[ncpus] = 0;
121 	for (n = 0; n < ncpus; n++)
122 		results[ncpus] +=  results[n];
123 	printf("%.3f us\n", results[ncpus] / ncpus);
124 	return 0;
125 }
126 
allow_files(unsigned min)127 static bool allow_files(unsigned min)
128 {
129 	struct rlimit rlim;
130 	unsigned nofile_rlim = 1024*1024;
131 
132 	FILE *file = fopen("/proc/sys/fs/file-max", "r");
133 	if (file) {
134 		igt_assert(fscanf(file, "%u", &nofile_rlim) == 1);
135 		igt_info("System limit for open files is %u\n", nofile_rlim);
136 		fclose(file);
137 	}
138 
139 	if (min > nofile_rlim)
140 		return false;
141 
142 	if (getrlimit(RLIMIT_NOFILE, &rlim))
143 		return false;
144 
145 	igt_info("Current file limit is %ld, estimated we need %d\n",
146 		 (long)rlim.rlim_cur, min);
147 
148 	if (rlim.rlim_cur > min)
149 		return true;
150 
151 	rlim.rlim_cur = min;
152 	rlim.rlim_max = min;
153 	return setrlimit(RLIMIT_NOFILE, &rlim) == 0;
154 }
155 
main(int argc,char ** argv)156 int main(int argc, char **argv)
157 {
158 	unsigned flags = 0;
159 	int ncpus = 1;
160 	int ndev = 512;
161 	int nobj = 32 << 10;
162 	int nage = 1024;
163 	int c;
164 
165 	while ((c = getopt (argc, argv, "a:d:o:cf")) != -1) {
166 		switch (c) {
167 		case 'o':
168 			nobj = atoi(optarg);
169 			if (nobj < 1)
170 				nobj = 1;
171 			break;
172 
173 		case 'd':
174 			ndev = atoi(optarg);
175 			if (ndev < 1)
176 				ndev = 1;
177 			break;
178 
179 		case 'a':
180 			nage = atoi(optarg);
181 			if (nage < 1)
182 				nage = 1;
183 			break;
184 
185 		case 'f':
186 			ncpus = sysconf(_SC_NPROCESSORS_ONLN);
187 			break;
188 
189 		case 'c':
190 			flags |= CLOSE_DEVICE;
191 			break;
192 
193 		default:
194 			break;
195 		}
196 	}
197 
198 	if (!allow_files((nage + 1)*ndev + 1)) {
199 		fprintf(stderr, "Unable to relax fd limit\n");
200 		exit(1);
201 	}
202 
203 	return loop(nobj, ndev, nage, ncpus, flags);
204 }
205