Home | History | Annotate | Download | only in libmicro
      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 
     40 typedef volatile char		vchar_t;
     41 
     42 typedef struct {
     43 	int			ts_batch;
     44 	int			ts_res;
     45 } tsd_t;
     46 
     47 #define	DEFF			"/dev/zero"
     48 #define	DEFL			8192
     49 
     50 static char			*optf = DEFF;
     51 static long long		optl = DEFL;
     52 static int			optr = 0;
     53 static int			optw = 0;
     54 static int			opts = 0;
     55 static int			optt = 0;
     56 static int			fd = -1;
     57 static int			anon = 0;
     58 static int			foo = 0;
     59 static vchar_t			*seg;
     60 static int			pagesize;
     61 
     62 int
     63 benchmark_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 
     84 int
     85 benchmark_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 
    113 int
    114 benchmark_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 
    149 int
    150 benchmark(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 	us = (getpindex() * lm_optT) + gettindex();
    159 	for (i = 0; i < lm_optB; i++) {
    160 		switch ((us + ts->ts_batch + i) % 2) {
    161 		case 0:
    162 			prot = PROT_NONE;
    163 			if (optt) {
    164 				for (j = k = 0; j < optl; j += pagesize)
    165 					k += seg[i * optl + j];
    166 				ts->ts_res += k;
    167 			}
    168 			break;
    169 		default:
    170 			prot = PROT_READ | PROT_WRITE;
    171 			break;
    172 		}
    173 
    174 		if (mprotect((void *)&seg[i * optl], optl, prot) == -1) {
    175 			res->re_errors++;
    176 		}
    177 	}
    178 	res->re_count += lm_optB;
    179 	ts->ts_batch++;
    180 
    181 	return (0);
    182 }
    183 
    184 char *
    185 benchmark_result()
    186 {
    187 	static char		result[256];
    188 	char			flags[6];
    189 
    190 	flags[0] = anon ? 'a' : '-';
    191 	flags[1] = optr ? 'r' : '-';
    192 	flags[2] = optw ? 'w' : '-';
    193 	flags[3] = opts ? 's' : '-';
    194 	flags[4] = optt ? 't' : '-';
    195 	flags[5] = 0;
    196 
    197 	(void) sprintf(result, "%8lld %5s", optl, flags);
    198 
    199 	return (result);
    200 }
    201