xref: /titanic_41/usr/src/cmd/lms/SyncLib/src/ThreadUnix.cpp (revision 617e2443dfc17fe44fd44c0675d6aad2ffc9df42)
1 /*******************************************************************************
2  * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  - Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *
10  *  - Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  *  - Neither the name of Intel Corp. nor the names of its
15  *    contributors may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *******************************************************************************/
30 
31 //////////////////////////////////////////////////////////////////////////
32 // ThreadLinux.cpp
33 //
34 // This file contains the linux implementation of the Thread class
35 ///////////////////////////////////////////////////////////////////////////
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39 #include "Thread.h"
40 #include <pthread.h>
41 #include <sys/time.h>
42 #include <cerrno>
43 #include <cstdio>
44 
45 
46 class OSThread
47 {
48 public:
49 	pthread_t _handle;
50 	pthread_cond_t _cond;
51 	pthread_mutex_t _mut;
52 	bool _running;
53 	static void *threadFunc(void * thread_p);
54 };
55 
56 
threadFunc(void * thread_p)57 void *OSThread::threadFunc(void *thread_p)
58 {
59 	if (thread_p) {
60 		Thread *t = (Thread*)thread_p;
61 		//printf("@@@@ OSThread::threadFunc (%p)\n", t->_osThread);
62 		t->run();
63 		//printf("@@@@ OSThread::threadFunc (%p) after run\n", t->_osThread);
64 		pthread_mutex_lock(&t->_osThread->_mut);
65 		t->_osThread->_running = false;
66 		//printf("@@@@ OSThread::threadFunc setting signal\n");
67 		pthread_cond_signal(&t->_osThread->_cond);
68 		pthread_mutex_unlock(&t->_osThread->_mut);
69 	}
70 	return (void *)0;
71 }
72 
Thread(CallbackFunction func_p,void * param_p)73 Thread::Thread(CallbackFunction func_p, void* param_p)
74 {
75 	_osThread = new OSThread;
76 	_osThread->_handle = 0;
77 	_osThread->_running = false;
78 	pthread_mutex_init(&_osThread->_mut, NULL);
79 	pthread_cond_init(&_osThread->_cond, NULL);
80 	_func = func_p;
81 	_param = param_p;
82 }
83 
~Thread()84 Thread::~Thread()
85 {
86 	pthread_cond_destroy(&_osThread->_cond);
87 	pthread_mutex_destroy(&_osThread->_mut);
88 	delete _osThread;
89 }
90 
currentThread()91 unsigned long Thread::currentThread()
92 {
93 	return pthread_self();
94 }
95 
wait(unsigned long msecs_p) const96 bool Thread::wait(unsigned long msecs_p) const
97 {
98 	int retcode = 0;
99 
100 	if (msecs_p != WAIT_INFINITE) {
101 		timeval now;
102 		timespec timeout, time;
103 
104 		gettimeofday(&now, NULL);
105 		time.tv_sec = msecs_p / 1000;
106 		time.tv_nsec = (msecs_p % 1000) * 1000000;
107 		timeout.tv_sec = now.tv_sec + time.tv_sec;
108 		timeout.tv_nsec = now.tv_usec + time.tv_nsec;
109 
110 		pthread_mutex_lock(&_osThread->_mut);
111 		if (_osThread->_running) {
112 			retcode = pthread_cond_timedwait(&_osThread->_cond, &_osThread->_mut, &timeout);
113 		}
114 		pthread_mutex_unlock(&_osThread->_mut);
115 
116 		if (retcode == ETIMEDOUT) {
117 			return false;
118 		} else {
119 			return true;
120 		}
121 	} else {
122 		pthread_mutex_lock(&_osThread->_mut);
123 		//printf("@@@@ Thread wait (%p), running: %d\n", _osThread, _osThread->_running);
124 		if (_osThread->_running) {
125 			pthread_cond_wait(&_osThread->_cond, &_osThread->_mut);
126 			_osThread->_running = false;
127 		}
128 		//printf("@@@@ Thread after wait\n");
129 		pthread_mutex_unlock(&_osThread->_mut);
130 		return true;
131 	}
132 }
133 
start()134 bool Thread::start()
135 {
136 	if (running() == false) {
137 		timeval now;
138 		struct timezone tz;
139 
140 		gettimeofday(&now, &tz);
141 		_startTime = now.tv_sec;
142 		_osThread->_running = true;
143 		if (pthread_create(&_osThread->_handle, NULL, OSThread::threadFunc, this) != 0) {
144 			return false;
145 		}
146 	}
147 
148 	return true;
149 }
150 
running() const151 bool Thread::running() const
152 {
153 	return (_osThread->_running);
154 }
155 
msleep(long msecs_p)156 void Thread::msleep(long msecs_p)
157 {
158 	timespec time, rem;
159 	int counter = 5; // givin it 5 tries
160 
161 	time.tv_sec = msecs_p / 1000;
162 	time.tv_nsec = (msecs_p % 1000) * 1000000;
163 	while (counter > 0) {
164 		// nanosleep might return due to a signal, in which case
165 		// rem will include the remaining time
166 		if (nanosleep(&time, &rem) == -1) {
167 			time.tv_sec = rem.tv_sec;
168 			time.tv_nsec = rem.tv_nsec;
169 			--counter;
170 		} else {
171 			break;
172 		}
173 	}
174 }
175 
run()176 void Thread::run()
177 {
178 	if (_func != NULL) {
179 		_func(_param);
180 	}
181 }
182 
elapsedTime() const183 long Thread::elapsedTime() const
184 {
185 	struct timezone tz;
186 	timeval now;
187 
188 	gettimeofday(&now, &tz);
189 	return ((now.tv_sec - _startTime)*1000);
190 }
191 
192