00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "threadPosixImpl.h"
00016 #include "selectThreadImpl.h"
00017
00018 #ifdef THREAD_POSIX_IMPL
00019
00020 #include "thread.h"
00021 #include "pointerTo.h"
00022 #include "config_pipeline.h"
00023 #include <sched.h>
00024
00025 pthread_key_t ThreadPosixImpl::_pt_ptr_index = 0;
00026 bool ThreadPosixImpl::_got_pt_ptr_index = false;
00027
00028
00029
00030
00031
00032
00033 ThreadPosixImpl::
00034 ~ThreadPosixImpl() {
00035 if (thread_cat->is_debug()) {
00036 thread_cat.debug()
00037 << "Deleting thread " << _parent_obj->get_name() << "\n";
00038 }
00039
00040 _mutex.acquire();
00041
00042 if (!_detached) {
00043 pthread_detach(_thread);
00044 _detached = true;
00045 }
00046
00047 _mutex.release();
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057 void ThreadPosixImpl::
00058 setup_main_thread() {
00059 _status = S_running;
00060 }
00061
00062
00063
00064
00065
00066
00067 bool ThreadPosixImpl::
00068 start(ThreadPriority priority, bool joinable) {
00069 _mutex.acquire();
00070 if (thread_cat->is_debug()) {
00071 thread_cat.debug() << "Starting " << *_parent_obj << "\n";
00072 }
00073
00074 nassertd(_status == S_new) {
00075 _mutex.release();
00076 return false;
00077 }
00078
00079 _joinable = joinable;
00080 _status = S_start_called;
00081 _detached = false;
00082
00083 if (!_got_pt_ptr_index) {
00084 init_pt_ptr_index();
00085 }
00086
00087 pthread_attr_t attr;
00088 pthread_attr_init(&attr);
00089
00090 if (!_joinable) {
00091 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00092 _detached = true;
00093 }
00094
00095 int result = pthread_attr_setstacksize(&attr, thread_stack_size);
00096 if (result != 0) {
00097 thread_cat->warning()
00098 << "Unable to set stack size.\n";
00099 }
00100
00101
00102
00103 result = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
00104 if (result != 0) {
00105 thread_cat->warning()
00106 << "Unable to set system scope.\n";
00107 }
00108
00109 struct sched_param param;
00110 int current_policy = SCHED_OTHER;
00111 result = pthread_attr_setschedpolicy(&attr, current_policy);
00112 if (result != 0) {
00113 thread_cat->warning()
00114 << "Unable to set scheduling policy.\n";
00115
00116 }
00117
00118 result = 0;
00119 switch (priority) {
00120 case TP_low:
00121 param.sched_priority = sched_get_priority_min(current_policy);
00122 result = pthread_attr_setschedparam(&attr, ¶m);
00123 break;
00124
00125 case TP_high:
00126 case TP_urgent:
00127 param.sched_priority = sched_get_priority_max(current_policy);
00128 result = pthread_attr_setschedparam(&attr, ¶m);
00129 break;
00130
00131 case TP_normal:
00132 default:
00133 break;
00134 }
00135
00136 if (result != 0) {
00137 thread_cat->warning()
00138 << "Unable to specify thread priority.\n";
00139 }
00140
00141
00142
00143 _parent_obj->ref();
00144 result = pthread_create(&_thread, &attr, &root_func, (void *)this);
00145
00146 pthread_attr_destroy(&attr);
00147
00148 if (result != 0) {
00149
00150
00151
00152 unref_delete(_parent_obj);
00153 _mutex.release();
00154 return false;
00155 }
00156
00157
00158 _mutex.release();
00159 return true;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169 void ThreadPosixImpl::
00170 join() {
00171 _mutex.acquire();
00172 if (!_detached) {
00173 _mutex.release();
00174 void *return_val;
00175 pthread_join(_thread, &return_val);
00176 _detached = true;
00177 return;
00178 }
00179 _mutex.release();
00180 }
00181
00182
00183
00184
00185
00186
00187 string ThreadPosixImpl::
00188 get_unique_id() const {
00189 ostringstream strm;
00190 strm << getpid() << "." << _thread;
00191
00192 return strm.str();
00193 }
00194
00195
00196
00197
00198
00199
00200 void *ThreadPosixImpl::
00201 root_func(void *data) {
00202 TAU_REGISTER_THREAD();
00203 {
00204
00205
00206 ThreadPosixImpl *self = (ThreadPosixImpl *)data;
00207 int result = pthread_setspecific(_pt_ptr_index, self->_parent_obj);
00208 nassertr(result == 0, NULL);
00209
00210 {
00211 self->_mutex.acquire();
00212 nassertd(self->_status == S_start_called) {
00213 self->_mutex.release();
00214 return NULL;
00215 }
00216
00217 self->_status = S_running;
00218 self->_mutex.release();
00219 }
00220
00221 self->_parent_obj->thread_main();
00222
00223 if (thread_cat->is_debug()) {
00224 thread_cat.debug()
00225 << "Terminating thread " << self->_parent_obj->get_name()
00226 << ", count = " << self->_parent_obj->get_ref_count() << "\n";
00227 }
00228
00229 {
00230 self->_mutex.acquire();
00231 nassertd(self->_status == S_running) {
00232 self->_mutex.release();
00233 return NULL;
00234 }
00235 self->_status = S_finished;
00236 self->_mutex.release();
00237 }
00238
00239
00240
00241
00242 unref_delete(self->_parent_obj);
00243 }
00244
00245 return NULL;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 void ThreadPosixImpl::
00255 init_pt_ptr_index() {
00256 nassertv(!_got_pt_ptr_index);
00257
00258 int result = pthread_key_create(&_pt_ptr_index, NULL);
00259 if (result != 0) {
00260 thread_cat->error()
00261 << "Unable to associate Thread pointers with threads.\n";
00262 return;
00263 }
00264
00265 _got_pt_ptr_index = true;
00266
00267
00268
00269 Thread *main_thread_obj = Thread::get_main_thread();
00270 result = pthread_setspecific(_pt_ptr_index, main_thread_obj);
00271 nassertv(result == 0);
00272 }
00273
00274 #endif // THREAD_POSIX_IMPL