1#!/bin/sh 2 3# 4# Copyright (c) 2025 Peter Holm <pho@FreeBSD.org> 5# 6# SPDX-License-Identifier: BSD-2-Clause 7# 8 9. ../default.cfg 10set -u 11prog=$(basename "$0" .sh) 12cat > /tmp/$prog.c <<EOF 13/* N readers and 1 writer threaded test scenario */ 14 15#include <sys/types.h> 16#include <sys/mman.h> 17 18#include <assert.h> 19#include <err.h> 20#include <pthread.h> 21#include <signal.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <string.h> 25#include <time.h> 26#include <unistd.h> 27 28static int go, n, ps; 29static char *cp; 30static volatile char v; 31 32void * 33rd(void *arg __unused) 34{ 35 int i; 36 37 while (go == 0) 38 usleep(100); 39 while (go == 1) { 40 for (i = 0; i < n; i += ps) { 41 v = cp[i]; 42 } 43 pthread_yield(); 44 } 45 return(NULL); 46} 47 48void 49usage(char *prog) { 50 fprintf(stderr, "Usage: %s <number of threads>\n", prog); 51 _exit(1); 52} 53 54int 55main(int argc, char *argv[]) 56{ 57 pthread_t *tid; 58 time_t start; 59 int e, i, nb; 60 61 if (argc != 2) 62 usage(argv[0]); 63 if (sscanf(argv[1], "%d", &n) != 1) 64 usage(argv[0]); 65 if (n > 1) 66 n--; 67 if ((tid = calloc(n, sizeof(pthread_t *))) == NULL) 68 err(1, "calloc()"); 69 70 ps = getpagesize(); 71 cp = mmap(NULL, n * ps, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); 72 go = 0; 73 for (i = 0; i < n; i++) { 74 if ((e = pthread_create(&tid[i], NULL, rd, NULL)) != 0) 75 errc(1, e, "pthread_create()"); 76 } 77 go = 1; 78 79 nb = 0; 80 start = time(NULL); 81 while (time(NULL) - start < 120) { 82 for (i = 0; i < n; i += ps) { 83 if (mprotect(&cp[i], ps, PROT_READ|PROT_WRITE) == -1) 84 err(1, "mprotect(PROT_READ)"); 85 cp[i] = 1; 86 if (mprotect(&cp[i], ps, PROT_READ) == -1) 87 err(1, "mprotect(PROT_READ)"); 88 nb++; 89 } 90 } 91 go = 0; 92 for (i = 0; i < n; i++) { 93 if ((e = pthread_join(tid[i], NULL)) != 0) 94 errc(1, e, "pthread_join() in loop %d", i); 95 } 96 if (nb >= 0) { 97#if defined(DEBUG) 98 fprintf(stderr, "%d loops\n", nb); 99#endif 100 ; 101 } 102} 103EOF 104mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 105 106/tmp/$prog `sysctl -n hw.ncpu`; s=$? 107 108rm -d /tmp/$prog /tmp/$prog.c 109exit $s 110