1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17
18 #include <isc/print.h>
19 #include <isc/rwlock.h>
20 #include <isc/string.h>
21 #include <isc/thread.h>
22 #include <isc/util.h>
23
24 #ifdef WIN32
25 #define sleep(x) Sleep(1000 * x)
26 #endif /* ifdef WIN32 */
27
28 isc_rwlock_t lock;
29
30 static isc_threadresult_t
31 #ifdef WIN32
32 WINAPI
33 #endif /* ifdef WIN32 */
run1(void * arg)34 run1(void *arg) {
35 char *message = arg;
36
37 RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
38 ISC_R_SUCCESS);
39 printf("%s got READ lock\n", message);
40 sleep(1);
41 printf("%s giving up READ lock\n", message);
42 RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
43 ISC_R_SUCCESS);
44 RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
45 ISC_R_SUCCESS);
46 printf("%s got READ lock\n", message);
47 sleep(1);
48 printf("%s giving up READ lock\n", message);
49 RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
50 ISC_R_SUCCESS);
51 RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
52 ISC_R_SUCCESS);
53 printf("%s got WRITE lock\n", message);
54 sleep(1);
55 printf("%s giving up WRITE lock\n", message);
56 RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
57 ISC_R_SUCCESS);
58 return ((isc_threadresult_t)0);
59 }
60
61 static isc_threadresult_t
62 #ifdef WIN32
63 WINAPI
64 #endif /* ifdef WIN32 */
run2(void * arg)65 run2(void *arg) {
66 char *message = arg;
67
68 RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
69 ISC_R_SUCCESS);
70 printf("%s got WRITE lock\n", message);
71 sleep(1);
72 printf("%s giving up WRITE lock\n", message);
73 RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
74 ISC_R_SUCCESS);
75 RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
76 ISC_R_SUCCESS);
77 printf("%s got WRITE lock\n", message);
78 sleep(1);
79 printf("%s giving up WRITE lock\n", message);
80 RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
81 ISC_R_SUCCESS);
82 RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
83 ISC_R_SUCCESS);
84 printf("%s got READ lock\n", message);
85 sleep(1);
86 printf("%s giving up READ lock\n", message);
87 RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
88 ISC_R_SUCCESS);
89 return ((isc_threadresult_t)0);
90 }
91
92 int
main(int argc,char * argv[])93 main(int argc, char *argv[]) {
94 unsigned int nworkers;
95 unsigned int i;
96 isc_thread_t workers[100];
97 char name[100];
98 void *dupname;
99
100 if (argc > 1) {
101 nworkers = atoi(argv[1]);
102 } else {
103 nworkers = 2;
104 }
105 if (nworkers > 100) {
106 nworkers = 100;
107 }
108 printf("%u workers\n", nworkers);
109
110 isc_rwlock_init(&lock, 5, 10);
111
112 for (i = 0; i < nworkers; i++) {
113 snprintf(name, sizeof(name), "%02u", i);
114 dupname = strdup(name);
115 RUNTIME_CHECK(dupname != NULL);
116 if (i != 0 && i % 3 == 0) {
117 isc_thread_create(run1, dupname, &workers[i]);
118 } else {
119 isc_thread_create(run2, dupname, &workers[i]);
120 }
121 }
122
123 for (i = 0; i < nworkers; i++) {
124 isc_thread_join(workers[i], NULL);
125 }
126
127 isc_rwlock_destroy(&lock);
128
129 return (0);
130 }
131