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/* N writers threaded test scenario */ 14*ef777be9SPeter Holm 15*ef777be9SPeter Holm#include <sys/types.h> 16*ef777be9SPeter Holm#include <sys/mman.h> 17*ef777be9SPeter Holm 18*ef777be9SPeter Holm#include <assert.h> 19*ef777be9SPeter Holm#include <err.h> 20*ef777be9SPeter Holm#include <pthread.h> 21*ef777be9SPeter Holm#include <signal.h> 22*ef777be9SPeter Holm#include <stdio.h> 23*ef777be9SPeter Holm#include <stdlib.h> 24*ef777be9SPeter Holm#include <string.h> 25*ef777be9SPeter Holm#include <time.h> 26*ef777be9SPeter Holm#include <unistd.h> 27*ef777be9SPeter Holm 28*ef777be9SPeter Holmstatic pthread_mutex_t write_mutex; 29*ef777be9SPeter Holmstatic int go, n, ps; 30*ef777be9SPeter Holmstatic char *cp, *wp; 31*ef777be9SPeter Holm 32*ef777be9SPeter Holmvoid * 33*ef777be9SPeter Holmwr(void *arg __unused) 34*ef777be9SPeter Holm{ 35*ef777be9SPeter Holm while (go == 0) 36*ef777be9SPeter Holm usleep(100); 37*ef777be9SPeter Holm while (go == 1) { 38*ef777be9SPeter Holm pthread_mutex_lock(&write_mutex); 39*ef777be9SPeter Holm if (wp != NULL) 40*ef777be9SPeter Holm *wp += 1; 41*ef777be9SPeter Holm pthread_mutex_unlock(&write_mutex); 42*ef777be9SPeter Holm } 43*ef777be9SPeter Holm return(NULL); 44*ef777be9SPeter Holm} 45*ef777be9SPeter Holm 46*ef777be9SPeter Holmvoid 47*ef777be9SPeter Holmusage(char *prog) { 48*ef777be9SPeter Holm fprintf(stderr, "Usage: %s <number of threads>\n", prog); 49*ef777be9SPeter Holm _exit(1); 50*ef777be9SPeter Holm} 51*ef777be9SPeter Holm 52*ef777be9SPeter Holmint 53*ef777be9SPeter Holmmain(int argc, char *argv[]) 54*ef777be9SPeter Holm{ 55*ef777be9SPeter Holm pthread_t *tid; 56*ef777be9SPeter Holm time_t start; 57*ef777be9SPeter Holm int e, i, nb; 58*ef777be9SPeter Holm 59*ef777be9SPeter Holm if (argc != 2) 60*ef777be9SPeter Holm usage(argv[0]); 61*ef777be9SPeter Holm if (sscanf(argv[1], "%d", &n) != 1) 62*ef777be9SPeter Holm usage(argv[0]); 63*ef777be9SPeter Holm if (n > 1) 64*ef777be9SPeter Holm n--; 65*ef777be9SPeter Holm if ((tid = calloc(n, sizeof(pthread_t *))) == NULL) 66*ef777be9SPeter Holm err(1, "calloc()"); 67*ef777be9SPeter Holm 68*ef777be9SPeter Holm ps = getpagesize(); 69*ef777be9SPeter Holm cp = mmap(NULL, n * ps, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); 70*ef777be9SPeter Holm pthread_mutex_init(&write_mutex, NULL); 71*ef777be9SPeter Holm pthread_mutex_lock(&write_mutex); 72*ef777be9SPeter Holm go = 0; 73*ef777be9SPeter Holm for (i = 0; i < n; i++) { 74*ef777be9SPeter Holm if ((e = pthread_create(&tid[i], NULL, wr, NULL)) != 0) 75*ef777be9SPeter Holm errc(1, e, "pthread_create()"); 76*ef777be9SPeter Holm } 77*ef777be9SPeter Holm go = 1; 78*ef777be9SPeter Holm 79*ef777be9SPeter Holm nb = 0; 80*ef777be9SPeter Holm start = time(NULL); 81*ef777be9SPeter Holm while (time(NULL) - start < 120) { 82*ef777be9SPeter Holm for (i = 0; i < n; i += ps) { 83*ef777be9SPeter Holm pthread_mutex_lock(&write_mutex); 84*ef777be9SPeter Holm if (mprotect(&cp[i], ps, PROT_READ|PROT_WRITE) == -1) 85*ef777be9SPeter Holm err(1, "mprotect(PROT_READ)"); 86*ef777be9SPeter Holm cp[i] = 0; 87*ef777be9SPeter Holm wp = &cp[i]; 88*ef777be9SPeter Holm pthread_mutex_unlock(&write_mutex); 89*ef777be9SPeter Holm 90*ef777be9SPeter Holm usleep(100); 91*ef777be9SPeter Holm 92*ef777be9SPeter Holm pthread_mutex_lock(&write_mutex); 93*ef777be9SPeter Holm if (mprotect(&cp[i], ps, PROT_READ) == -1) 94*ef777be9SPeter Holm err(1, "mprotect(PROT_READ)"); 95*ef777be9SPeter Holm wp = NULL; 96*ef777be9SPeter Holm pthread_mutex_unlock(&write_mutex); 97*ef777be9SPeter Holm nb++; 98*ef777be9SPeter Holm } 99*ef777be9SPeter Holm } 100*ef777be9SPeter Holm go = 0; 101*ef777be9SPeter Holm for (i = 0; i < n; i++) { 102*ef777be9SPeter Holm if ((e = pthread_join(tid[i], NULL)) != 0) 103*ef777be9SPeter Holm errc(1, e, "pthread_join() in loop %d", i); 104*ef777be9SPeter Holm } 105*ef777be9SPeter Holm if (nb >= 0) { 106*ef777be9SPeter Holm#if defined(DEBUG) 107*ef777be9SPeter Holm fprintf(stderr, "%d loops\n", nb); 108*ef777be9SPeter Holm#endif 109*ef777be9SPeter Holm ; 110*ef777be9SPeter Holm } 111*ef777be9SPeter Holm} 112*ef777be9SPeter HolmEOF 113*ef777be9SPeter Holmmycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 114*ef777be9SPeter Holm 115*ef777be9SPeter Holm/tmp/$prog `sysctl -n hw.ncpu`; s=$? 116*ef777be9SPeter Holm 117*ef777be9SPeter Holmrm -d /tmp/$prog /tmp/$prog.c 118*ef777be9SPeter Holmexit $s 119