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 writers 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 pthread_mutex_t write_mutex; 29static int go, n, ps; 30static char *cp, *wp; 31 32void * 33wr(void *arg __unused) 34{ 35 while (go == 0) 36 usleep(100); 37 while (go == 1) { 38 pthread_mutex_lock(&write_mutex); 39 if (wp != NULL) 40 *wp += 1; 41 pthread_mutex_unlock(&write_mutex); 42 } 43 return(NULL); 44} 45 46void 47usage(char *prog) { 48 fprintf(stderr, "Usage: %s <number of threads>\n", prog); 49 _exit(1); 50} 51 52int 53main(int argc, char *argv[]) 54{ 55 pthread_t *tid; 56 time_t start; 57 int e, i, nb; 58 59 if (argc != 2) 60 usage(argv[0]); 61 if (sscanf(argv[1], "%d", &n) != 1) 62 usage(argv[0]); 63 if (n > 1) 64 n--; 65 if ((tid = calloc(n, sizeof(pthread_t *))) == NULL) 66 err(1, "calloc()"); 67 68 ps = getpagesize(); 69 cp = mmap(NULL, n * ps, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0); 70 pthread_mutex_init(&write_mutex, NULL); 71 pthread_mutex_lock(&write_mutex); 72 go = 0; 73 for (i = 0; i < n; i++) { 74 if ((e = pthread_create(&tid[i], NULL, wr, 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 pthread_mutex_lock(&write_mutex); 84 if (mprotect(&cp[i], ps, PROT_READ|PROT_WRITE) == -1) 85 err(1, "mprotect(PROT_READ)"); 86 cp[i] = 0; 87 wp = &cp[i]; 88 pthread_mutex_unlock(&write_mutex); 89 90 usleep(100); 91 92 pthread_mutex_lock(&write_mutex); 93 if (mprotect(&cp[i], ps, PROT_READ) == -1) 94 err(1, "mprotect(PROT_READ)"); 95 wp = NULL; 96 pthread_mutex_unlock(&write_mutex); 97 nb++; 98 } 99 } 100 go = 0; 101 for (i = 0; i < n; i++) { 102 if ((e = pthread_join(tid[i], NULL)) != 0) 103 errc(1, e, "pthread_join() in loop %d", i); 104 } 105 if (nb >= 0) { 106#if defined(DEBUG) 107 fprintf(stderr, "%d loops\n", nb); 108#endif 109 ; 110 } 111} 112EOF 113mycc -o /tmp/$prog -Wall -Wextra -O0 /tmp/$prog.c -lpthread || exit 1 114 115/tmp/$prog `sysctl -n hw.ncpu`; s=$? 116 117rm -d /tmp/$prog /tmp/$prog.c 118exit $s 119