1*ef777be9SPeter Holm#!/bin/sh 2*ef777be9SPeter Holm 3*ef777be9SPeter Holm# 4*ef777be9SPeter Holm# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> 5*ef777be9SPeter Holm# 6*ef777be9SPeter Holm# SPDX-License-Identifier: BSD-2-Clause 7*ef777be9SPeter Holm# 8*ef777be9SPeter Holm 9*ef777be9SPeter Holm. ../default.cfg 10*ef777be9SPeter Holmset -u 11*ef777be9SPeter Holmprog=$(basename "$0" .sh) 12*ef777be9SPeter Holmcat > /tmp/$prog.c <<EOF 13*ef777be9SPeter Holm#include <sys/types.h> 14*ef777be9SPeter Holm#include <sys/mman.h> 15*ef777be9SPeter Holm 16*ef777be9SPeter Holm#include <assert.h> 17*ef777be9SPeter Holm#include <err.h> 18*ef777be9SPeter Holm#include <pthread.h> 19*ef777be9SPeter Holm#include <signal.h> 20*ef777be9SPeter Holm#include <stdio.h> 21*ef777be9SPeter Holm#include <stdlib.h> 22*ef777be9SPeter Holm#include <string.h> 23*ef777be9SPeter Holm#include <time.h> 24*ef777be9SPeter Holm#include <unistd.h> 25*ef777be9SPeter Holm 26*ef777be9SPeter Holmstatic pthread_mutex_t write_mutex; 27*ef777be9SPeter Holmstatic volatile int done; 28*ef777be9SPeter Holmstatic int go, n, *once, *p, ps; 29*ef777be9SPeter Holm 30*ef777be9SPeter Holmstatic void * 31*ef777be9SPeter Holmwr(void *arg) 32*ef777be9SPeter Holm{ 33*ef777be9SPeter Holm int idx; 34*ef777be9SPeter Holm 35*ef777be9SPeter Holm alarm(180); 36*ef777be9SPeter Holm idx = *(int *)arg; 37*ef777be9SPeter Holm while (go == 0) 38*ef777be9SPeter Holm usleep(100); 39*ef777be9SPeter Holm while (go == 1) { 40*ef777be9SPeter Holm while (go == 1 && once[idx] == 0) 41*ef777be9SPeter Holm usleep(100); 42*ef777be9SPeter Holm if (go == 0) 43*ef777be9SPeter Holm break; 44*ef777be9SPeter Holm p[idx]++; 45*ef777be9SPeter Holm once[idx] = 0; 46*ef777be9SPeter Holm pthread_mutex_lock(&write_mutex); 47*ef777be9SPeter Holm done++; 48*ef777be9SPeter Holm pthread_mutex_unlock(&write_mutex); 49*ef777be9SPeter Holm } 50*ef777be9SPeter Holm return(NULL); 51*ef777be9SPeter Holm} 52*ef777be9SPeter Holm 53*ef777be9SPeter Holmstatic void 54*ef777be9SPeter Holmsetonce(int val) 55*ef777be9SPeter Holm{ 56*ef777be9SPeter Holm int i; 57*ef777be9SPeter Holm 58*ef777be9SPeter Holm for (i = 0; i < n; i++) 59*ef777be9SPeter Holm once[i] = val; 60*ef777be9SPeter Holm} 61*ef777be9SPeter Holm 62*ef777be9SPeter Holmstatic void 63*ef777be9SPeter Holmusage(char *prog) { 64*ef777be9SPeter Holm fprintf(stderr, "Usage: %s <number of threads>\n", prog); 65*ef777be9SPeter Holm _exit(1); 66*ef777be9SPeter Holm} 67*ef777be9SPeter Holm 68*ef777be9SPeter Holmint 69*ef777be9SPeter Holmmain(int argc, char *argv[]) 70*ef777be9SPeter Holm{ 71*ef777be9SPeter Holm pthread_t *tid; 72*ef777be9SPeter Holm time_t start; 73*ef777be9SPeter Holm int *arg; 74*ef777be9SPeter Holm int e, i, nb, r; 75*ef777be9SPeter Holm 76*ef777be9SPeter Holm if (argc != 2) 77*ef777be9SPeter Holm usage(argv[0]); 78*ef777be9SPeter Holm if (sscanf(argv[1], "%d", &n) != 1) 79*ef777be9SPeter Holm usage(argv[0]); 80*ef777be9SPeter Holm if (n > 1) 81*ef777be9SPeter Holm n--; 82*ef777be9SPeter Holm if ((tid = calloc(n, sizeof(pthread_t *))) == NULL) 83*ef777be9SPeter Holm err(1, "calloc()"); 84*ef777be9SPeter Holm if ((once = calloc(n, sizeof(int *))) == NULL) 85*ef777be9SPeter Holm err(1, "calloc()"); 86*ef777be9SPeter Holm setonce(0); 87*ef777be9SPeter Holm 88*ef777be9SPeter Holm ps = getpagesize(); 89*ef777be9SPeter Holm p = mmap(NULL, n * ps, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); 90*ef777be9SPeter Holm go = 0; 91*ef777be9SPeter Holm pthread_mutex_init(&write_mutex, NULL); 92*ef777be9SPeter Holm for (i = 0; i < n; i++) { 93*ef777be9SPeter Holm arg = malloc(sizeof(int)); 94*ef777be9SPeter Holm *arg = i; 95*ef777be9SPeter Holm if ((e = pthread_create(&tid[i], NULL, wr, (void *)arg)) != 0) 96*ef777be9SPeter Holm errc(1, e, "pthread_create()"); 97*ef777be9SPeter Holm } 98*ef777be9SPeter Holm go = 1; 99*ef777be9SPeter Holm 100*ef777be9SPeter Holm nb = 0; 101*ef777be9SPeter Holm start = time(NULL); 102*ef777be9SPeter Holm while (time(NULL) - start < 120) { 103*ef777be9SPeter Holm if (mprotect(p, n * ps, PROT_READ|PROT_WRITE) == -1) 104*ef777be9SPeter Holm err(1, "mprotect(PROT_READ)"); 105*ef777be9SPeter Holm done = 0; 106*ef777be9SPeter Holm setonce(1); 107*ef777be9SPeter Holm while (done != n) 108*ef777be9SPeter Holm usleep(100); 109*ef777be9SPeter Holm if (mprotect(p, n * ps, PROT_READ) == -1) 110*ef777be9SPeter Holm err(1, "mprotect(PROT_READ)"); 111*ef777be9SPeter Holm nb++; 112*ef777be9SPeter Holm usleep(100); 113*ef777be9SPeter Holm } 114*ef777be9SPeter Holm go = 0; 115*ef777be9SPeter Holm for (i = 0; i < n; i++) { 116*ef777be9SPeter Holm if ((e = pthread_join(tid[i], NULL)) != 0) 117*ef777be9SPeter Holm errc(1, e, "pthread_join() in loop %d", i); 118*ef777be9SPeter Holm } 119*ef777be9SPeter Holm r = 0; 120*ef777be9SPeter Holm for (i = 1; i < n; i++) { 121*ef777be9SPeter Holm if (p[0] != p[i]) 122*ef777be9SPeter Holm r++; 123*ef777be9SPeter Holm } 124*ef777be9SPeter Holm if (r != 0) { 125*ef777be9SPeter Holm fprintf(stderr, "%d loops.\n", nb); 126*ef777be9SPeter Holm for (i = 0; i < n; i++) 127*ef777be9SPeter Holm fprintf(stderr, "p[%3d] = %d\n", i, p[i]); 128*ef777be9SPeter Holm } 129*ef777be9SPeter Holm 130*ef777be9SPeter Holm return (r); 131*ef777be9SPeter Holm} 132*ef777be9SPeter HolmEOF 133*ef777be9SPeter Holmmycc -o /tmp/$prog -Wall -Wextra -O0 -g /tmp/$prog.c -lpthread || exit 1 134*ef777be9SPeter Holm 135*ef777be9SPeter Holmn=`sysctl -n hw.ncpu` 136*ef777be9SPeter Holmif [ $# -eq 1 ]; then 137*ef777be9SPeter Holm echo $1 | grep -Eq '^[0-9]+$' && n=$1 138*ef777be9SPeter Holmfi 139*ef777be9SPeter Holm../testcases/swap/swap -t 2m > /dev/null & 140*ef777be9SPeter Holmsleep 10 141*ef777be9SPeter Holm/tmp/$prog $n; s=$? 142*ef777be9SPeter Holmpkill -9 swap 143*ef777be9SPeter Holmwait 144*ef777be9SPeter Holm 145*ef777be9SPeter Holmrm -d /tmp/$prog /tmp/$prog.c 146*ef777be9SPeter Holmexit $s 147