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