1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Ebizzy - replicate a large ebusiness type of workload. 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * Written by Valerie Henson <val@nmt.edu> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Copyright 2006 - 2007 Intel Corporation 7f08c3bdfSopenharmony_ci * Copyright 2007 Valerie Henson <val@nmt.edu> 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * Rodrigo Rubira Branco <rrbranco@br.ibm.com> - HP/BSD/Solaris port and some 10f08c3bdfSopenharmony_ci * new features 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 13f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 14f08c3bdfSopenharmony_ci * the Free Software Foundation; version 2 of the License. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 17f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 18f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19f08c3bdfSopenharmony_ci * GNU General Public License for more details. 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 22f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 23f08c3bdfSopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 24f08c3bdfSopenharmony_ci * USA 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci */ 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci/* 29f08c3bdfSopenharmony_ci * This program is designed to replicate a common web search app 30f08c3bdfSopenharmony_ci * workload. A lot of search applications have the basic pattern: Get 31f08c3bdfSopenharmony_ci * a request to find a certain record, index into the chunk of memory 32f08c3bdfSopenharmony_ci * that contains it, copy it into another chunk, then look it up via 33f08c3bdfSopenharmony_ci * binary search. The interesting parts of this workload are: 34f08c3bdfSopenharmony_ci * 35f08c3bdfSopenharmony_ci * Large working set 36f08c3bdfSopenharmony_ci * Data alloc/copy/free cycle 37f08c3bdfSopenharmony_ci * Unpredictable data access patterns 38f08c3bdfSopenharmony_ci * 39f08c3bdfSopenharmony_ci * Fiddle with the command line options until you get something 40f08c3bdfSopenharmony_ci * resembling the kind of workload you want to investigate. 41f08c3bdfSopenharmony_ci * 42f08c3bdfSopenharmony_ci */ 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_ci#include <stdio.h> 45f08c3bdfSopenharmony_ci#include <unistd.h> 46f08c3bdfSopenharmony_ci#include <stdlib.h> 47f08c3bdfSopenharmony_ci#include <sys/mman.h> 48f08c3bdfSopenharmony_ci#include <pthread.h> 49f08c3bdfSopenharmony_ci#include <string.h> 50f08c3bdfSopenharmony_ci#include <time.h> 51f08c3bdfSopenharmony_ci#include <sys/time.h> 52f08c3bdfSopenharmony_ci#include <sys/resource.h> 53f08c3bdfSopenharmony_ci#include <stdint.h> 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci#include "ebizzy.h" 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci/* 58f08c3bdfSopenharmony_ci * Command line options 59f08c3bdfSopenharmony_ci */ 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistatic unsigned int always_mmap; 62f08c3bdfSopenharmony_cistatic unsigned int never_mmap; 63f08c3bdfSopenharmony_cistatic unsigned int chunks; 64f08c3bdfSopenharmony_cistatic unsigned int use_permissions; 65f08c3bdfSopenharmony_cistatic unsigned int use_holes; 66f08c3bdfSopenharmony_cistatic unsigned int random_size; 67f08c3bdfSopenharmony_cistatic unsigned int chunk_size; 68f08c3bdfSopenharmony_cistatic unsigned int seconds; 69f08c3bdfSopenharmony_cistatic unsigned int threads; 70f08c3bdfSopenharmony_cistatic unsigned int verbose; 71f08c3bdfSopenharmony_cistatic unsigned int linear; 72f08c3bdfSopenharmony_cistatic unsigned int touch_pages; 73f08c3bdfSopenharmony_cistatic unsigned int no_lib_memcpy; 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci/* 76f08c3bdfSopenharmony_ci * Other global variables 77f08c3bdfSopenharmony_ci */ 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_citypedef size_t record_t; 80f08c3bdfSopenharmony_cistatic unsigned int record_size = sizeof(record_t); 81f08c3bdfSopenharmony_cistatic char *cmd; 82f08c3bdfSopenharmony_cistatic record_t **mem; 83f08c3bdfSopenharmony_cistatic char **hole_mem; 84f08c3bdfSopenharmony_cistatic unsigned int page_size; 85f08c3bdfSopenharmony_cistatic time_t start_time; 86f08c3bdfSopenharmony_cistatic volatile int threads_go; 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_cistatic void usage(void) 89f08c3bdfSopenharmony_ci{ 90f08c3bdfSopenharmony_ci fprintf(stderr, "Usage: %s [options]\n" 91f08c3bdfSopenharmony_ci "-T\t\t Just 'touch' the allocated pages\n" 92f08c3bdfSopenharmony_ci "-l\t\t Don't use library memcpy\n" 93f08c3bdfSopenharmony_ci "-m\t\t Always use mmap instead of malloc\n" 94f08c3bdfSopenharmony_ci "-M\t\t Never use mmap\n" 95f08c3bdfSopenharmony_ci "-n <num>\t Number of memory chunks to allocate\n" 96f08c3bdfSopenharmony_ci "-p \t\t Prevent mmap coalescing using permissions\n" 97f08c3bdfSopenharmony_ci "-P \t\t Prevent mmap coalescing using holes\n" 98f08c3bdfSopenharmony_ci "-R\t\t Randomize size of memory to copy and search\n" 99f08c3bdfSopenharmony_ci "-s <size>\t Size of memory chunks, in bytes\n" 100f08c3bdfSopenharmony_ci "-S <seconds>\t Number of seconds to run\n" 101f08c3bdfSopenharmony_ci "-t <num>\t Number of threads (2 * number cpus by default)\n" 102f08c3bdfSopenharmony_ci "-v[v[v]]\t Be verbose (more v's for more verbose)\n" 103f08c3bdfSopenharmony_ci "-z\t\t Linear search instead of binary search\n", cmd); 104f08c3bdfSopenharmony_ci exit(1); 105f08c3bdfSopenharmony_ci} 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci/* 108f08c3bdfSopenharmony_ci * Read options, check them, and set some defaults. 109f08c3bdfSopenharmony_ci */ 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_cistatic void read_options(int argc, char *argv[]) 112f08c3bdfSopenharmony_ci{ 113f08c3bdfSopenharmony_ci int c; 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci page_size = getpagesize(); 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci /* 118f08c3bdfSopenharmony_ci * Set some defaults. These are currently tuned to run in a 119f08c3bdfSopenharmony_ci * reasonable amount of time on my laptop. 120f08c3bdfSopenharmony_ci * 121f08c3bdfSopenharmony_ci * We could set the static defaults in the declarations, but 122f08c3bdfSopenharmony_ci * then the defaults would be split between here and the top 123f08c3bdfSopenharmony_ci * of the file, which is annoying. 124f08c3bdfSopenharmony_ci */ 125f08c3bdfSopenharmony_ci threads = 2 * sysconf(_SC_NPROCESSORS_ONLN); 126f08c3bdfSopenharmony_ci chunks = 10; 127f08c3bdfSopenharmony_ci chunk_size = record_size * 64 * 1024; 128f08c3bdfSopenharmony_ci seconds = 10; 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci /* On to option processing */ 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci cmd = argv[0]; 133f08c3bdfSopenharmony_ci opterr = 1; 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_ci while ((c = getopt(argc, argv, "lmMn:pPRs:S:t:vzT")) != -1) { 136f08c3bdfSopenharmony_ci switch (c) { 137f08c3bdfSopenharmony_ci case 'l': 138f08c3bdfSopenharmony_ci no_lib_memcpy = 1; 139f08c3bdfSopenharmony_ci break; 140f08c3bdfSopenharmony_ci case 'm': 141f08c3bdfSopenharmony_ci always_mmap = 1; 142f08c3bdfSopenharmony_ci break; 143f08c3bdfSopenharmony_ci case 'M': 144f08c3bdfSopenharmony_ci never_mmap = 1; 145f08c3bdfSopenharmony_ci break; 146f08c3bdfSopenharmony_ci case 'n': 147f08c3bdfSopenharmony_ci chunks = atoi(optarg); 148f08c3bdfSopenharmony_ci if (chunks == 0) 149f08c3bdfSopenharmony_ci usage(); 150f08c3bdfSopenharmony_ci break; 151f08c3bdfSopenharmony_ci case 'p': 152f08c3bdfSopenharmony_ci use_permissions = 1; 153f08c3bdfSopenharmony_ci break; 154f08c3bdfSopenharmony_ci case 'P': 155f08c3bdfSopenharmony_ci use_holes = 1; 156f08c3bdfSopenharmony_ci break; 157f08c3bdfSopenharmony_ci case 'R': 158f08c3bdfSopenharmony_ci random_size = 1; 159f08c3bdfSopenharmony_ci break; 160f08c3bdfSopenharmony_ci case 's': 161f08c3bdfSopenharmony_ci chunk_size = atoi(optarg); 162f08c3bdfSopenharmony_ci if (chunk_size == 0) 163f08c3bdfSopenharmony_ci usage(); 164f08c3bdfSopenharmony_ci break; 165f08c3bdfSopenharmony_ci case 'S': 166f08c3bdfSopenharmony_ci seconds = atoi(optarg); 167f08c3bdfSopenharmony_ci if (seconds == 0) 168f08c3bdfSopenharmony_ci usage(); 169f08c3bdfSopenharmony_ci break; 170f08c3bdfSopenharmony_ci case 't': 171f08c3bdfSopenharmony_ci threads = atoi(optarg); 172f08c3bdfSopenharmony_ci if (threads == 0) 173f08c3bdfSopenharmony_ci usage(); 174f08c3bdfSopenharmony_ci break; 175f08c3bdfSopenharmony_ci case 'T': 176f08c3bdfSopenharmony_ci touch_pages = 1; 177f08c3bdfSopenharmony_ci break; 178f08c3bdfSopenharmony_ci case 'v': 179f08c3bdfSopenharmony_ci verbose++; 180f08c3bdfSopenharmony_ci break; 181f08c3bdfSopenharmony_ci case 'z': 182f08c3bdfSopenharmony_ci linear = 1; 183f08c3bdfSopenharmony_ci break; 184f08c3bdfSopenharmony_ci default: 185f08c3bdfSopenharmony_ci usage(); 186f08c3bdfSopenharmony_ci } 187f08c3bdfSopenharmony_ci } 188f08c3bdfSopenharmony_ci 189f08c3bdfSopenharmony_ci if (verbose) 190f08c3bdfSopenharmony_ci printf("ebizzy 0.2\n" 191f08c3bdfSopenharmony_ci "(C) 2006-7 Intel Corporation\n" 192f08c3bdfSopenharmony_ci "(C) 2007 Valerie Henson <val@nmt.edu>\n"); 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci if (verbose) { 195f08c3bdfSopenharmony_ci printf("always_mmap %u\n", always_mmap); 196f08c3bdfSopenharmony_ci printf("never_mmap %u\n", never_mmap); 197f08c3bdfSopenharmony_ci printf("chunks %u\n", chunks); 198f08c3bdfSopenharmony_ci printf("prevent coalescing using permissions %u\n", 199f08c3bdfSopenharmony_ci use_permissions); 200f08c3bdfSopenharmony_ci printf("prevent coalescing using holes %u\n", use_holes); 201f08c3bdfSopenharmony_ci printf("random_size %u\n", random_size); 202f08c3bdfSopenharmony_ci printf("chunk_size %u\n", chunk_size); 203f08c3bdfSopenharmony_ci printf("seconds %d\n", seconds); 204f08c3bdfSopenharmony_ci printf("threads %u\n", threads); 205f08c3bdfSopenharmony_ci printf("verbose %u\n", verbose); 206f08c3bdfSopenharmony_ci printf("linear %u\n", linear); 207f08c3bdfSopenharmony_ci printf("touch_pages %u\n", touch_pages); 208f08c3bdfSopenharmony_ci printf("page size %d\n", page_size); 209f08c3bdfSopenharmony_ci } 210f08c3bdfSopenharmony_ci 211f08c3bdfSopenharmony_ci /* Check for incompatible options */ 212f08c3bdfSopenharmony_ci 213f08c3bdfSopenharmony_ci if (always_mmap && never_mmap) { 214f08c3bdfSopenharmony_ci fprintf(stderr, "Both -m \"always mmap\" and -M " 215f08c3bdfSopenharmony_ci "\"never mmap\" option specified\n"); 216f08c3bdfSopenharmony_ci usage(); 217f08c3bdfSopenharmony_ci } 218f08c3bdfSopenharmony_ci#ifdef __GLIBC__ 219f08c3bdfSopenharmony_ci if (never_mmap) 220f08c3bdfSopenharmony_ci mallopt(M_MMAP_MAX, 0); 221f08c3bdfSopenharmony_ci#endif 222f08c3bdfSopenharmony_ci if (chunk_size < record_size) { 223f08c3bdfSopenharmony_ci fprintf(stderr, "Chunk size %u smaller than record size %u\n", 224f08c3bdfSopenharmony_ci chunk_size, record_size); 225f08c3bdfSopenharmony_ci usage(); 226f08c3bdfSopenharmony_ci } 227f08c3bdfSopenharmony_ci} 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_cistatic void touch_mem(char *dest, size_t size) 230f08c3bdfSopenharmony_ci{ 231f08c3bdfSopenharmony_ci int i; 232f08c3bdfSopenharmony_ci if (touch_pages) { 233f08c3bdfSopenharmony_ci for (i = 0; i < (long)size; i += page_size) 234f08c3bdfSopenharmony_ci *(dest + i) = 0xff; 235f08c3bdfSopenharmony_ci } 236f08c3bdfSopenharmony_ci} 237f08c3bdfSopenharmony_ci 238f08c3bdfSopenharmony_cistatic void *alloc_mem(size_t size) 239f08c3bdfSopenharmony_ci{ 240f08c3bdfSopenharmony_ci char *p; 241f08c3bdfSopenharmony_ci int err = 0; 242f08c3bdfSopenharmony_ci 243f08c3bdfSopenharmony_ci if (always_mmap) { 244f08c3bdfSopenharmony_ci p = mmap(NULL, size, (PROT_READ | PROT_WRITE), 245f08c3bdfSopenharmony_ci (MAP_PRIVATE | MAP_ANONYMOUS), -1, 0); 246f08c3bdfSopenharmony_ci if (p == MAP_FAILED) 247f08c3bdfSopenharmony_ci err = 1; 248f08c3bdfSopenharmony_ci } else { 249f08c3bdfSopenharmony_ci p = malloc(size); 250f08c3bdfSopenharmony_ci if (p == NULL) 251f08c3bdfSopenharmony_ci err = 1; 252f08c3bdfSopenharmony_ci } 253f08c3bdfSopenharmony_ci 254f08c3bdfSopenharmony_ci if (err) { 255f08c3bdfSopenharmony_ci fprintf(stderr, "Couldn't allocate %zu bytes, try smaller " 256f08c3bdfSopenharmony_ci "chunks or size options\n" 257f08c3bdfSopenharmony_ci "Using -n %u chunks and -s %u size\n", 258f08c3bdfSopenharmony_ci size, chunks, chunk_size); 259f08c3bdfSopenharmony_ci exit(1); 260f08c3bdfSopenharmony_ci } 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_ci return (p); 263f08c3bdfSopenharmony_ci} 264f08c3bdfSopenharmony_ci 265f08c3bdfSopenharmony_cistatic void free_mem(void *p, size_t size) 266f08c3bdfSopenharmony_ci{ 267f08c3bdfSopenharmony_ci if (always_mmap) 268f08c3bdfSopenharmony_ci munmap(p, size); 269f08c3bdfSopenharmony_ci else 270f08c3bdfSopenharmony_ci free(p); 271f08c3bdfSopenharmony_ci} 272f08c3bdfSopenharmony_ci 273f08c3bdfSopenharmony_ci/* 274f08c3bdfSopenharmony_ci * Factor out differences in memcpy implementation by optionally using 275f08c3bdfSopenharmony_ci * our own simple memcpy implementation. 276f08c3bdfSopenharmony_ci */ 277f08c3bdfSopenharmony_ci 278f08c3bdfSopenharmony_cistatic void my_memcpy(void *dest, void *src, size_t len) 279f08c3bdfSopenharmony_ci{ 280f08c3bdfSopenharmony_ci char *d = (char *)dest; 281f08c3bdfSopenharmony_ci char *s = (char *)src; 282f08c3bdfSopenharmony_ci int i; 283f08c3bdfSopenharmony_ci 284f08c3bdfSopenharmony_ci for (i = 0; i < (long)len; i++) 285f08c3bdfSopenharmony_ci d[i] = s[i]; 286f08c3bdfSopenharmony_ci return; 287f08c3bdfSopenharmony_ci} 288f08c3bdfSopenharmony_ci 289f08c3bdfSopenharmony_cistatic void allocate(void) 290f08c3bdfSopenharmony_ci{ 291f08c3bdfSopenharmony_ci unsigned int i; 292f08c3bdfSopenharmony_ci 293f08c3bdfSopenharmony_ci mem = alloc_mem(chunks * sizeof(record_t *)); 294f08c3bdfSopenharmony_ci 295f08c3bdfSopenharmony_ci if (use_holes) 296f08c3bdfSopenharmony_ci hole_mem = alloc_mem(chunks * sizeof(record_t *)); 297f08c3bdfSopenharmony_ci 298f08c3bdfSopenharmony_ci for (i = 0; i < chunks; i++) { 299f08c3bdfSopenharmony_ci mem[i] = (record_t *) alloc_mem(chunk_size); 300f08c3bdfSopenharmony_ci /* Prevent coalescing using holes */ 301f08c3bdfSopenharmony_ci if (use_holes) 302f08c3bdfSopenharmony_ci hole_mem[i] = alloc_mem(page_size); 303f08c3bdfSopenharmony_ci } 304f08c3bdfSopenharmony_ci 305f08c3bdfSopenharmony_ci /* Free hole memory */ 306f08c3bdfSopenharmony_ci if (use_holes) 307f08c3bdfSopenharmony_ci for (i = 0; i < chunks; i++) 308f08c3bdfSopenharmony_ci free_mem(hole_mem[i], page_size); 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci if (verbose) 311f08c3bdfSopenharmony_ci printf("Allocated memory\n"); 312f08c3bdfSopenharmony_ci} 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_cistatic void write_pattern(void) 315f08c3bdfSopenharmony_ci{ 316f08c3bdfSopenharmony_ci unsigned int i, j; 317f08c3bdfSopenharmony_ci 318f08c3bdfSopenharmony_ci for (i = 0; i < chunks; i++) { 319f08c3bdfSopenharmony_ci for (j = 0; j < chunk_size / record_size; j++) 320f08c3bdfSopenharmony_ci mem[i][j] = (record_t) j; 321f08c3bdfSopenharmony_ci /* Prevent coalescing by alternating permissions */ 322f08c3bdfSopenharmony_ci if (use_permissions && (i % 2) == 0) 323f08c3bdfSopenharmony_ci mprotect((void *)mem[i], chunk_size, PROT_READ); 324f08c3bdfSopenharmony_ci } 325f08c3bdfSopenharmony_ci if (verbose) 326f08c3bdfSopenharmony_ci printf("Wrote memory\n"); 327f08c3bdfSopenharmony_ci} 328f08c3bdfSopenharmony_ci 329f08c3bdfSopenharmony_cistatic void *linear_search(record_t key, record_t * base, size_t size) 330f08c3bdfSopenharmony_ci{ 331f08c3bdfSopenharmony_ci record_t *p; 332f08c3bdfSopenharmony_ci record_t *end = base + (size / record_size); 333f08c3bdfSopenharmony_ci 334f08c3bdfSopenharmony_ci for (p = base; p < end; p++) 335f08c3bdfSopenharmony_ci if (*p == key) 336f08c3bdfSopenharmony_ci return p; 337f08c3bdfSopenharmony_ci return NULL; 338f08c3bdfSopenharmony_ci} 339f08c3bdfSopenharmony_ci 340f08c3bdfSopenharmony_cistatic int compare(const void *p1, const void *p2) 341f08c3bdfSopenharmony_ci{ 342f08c3bdfSopenharmony_ci return (*(record_t *) p1 - *(record_t *) p2); 343f08c3bdfSopenharmony_ci} 344f08c3bdfSopenharmony_ci 345f08c3bdfSopenharmony_ci/* 346f08c3bdfSopenharmony_ci * Stupid ranged random number function. We don't care about quality. 347f08c3bdfSopenharmony_ci * 348f08c3bdfSopenharmony_ci * Inline because it's starting to be a scaling issue. 349f08c3bdfSopenharmony_ci */ 350f08c3bdfSopenharmony_ci 351f08c3bdfSopenharmony_cistatic inline unsigned int rand_num(unsigned int max, unsigned int *state) 352f08c3bdfSopenharmony_ci{ 353f08c3bdfSopenharmony_ci *state *= 1103515245 + 12345; 354f08c3bdfSopenharmony_ci return ((*state / 65536) % max); 355f08c3bdfSopenharmony_ci} 356f08c3bdfSopenharmony_ci 357f08c3bdfSopenharmony_ci/* 358f08c3bdfSopenharmony_ci * This function is the meat of the program; the rest is just support. 359f08c3bdfSopenharmony_ci * 360f08c3bdfSopenharmony_ci * In this function, we randomly select a memory chunk, copy it into a 361f08c3bdfSopenharmony_ci * newly allocated buffer, randomly select a search key, look it up, 362f08c3bdfSopenharmony_ci * then free the memory. An option tells us to allocate and copy a 363f08c3bdfSopenharmony_ci * randomly sized chunk of the memory instead of the whole thing. 364f08c3bdfSopenharmony_ci * 365f08c3bdfSopenharmony_ci * Linear search provided for sanity checking. 366f08c3bdfSopenharmony_ci * 367f08c3bdfSopenharmony_ci */ 368f08c3bdfSopenharmony_ci 369f08c3bdfSopenharmony_cistatic uintptr_t search_mem(void) 370f08c3bdfSopenharmony_ci{ 371f08c3bdfSopenharmony_ci record_t key, *found; 372f08c3bdfSopenharmony_ci record_t *src, *copy; 373f08c3bdfSopenharmony_ci unsigned int chunk; 374f08c3bdfSopenharmony_ci size_t copy_size = chunk_size; 375f08c3bdfSopenharmony_ci uintptr_t i; 376f08c3bdfSopenharmony_ci unsigned int state = 0; 377f08c3bdfSopenharmony_ci 378f08c3bdfSopenharmony_ci for (i = 0; threads_go == 1; i++) { 379f08c3bdfSopenharmony_ci chunk = rand_num(chunks, &state); 380f08c3bdfSopenharmony_ci src = mem[chunk]; 381f08c3bdfSopenharmony_ci /* 382f08c3bdfSopenharmony_ci * If we're doing random sizes, we need a non-zero 383f08c3bdfSopenharmony_ci * multiple of record size. 384f08c3bdfSopenharmony_ci */ 385f08c3bdfSopenharmony_ci if (random_size) 386f08c3bdfSopenharmony_ci copy_size = (rand_num(chunk_size / record_size, &state) 387f08c3bdfSopenharmony_ci + 1) * record_size; 388f08c3bdfSopenharmony_ci copy = alloc_mem(copy_size); 389f08c3bdfSopenharmony_ci 390f08c3bdfSopenharmony_ci if (touch_pages) { 391f08c3bdfSopenharmony_ci touch_mem((char *)copy, copy_size); 392f08c3bdfSopenharmony_ci } else { 393f08c3bdfSopenharmony_ci 394f08c3bdfSopenharmony_ci if (no_lib_memcpy) 395f08c3bdfSopenharmony_ci my_memcpy(copy, src, copy_size); 396f08c3bdfSopenharmony_ci else 397f08c3bdfSopenharmony_ci memcpy(copy, src, copy_size); 398f08c3bdfSopenharmony_ci 399f08c3bdfSopenharmony_ci key = rand_num(copy_size / record_size, &state); 400f08c3bdfSopenharmony_ci 401f08c3bdfSopenharmony_ci if (verbose > 2) 402f08c3bdfSopenharmony_ci printf("Search key %zu, copy size %zu\n", key, 403f08c3bdfSopenharmony_ci copy_size); 404f08c3bdfSopenharmony_ci if (linear) 405f08c3bdfSopenharmony_ci found = linear_search(key, copy, copy_size); 406f08c3bdfSopenharmony_ci else 407f08c3bdfSopenharmony_ci found = 408f08c3bdfSopenharmony_ci bsearch(&key, copy, copy_size / record_size, 409f08c3bdfSopenharmony_ci record_size, compare); 410f08c3bdfSopenharmony_ci 411f08c3bdfSopenharmony_ci /* Below check is mainly for memory corruption or other bug */ 412f08c3bdfSopenharmony_ci if (found == NULL) { 413f08c3bdfSopenharmony_ci fprintf(stderr, "Couldn't find key %zd\n", key); 414f08c3bdfSopenharmony_ci exit(1); 415f08c3bdfSopenharmony_ci } 416f08c3bdfSopenharmony_ci } /* end if ! touch_pages */ 417f08c3bdfSopenharmony_ci 418f08c3bdfSopenharmony_ci free_mem(copy, copy_size); 419f08c3bdfSopenharmony_ci } 420f08c3bdfSopenharmony_ci 421f08c3bdfSopenharmony_ci return (i); 422f08c3bdfSopenharmony_ci} 423f08c3bdfSopenharmony_ci 424f08c3bdfSopenharmony_cistatic void *thread_run(void *arg __attribute__((unused))) 425f08c3bdfSopenharmony_ci{ 426f08c3bdfSopenharmony_ci uintptr_t records_thread; 427f08c3bdfSopenharmony_ci 428f08c3bdfSopenharmony_ci if (verbose > 1) 429f08c3bdfSopenharmony_ci printf("Thread started\n"); 430f08c3bdfSopenharmony_ci 431f08c3bdfSopenharmony_ci /* Wait for the start signal */ 432f08c3bdfSopenharmony_ci 433f08c3bdfSopenharmony_ci while (threads_go == 0) ; 434f08c3bdfSopenharmony_ci 435f08c3bdfSopenharmony_ci records_thread = search_mem(); 436f08c3bdfSopenharmony_ci 437f08c3bdfSopenharmony_ci if (verbose > 1) 438f08c3bdfSopenharmony_ci printf("Thread finished, %f seconds\n", 439f08c3bdfSopenharmony_ci difftime(time(NULL), start_time)); 440f08c3bdfSopenharmony_ci 441f08c3bdfSopenharmony_ci return (void *)records_thread; 442f08c3bdfSopenharmony_ci} 443f08c3bdfSopenharmony_ci 444f08c3bdfSopenharmony_cistatic struct timeval difftimeval(struct timeval *end, struct timeval *start) 445f08c3bdfSopenharmony_ci{ 446f08c3bdfSopenharmony_ci struct timeval diff; 447f08c3bdfSopenharmony_ci diff.tv_sec = end->tv_sec - start->tv_sec; 448f08c3bdfSopenharmony_ci diff.tv_usec = end->tv_usec - start->tv_usec; 449f08c3bdfSopenharmony_ci return diff; 450f08c3bdfSopenharmony_ci} 451f08c3bdfSopenharmony_ci 452f08c3bdfSopenharmony_cistatic void start_threads(void) 453f08c3bdfSopenharmony_ci{ 454f08c3bdfSopenharmony_ci pthread_t thread_array[threads]; 455f08c3bdfSopenharmony_ci double elapsed; 456f08c3bdfSopenharmony_ci unsigned int i; 457f08c3bdfSopenharmony_ci struct rusage start_ru, end_ru; 458f08c3bdfSopenharmony_ci struct timeval usr_time, sys_time; 459f08c3bdfSopenharmony_ci double records_per_sec = 0.0; 460f08c3bdfSopenharmony_ci int err; 461f08c3bdfSopenharmony_ci 462f08c3bdfSopenharmony_ci if (verbose) 463f08c3bdfSopenharmony_ci printf("Threads starting\n"); 464f08c3bdfSopenharmony_ci 465f08c3bdfSopenharmony_ci for (i = 0; i < threads; i++) { 466f08c3bdfSopenharmony_ci err = pthread_create(&thread_array[i], NULL, thread_run, NULL); 467f08c3bdfSopenharmony_ci if (err) { 468f08c3bdfSopenharmony_ci fprintf(stderr, "Error creating thread %d\n", i); 469f08c3bdfSopenharmony_ci exit(1); 470f08c3bdfSopenharmony_ci } 471f08c3bdfSopenharmony_ci } 472f08c3bdfSopenharmony_ci 473f08c3bdfSopenharmony_ci /* 474f08c3bdfSopenharmony_ci * Begin accounting - this is when we actually do the things 475f08c3bdfSopenharmony_ci * we want to measure. */ 476f08c3bdfSopenharmony_ci 477f08c3bdfSopenharmony_ci getrusage(RUSAGE_SELF, &start_ru); 478f08c3bdfSopenharmony_ci start_time = time(NULL); 479f08c3bdfSopenharmony_ci threads_go = 1; 480f08c3bdfSopenharmony_ci sleep(seconds); 481f08c3bdfSopenharmony_ci threads_go = 0; 482f08c3bdfSopenharmony_ci elapsed = difftime(time(NULL), start_time); 483f08c3bdfSopenharmony_ci getrusage(RUSAGE_SELF, &end_ru); 484f08c3bdfSopenharmony_ci 485f08c3bdfSopenharmony_ci /* 486f08c3bdfSopenharmony_ci * The rest is just clean up. 487f08c3bdfSopenharmony_ci */ 488f08c3bdfSopenharmony_ci 489f08c3bdfSopenharmony_ci for (i = 0; i < threads; i++) { 490f08c3bdfSopenharmony_ci uintptr_t record_thread; 491f08c3bdfSopenharmony_ci err = pthread_join(thread_array[i], (void *)&record_thread); 492f08c3bdfSopenharmony_ci if (err) { 493f08c3bdfSopenharmony_ci fprintf(stderr, "Error joining thread %d\n", i); 494f08c3bdfSopenharmony_ci exit(1); 495f08c3bdfSopenharmony_ci } 496f08c3bdfSopenharmony_ci records_per_sec += ((double)record_thread / elapsed); 497f08c3bdfSopenharmony_ci } 498f08c3bdfSopenharmony_ci 499f08c3bdfSopenharmony_ci if (verbose) 500f08c3bdfSopenharmony_ci printf("Threads finished\n"); 501f08c3bdfSopenharmony_ci 502f08c3bdfSopenharmony_ci printf("%tu records/s\n", (uintptr_t) records_per_sec); 503f08c3bdfSopenharmony_ci 504f08c3bdfSopenharmony_ci usr_time = difftimeval(&end_ru.ru_utime, &start_ru.ru_utime); 505f08c3bdfSopenharmony_ci sys_time = difftimeval(&end_ru.ru_stime, &start_ru.ru_stime); 506f08c3bdfSopenharmony_ci 507f08c3bdfSopenharmony_ci printf("real %5.2f s\n", elapsed); 508f08c3bdfSopenharmony_ci printf("user %5.2f s\n", usr_time.tv_sec + usr_time.tv_usec / 1e6); 509f08c3bdfSopenharmony_ci printf("sys %5.2f s\n", sys_time.tv_sec + sys_time.tv_usec / 1e6); 510f08c3bdfSopenharmony_ci} 511f08c3bdfSopenharmony_ci 512f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 513f08c3bdfSopenharmony_ci{ 514f08c3bdfSopenharmony_ci read_options(argc, argv); 515f08c3bdfSopenharmony_ci 516f08c3bdfSopenharmony_ci allocate(); 517f08c3bdfSopenharmony_ci 518f08c3bdfSopenharmony_ci write_pattern(); 519f08c3bdfSopenharmony_ci 520f08c3bdfSopenharmony_ci start_threads(); 521f08c3bdfSopenharmony_ci 522f08c3bdfSopenharmony_ci return 0; 523f08c3bdfSopenharmony_ci} 524