Add to git.
[pthrlib.git] / src / test_rwlock.c
1 /* Test rwlocks.
2  * Copyright (C) 2001 Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: test_rwlock.c,v 1.3 2002/12/01 14:29:31 rich Exp $
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <assert.h>
26
27 #ifdef HAVE_FCNTL_H
28 #include <fcntl.h>
29 #endif
30
31 #include <pool.h>
32 #include <pstring.h>
33
34 #include "pthr_rwlock.h"
35
36 #define NR_WRITER_THREADS 1
37 #define NR_READER_THREADS 500
38 #define NR_INCREMENTS 1000
39
40 static int var = 0;             /* The contended variable. */
41 static rwlock lock;             /* The lock. */
42 static int nr_writer_threads = NR_WRITER_THREADS;
43 static int nr_reader_threads = NR_READER_THREADS;
44
45 static void
46 start_monitor_thread (void *data)
47 {
48   int p = 0, v;
49
50   printf ("[                                                                        ]\r[");
51
52   while (nr_writer_threads > 0 && nr_reader_threads > 0)
53     {
54       /* Get value of contended variable and draw a scale. */
55       v = 72 * var / (NR_WRITER_THREADS * NR_INCREMENTS);
56       while (v > p)
57         {
58           printf (".");
59           fflush (stdout);
60           p++;
61         }
62
63       pth_millisleep (100);
64     }
65
66   printf ("\n");
67
68   /* Check v is correct at the end. */
69   assert (var == NR_WRITER_THREADS * NR_INCREMENTS);
70   exit (0);
71 }
72
73 static void
74 start_writer_thread (void *data)
75 {
76   int i;
77
78   for (i = 0; i < NR_INCREMENTS; ++i)
79     {
80       int v;
81
82       rwlock_enter_write (lock);
83       v = var;                  /* Do a slow R/M/W. */
84       pth_millisleep (1);
85       var = v + 1;
86       rwlock_leave (lock);
87
88       pth_millisleep (1);
89     }
90
91   nr_writer_threads--;
92 }
93
94 static void
95 start_reader_thread (void *data)
96 {
97   while (nr_writer_threads > 0)
98     {
99       rwlock_enter_read (lock);
100       pth_millisleep (1);
101       rwlock_leave (lock);
102
103       pth_millisleep (1);
104     }
105
106   nr_reader_threads--;
107 }
108
109 int
110 main ()
111 {
112   pseudothread writer_pth[NR_WRITER_THREADS];
113   pseudothread reader_pth[NR_READER_THREADS];
114   pseudothread monitor_pth;
115   pool p;
116   int i;
117
118   /* Create the lock. */
119   lock = new_rwlock (global_pool);
120
121   /* Create the monitoring thread. */
122   p = new_subpool (global_pool);
123   monitor_pth = new_pseudothread (p, start_monitor_thread, 0,
124                                   "monitor");
125   pth_start (monitor_pth);
126
127   /* Create the writer threads. */
128   for (i = 0; i < NR_WRITER_THREADS; ++i)
129     {
130       p = new_subpool (global_pool);
131       writer_pth[i] = new_pseudothread (p,
132                                         start_writer_thread, 0,
133                                         psprintf (p, "writer thread %d", i));
134     }
135
136   /* Create the reader threads. */
137   for (i = 0; i < NR_READER_THREADS; ++i)
138     {
139       p = new_subpool (global_pool);
140       reader_pth[i] = new_pseudothread (p,
141                                         start_reader_thread, 0,
142                                         psprintf (p, "reader thread %d", i));
143     }
144
145   /* Start all the threads running. */
146   for (i = 0; i < NR_WRITER_THREADS; ++i)
147     pth_start (writer_pth[i]);
148   for (i = 0; i < NR_READER_THREADS; ++i)
149     pth_start (reader_pth[i]);
150
151   for (;;) reactor_invoke ();
152 }