1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms
5 * of the Common Development and Distribution License
6 * (the "License").  You may not use this file except
7 * in compliance with the License.
8 *
9 * You can obtain a copy of the license at
10 * src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing
13 * permissions and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL
16 * HEADER in each file and include the License file at
17 * usr/src/OPENSOLARIS.LICENSE.  If applicable,
18 * add the following below this CDDL HEADER, with the
19 * fields enclosed by brackets "[]" replaced with your
20 * own identifying information: Portions Copyright [yyyy]
21 * [name of copyright owner]
22 *
23 * CDDL HEADER END
24 */
25
26/*
27 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28 * Use is subject to license terms.
29 */
30
31#include <unistd.h>
32#include <stdlib.h>
33#include <stdio.h>
34#include <sys/mman.h>
35#include <fcntl.h>
36#include <strings.h>
37
38#include "libmicro.h"
39
40typedef volatile char		vchar_t;
41
42typedef struct {
43	int			ts_batch;
44	int			ts_res;
45} tsd_t;
46
47#define	DEFF			"/dev/zero"
48#define	DEFL			8192
49
50static char			*optf = DEFF;
51static long long		optl = DEFL;
52static int			optr = 0;
53static int			optw = 0;
54static int			opts = 0;
55static int			optt = 0;
56static int			fd = -1;
57static int			anon = 0;
58static int			foo = 0;
59static vchar_t			*seg;
60static int			pagesize;
61
62int
63benchmark_init()
64{
65	lm_tsdsize = sizeof (tsd_t);
66
67	(void) sprintf(lm_optstr, "f:l:rstw");
68
69	(void) sprintf(lm_usage,
70	    "       [-f file-to-map (default %s)]\n"
71	    "       [-l mapping-length (default %d)]\n"
72	    "       [-r] (read a byte from each page)\n"
73	    "       [-w] (write a byte on each page)\n"
74	    "       [-s] (use MAP_SHARED)\n"
75	    "       [-t] (touch each page after restoring permissions)\n"
76	    "notes: measures mprotect()\n",
77	    DEFF, DEFL);
78
79	(void) sprintf(lm_header, "%8s %5s", "size", "flags");
80
81	return (0);
82}
83
84int
85benchmark_optswitch(int opt, char *optarg)
86{
87	switch (opt) {
88	case 'f':
89		optf = optarg;
90		anon = strcmp(optf, "MAP_ANON") == 0;
91		break;
92	case 'l':
93		optl = sizetoll(optarg);
94		break;
95	case 'r':
96		optr = 1;
97		break;
98	case 's':
99		opts = 1;
100		break;
101	case 't':
102		optt = 1;
103		break;
104	case 'w':
105		optw = 1;
106		break;
107	default:
108		return (-1);
109	}
110	return (0);
111}
112
113int
114benchmark_initrun()
115{
116	int			flags;
117	int			i;
118
119	if (!anon)
120		fd = open(optf, O_RDWR);
121
122	flags = opts ? MAP_SHARED : MAP_PRIVATE;
123	flags |= anon ? MAP_ANON : 0;
124
125	seg = (vchar_t *)mmap(NULL, lm_optB * optl, PROT_READ | PROT_WRITE,
126	    flags, anon ? -1 : fd, 0L);
127
128	if (seg == MAP_FAILED) {
129		return (-1);
130	}
131
132	if (optr) {
133		for (i = 0; i < lm_optB * optl; i += 4096) {
134			foo += seg[i];
135		}
136	}
137
138	if (optw) {
139		for (i = 0; i < lm_optB * optl; i += 4096) {
140			seg[i] = 1;
141		}
142	}
143
144	pagesize = getpagesize();
145
146	return (0);
147}
148
149int
150benchmark(void *tsd, result_t *res)
151{
152	tsd_t			*ts = (tsd_t *)tsd;
153	int			i;
154	int			us;
155	int			prot = PROT_NONE;
156	int			j, k;
157
158#if !defined(__APPLE__)
159    us = (getpindex() * lm_optT) + gettindex();
160#else
161    us = gettsdindex(tsd);
162#endif /* __APPLE__ */
163
164	for (i = 0; i < lm_optB; i++) {
165		switch ((us + ts->ts_batch + i) % 2) {
166		case 0:
167			prot = PROT_NONE;
168			if (optt) {
169				for (j = k = 0; j < optl; j += pagesize)
170					k += seg[i * optl + j];
171				ts->ts_res += k;
172			}
173			break;
174		default:
175			prot = PROT_READ | PROT_WRITE;
176			break;
177		}
178
179		if (mprotect((void *)&seg[i * optl], optl, prot) == -1) {
180			res->re_errors++;
181		}
182	}
183	res->re_count += lm_optB;
184	ts->ts_batch++;
185
186	return (0);
187}
188
189char *
190benchmark_result()
191{
192	static char		result[256];
193	char			flags[6];
194
195	flags[0] = anon ? 'a' : '-';
196	flags[1] = optr ? 'r' : '-';
197	flags[2] = optw ? 'w' : '-';
198	flags[3] = opts ? 's' : '-';
199	flags[4] = optt ? 't' : '-';
200	flags[5] = 0;
201
202	(void) sprintf(result, "%8lld %5s", optl, flags);
203
204	return (result);
205}
206