1 /* $OpenBSD: pthread_rwlock2.c,v 1.1 2019/03/04 08:23:05 semarie Exp $ */ 2 /* 3 * Copyright (c) 2019 Sebastien Marie <semarie@online.fr> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <err.h> 19 #include <pthread.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #define LOOP_MAIN 64 /* number of loop to try */ 25 #define NTHREADS 16 /* number of concurrents threads */ 26 27 /* 28 * start several threads that share a buffer protected by rwlock. 29 * 30 * for each thread, take lock rw to set the buffer, and next take lock 31 * rd to read (print) the buffer content. 32 */ 33 34 static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; 35 static char msg[128] = "default message"; 36 37 void 38 set_msg(int self_n, char *new_msg) 39 { 40 pthread_t self = pthread_self(); 41 42 if (pthread_rwlock_wrlock(&rwlock) != 0) 43 err(EXIT_FAILURE, "set_msg: pthread_rwlock_wrlock"); 44 45 printf("%p: %d: set_msg\n", self, self_n); 46 strlcpy(msg, new_msg, sizeof(msg)); 47 48 if (pthread_rwlock_unlock(&rwlock) != 0) 49 err(EXIT_FAILURE, "set_msg: pthread_rwlock_unlock"); 50 } 51 52 void 53 print_msg(int self_n) 54 { 55 pthread_t self = pthread_self(); 56 57 if (pthread_rwlock_rdlock(&rwlock) != 0) 58 err(EXIT_FAILURE, "print_msg: pthread_rwlock_rdlock"); 59 60 printf("%p: %d: msg: \"%s\"\n", self, self_n, msg); 61 62 if (pthread_rwlock_unlock(&rwlock) != 0) 63 err(EXIT_FAILURE, "print_msg: pthread_rwlock_unlock"); 64 } 65 66 void * 67 run(void *data) 68 { 69 int self_n = (int)data; 70 pthread_t self = pthread_self(); 71 72 printf("%p: %d: enter run()\n", self, self_n); 73 74 set_msg(self_n, "new message"); 75 print_msg(self_n); 76 77 printf("%p: %d: exit run()\n", self, self_n); 78 return NULL; 79 } 80 81 int 82 main(int argc, char *argv[]) 83 { 84 int i, j; 85 86 /* enable some rthread debug code (env take precedence) */ 87 if (setenv("RTHREAD_DEBUG", "9", 0) == -1) 88 err(EXIT_FAILURE, "setenv"); 89 90 /* test in loop */ 91 for (i=0; i < LOOP_MAIN; i++) { 92 pthread_t handlers[NTHREADS]; 93 94 printf("main: %d\n", i); 95 96 /* launch a serie of threads */ 97 for (j=0; j < NTHREADS; j++) { 98 if (pthread_create(&(handlers[j]), NULL, 99 &run, (void *)(long)j) != 0) 100 err(EXIT_FAILURE, "main: pthread_create"); 101 } 102 103 /* wait for them to finish */ 104 for (j=0; j < NTHREADS; j++) { 105 if (pthread_join(handlers[j], NULL) != 0) 106 err(EXIT_FAILURE, "main: pthread_join"); 107 } 108 } 109 110 return EXIT_SUCCESS; 111 } 112