Add to git.
[pthrlib.git] / src / test_mutex.c
1 /* Test mutexes.
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_mutex.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_mutex.h"
35
36 #define NR_THREADS 50
37 #define NR_INCREMENTS 50
38
39 static int var = 0;             /* The contended variable. */
40 static mutex lock;              /* The lock. */
41 static int nr_threads = NR_THREADS;
42
43 static void
44 start_monitor_thread (void *data)
45 {
46   int p = 0, v;
47
48   printf ("[                                                                        ]\r[");
49
50   while (nr_threads > 0)
51     {
52       /* Get value of contended variable and draw a scale. */
53       v = 72 * var / (NR_THREADS * NR_INCREMENTS);
54       while (v > p)
55         {
56           printf (".");
57           fflush (stdout);
58           p++;
59         }
60
61       pth_millisleep (100);
62     }
63
64   printf ("\n");
65
66   /* Check v is correct at the end. */
67   assert (var == NR_THREADS * NR_INCREMENTS);
68   exit (0);
69 }
70
71 static void
72 start_thread (void *data)
73 {
74   int i;
75
76   for (i = 0; i < NR_INCREMENTS; ++i)
77     {
78       int v;
79
80       mutex_enter (lock);
81       v = var;                  /* Do a slow R/M/W. */
82       pth_millisleep (1);
83       var = v + 1;
84       mutex_leave (lock);
85
86       pth_millisleep (1);
87     }
88
89   nr_threads--;
90 }
91
92 int
93 main ()
94 {
95   pseudothread pth[NR_THREADS];
96   pseudothread monitor_pth;
97   pool p;
98   int i;
99
100   /* Create the lock. */
101   lock = new_mutex (global_pool);
102
103   /* Create the monitoring thread. */
104   p = new_subpool (global_pool);
105   monitor_pth = new_pseudothread (p, start_monitor_thread, 0,
106                                   "monitor");
107   pth_start (monitor_pth);
108
109   /* Create the threads. */
110   for (i = 0; i < NR_THREADS; ++i)
111     {
112       p = new_subpool (global_pool);
113       pth[i] = new_pseudothread (p, start_thread, 0,
114                                  psprintf (p, "thread %d", i));
115     }
116
117   /* Start all the threads running. */
118   for (i = 0; i < NR_THREADS; ++i)
119     pth_start (pth[i]);
120
121   for (;;) reactor_invoke ();
122 }