The Pedigree Project 0.1
user/applications/thread-test/main.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <errno.h>
21#include <list>
22#include <pthread.h>
23#include <stdio.h>
24#include <string.h>
25#include <unistd.h>
26
27#include <pedigree/log.h>
28#include <sys/time.h>
29
30#define LOOPS 1024 // 10000000
31
32// Modified from http://www.alexonlinux.com/do-you-need-mutex-to-protect-int
33// Uses mutexes or spinlocks
34
35using namespace std;
36
37list<int> the_list;
38
39// #define USE_SPINLOCK
40
41#ifdef USE_SPINLOCK
42pthread_spinlock_t spinlock;
43#else
44pthread_mutex_t mutex;
45#endif
46
47void* consumer(void* ptr) {
48 int i;
49
50 printf("Consumer TID %lu\n", (unsigned long)ptr);
51
52 while (1) {
53#ifdef USE_SPINLOCK
54 pthread_spin_lock(&spinlock);
55#else
56 pthread_mutex_lock(&mutex);
57#endif
58
59 if (the_list.empty()) {
60#ifdef USE_SPINLOCK
61 pthread_spin_unlock(&spinlock);
62#else
63 pthread_mutex_unlock(&mutex);
64#endif
65 break;
66 }
67
68 i = the_list.front();
69 the_list.pop_front();
70
71#ifdef USE_SPINLOCK
72 pthread_spin_unlock(&spinlock);
73#else
74 pthread_mutex_unlock(&mutex);
75#endif
76 }
77
78 return NULL;
79}
80
81int main() {
82 int i;
83 pthread_t thr1, thr2;
84 struct timeval tv1, tv2;
85
86#ifdef USE_SPINLOCK
87 pthread_spin_init(&spinlock, 0);
88#else
89 pthread_mutex_init(&mutex, NULL);
90#endif
91
92 // syslog used to split up debug logs.
93 pedigree_log(LOG_INFO, "TEST 0");
94
95 printf("Locking without any contention...\n");
96 pthread_mutex_t contention_mutex;
97 pthread_mutex_init(&contention_mutex, 0);
98 pthread_mutex_lock(&contention_mutex);
99 printf("Acquired\n");
100 pthread_mutex_unlock(&contention_mutex);
101 printf("Released!\n");
102
103 pedigree_log(LOG_INFO, "TEST 1");
104
105 printf("Creating a recursive lock!\n");
106 pthread_mutex_t recursive;
107 pthread_mutexattr_t attr;
108 pthread_mutexattr_init(&attr);
109 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
110 pthread_mutex_init(&recursive, &attr);
111 printf("Testing recursion...\n");
112 pthread_mutex_lock(&recursive);
113 pthread_mutex_lock(&recursive);
114 pthread_mutex_lock(&recursive);
115 printf("Locked OK, testing unlock...\n");
116 pthread_mutex_unlock(&recursive);
117 pthread_mutex_unlock(&recursive);
118 pthread_mutex_unlock(&recursive);
119 printf("Testing re-acquire...\n");
120 pthread_mutex_lock(&recursive);
121 printf("OK!\n");
122
123 pedigree_log(LOG_INFO, "TEST 2");
124 printf("Locking with deadlock\n");
125 pthread_mutex_t deadlock_mutex;
126 pthread_mutexattr_t deadlock_attr;
127 pthread_mutexattr_init(&deadlock_attr);
128 pthread_mutexattr_settype(&deadlock_attr, PTHREAD_MUTEX_ERRORCHECK);
129 pthread_mutex_init(&deadlock_mutex, &deadlock_attr);
130 pthread_mutexattr_destroy(&deadlock_attr);
131 i = pthread_mutex_lock(&deadlock_mutex);
132 printf("First lock: %d (%s)\n", i, strerror(i));
133 i = pthread_mutex_lock(&deadlock_mutex);
134 if (i != EDEADLK)
135 printf("Didn't get EDEADLK!\n");
136 printf("Second lock: %d (%s)\n", i, strerror(i));
137 pthread_mutex_unlock(&deadlock_mutex);
138 pthread_mutex_destroy(&deadlock_mutex);
139
140 // Creating the list content...
141 for (i = 0; i < LOOPS; i++)
142 the_list.push_back(i);
143
144 // Measuring time before starting the threads...
145 gettimeofday(&tv1, NULL);
146
147 pedigree_log(LOG_INFO, "TEST 3");
148 pthread_create(&thr1, NULL, consumer, (void*)1);
149 pthread_create(&thr2, NULL, consumer, (void*)2);
150
151 pthread_join(thr1, NULL);
152 pthread_join(thr2, NULL);
153 pedigree_log(LOG_INFO, "TEST 4");
154
155 // Measuring time after threads finished...
156 gettimeofday(&tv2, NULL);
157
158 if (tv1.tv_usec > tv2.tv_usec) {
159 tv2.tv_sec--;
160 tv2.tv_usec += 1000000;
161 }
162
163 printf("Result - %ld.%ld\n", tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
164
165#ifdef USE_SPINLOCK
166 pthread_spin_destroy(&spinlock);
167#else
168 pthread_mutex_destroy(&mutex);
169#endif
170
171 return 0;
172}