root/juggler/tags/1.0.7/Threads/vjThreadPosix.cpp

Revision 8789, 11.3 kB (checked in by patrickh, 7 years ago)

Copyright update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
2  *
3  * VR Juggler is (C) Copyright 1998, 1999, 2000, 2001, 2002
4  *   by Iowa State University
5  *
6  * Original Authors:
7  *   Allen Bierbaum, Christopher Just,
8  *   Patrick Hartling, Kevin Meinert,
9  *   Carolina Cruz-Neira, Albert Baker
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  *
26  * -----------------------------------------------------------------
27  * File:          $RCSfile$
28  * Date modified: $Date$
29  * Version:       $Revision$
30  * -----------------------------------------------------------------
31  *
32  *************** <auto-copyright.pl END do not edit this line> ***************/
33
34
35 #include <vjConfig.h>
36
37 #include <string.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40 #include <pthread.h>
41
42 #ifdef HAVE_SYS_CAPABILITY_H
43 #   include <sys/capability.h>
44 #endif
45
46 #include <Threads/vjThread.h>
47 #include <Threads/vjThreadManager.h>
48 #include <Threads/vjThreadFunctor.h>
49
50
51 vjThreadPosix::staticWrapper vjThreadPosix::statics;
52
53 typedef struct sched_param sched_param_t;
54
55
56 // ---------------------------------------------------------------------------
57 //: Spawning constructor
58 //
59 // This will actually start a new thread that will execute the specified
60 // function.
61 // ---------------------------------------------------------------------------
62 vjThreadPosix::vjThreadPosix (vj_thread_func_t func, void* arg, long flags,
63                               u_int priority, void* stack_addr,
64                               size_t stack_size)
65 {
66    mUserThreadFunctor = NULL;
67    vjThreadManager* vj_tm_inst;
68
69    mScope = VJ_THREAD_SCOPE;
70    vj_tm_inst = vjThreadManager::instance();
71
72    // Create the thread functor to start
73    mUserThreadFunctor = new vjThreadNonMemberFunctor(func, arg);
74    vjThreadMemberFunctor<vjThreadPosix>* start_functor
75                = new vjThreadMemberFunctor<vjThreadPosix>(this,&vjThreadPosix::startThread,NULL);
76
77    // START THREAD
78    // NOTE: Automagically registers thread UNLESS failure
79    int ret_val = spawn(start_functor, flags, priority, stack_addr,
80                         stack_size);
81
82    if(ret_val)
83    {
84       vj_tm_inst->lock();  // Need to lock thread manager before I register the thread with them
85       {
86          registerThread(false);
87       }
88       vj_tm_inst->unlock();
89    }
90 }
91
92 // ---------------------------------------------------------------------------
93 // Spawning constructor with arguments (functor version).
94 //
95 // This will start a new thread that will execute the specified function.
96 // ---------------------------------------------------------------------------
97 vjThreadPosix::vjThreadPosix (vjBaseThreadFunctor* functorPtr, long flags,
98                               u_int priority, void* stack_addr,
99                               size_t stack_size)  : mUserThreadFunctor(NULL)
100 {
101     vjThreadManager* vj_tm_inst;
102
103     mScope = VJ_THREAD_SCOPE;
104     vj_tm_inst = vjThreadManager::instance();
105
106     // Create the thread functor to start
107     mUserThreadFunctor = functorPtr;
108     vjThreadMemberFunctor<vjThreadPosix>* start_functor
109                   = new vjThreadMemberFunctor<vjThreadPosix>(this,&vjThreadPosix::startThread,NULL);
110
111     // Start thread
112     // NOTE: Automagically registers thread UNLESS failure
113     int ret_val = spawn(start_functor, flags, priority, stack_addr, stack_size);
114
115     if(ret_val)
116     {
117        vj_tm_inst->lock();  // Need to lock thread manager before I register the thread with them
118        {
119          registerThread(false);
120        }
121        vj_tm_inst->unlock();
122     }
123 }
124
125 // ---------------------------------------------------------------------------
126 // Destructor.
127 //
128 // PRE: None.
129 // POST: This thread is removed from the thread table and from the local
130 //       thread hash.
131 // ---------------------------------------------------------------------------
132 vjThreadPosix::~vjThreadPosix (void) {
133     int status;
134
135     delete mUserThreadFunctor;
136
137     status = 0;
138 }
139
140 // ---------------------------------------------------------------------------
141 // Create a new thread that will execute functorPtr.
142 //
143 // PRE: None.
144 // POST: A thread (with any specified attributes) is created that begins
145 //       executing func().  Depending on the scheduler, it may begin
146 //       execution immediately, or it may block for a short time before
147 //       beginning execution.
148 // ---------------------------------------------------------------------------
149 int
150 vjThreadPosix::spawn (vjBaseThreadFunctor* functorPtr, long flags,
151                       u_int priority, void* stack_addr, size_t stack_size)
152 {
153     int ret_val;
154     pthread_attr_t thread_attrs;
155
156     // Initialize thread_attrs and set the priority of the thread if it is
157     // supported.  HP-UX requires a slightly different syntax than other
158     // operating systems.
159 #ifdef _PTHREADS_DRAFT_4
160     pthread_attr_create(&thread_attrs);
161
162 #   ifdef _POSIX_THREAD_REALTIME_SCHEDULING
163         if ( priority > 0 ) {
164             pthread_attr_setprio(&thread_attrs, priority);
165         }
166 #   endif   /* _POSIX_THREAD_REALTIME_SCHEDULING */
167
168 #else /* ! _PTHREADS_DRAFT_4 */
169     sched_param_t prio_param;
170
171     pthread_attr_init(&thread_attrs);
172
173     // If this pthreads implementation supports it and an alternate address
174     // is specified, set the stack address for the thread.
175 # ifdef _POSIX_THREAD_ATTR_STACKADDR
176         if ( stack_addr != NULL && stack_addr > 0 ) {
177 #ifdef HAVE_PTHREAD_ATTR_SETSTACK
178             pthread_attr_setstack(&thread_attrs, stack_addr, stack_size);
179 #else
180             pthread_attr_setstackaddr(&thread_attrs, stack_addr);
181 #endif
182         }
183 #   endif   /* _POSIX_THREAD_ATTR_STACKADDR */
184
185     // If thread priority scheduling is available, set the thread's priority
186     // if it is set to be higher than 0.
187 # ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
188 #   if defined(HAVE_SYS_CAPABILITY_H) &&        \
189        ! defined(VJ_OS_FreeBSD) && ! defined(VJ_OS_Linux)
190         cap_t capabilities = cap_get_proc();
191
192         // If we have the capability to do so, set the scope of the threads
193         // to system scope.
194         if ( capabilities->cap_effective & CAP_SCHED_MGT ) {
195             mScope = PTHREAD_SCOPE_SYSTEM;
196         }
197 #   endif   /* HAVE_SYS_CAPABILITY_H */
198
199         pthread_attr_setscope(&thread_attrs, mScope);
200
201         if ( priority > 0 ) {
202             prio_param.sched_priority = priority;
203             pthread_attr_setschedparam(&thread_attrs, &prio_param);
204         }
205 #   endif   /* _POSIX_THREAD_PRIORITY_SCHEDULING */
206
207 #endif   /* _PTHREADS_DRAFT_4 */
208
209     // Set the stack size if a value greater than 0 is specified and this
210     // pthreads implementation supports it.  Ensure that
211     // _POSIX_THREAD_ATTR_STACKSIZE is defined before trying to test its
212     // value.
213 #ifdef _POSIX_THREAD_ATTR_STACKSIZE
214     if ( stack_size > 0 ) {
215         // ** STACK SIZE CHECK NEEDED **
216
217         pthread_attr_setstacksize(&thread_attrs, stack_size);
218     }
219 #endif
220
221     // Finally create the thread.
222 #ifdef _PTHREADS_DRAFT_4
223     ret_val = pthread_create(&(mThread), thread_attrs,
224                              (pthread_startroutine_t) ThreadFunctorFunction,
225                              (pthread_addr_t) functorPtr);
226 #else
227     ret_val = pthread_create(&(mThread), &thread_attrs,
228                              ThreadFunctorFunction, (void *) functorPtr);
229 #endif
230
231     // Inform the caller if the thread was not created successfully.
232     if ( ret_val != 0 ) {
233         std::cerr << "vjThreadPosix::spawn() - Cannot create thread:"
234                   << strerror(ret_val) << std::endl;
235     }
236
237     return ret_val;
238 }
239
240
241 /**
242  * Called by the spawn routine to start the user thread function
243  * PRE: Called ONLY by a new thread
244  * POST: Do any thread registration necessary
245  *       Call the user thread functor
246  *
247  * @param null_param
248  */
249 void vjThreadPosix::startThread(void* null_param)
250 {
251    // WE are a new thread... yeah!!!!
252    // TELL EVERYONE THAT WE LIVE!!!!
253    vjThreadManager::instance()->lock();      // Lock manager
254    {
255       threadIdKey().setspecific((void*)this);     // Store the pointer to me
256       registerThread(true);
257    }
258    vjThreadManager::instance()->unlock();
259
260    // --- CALL USER FUNCTOR --- //
261    (*mUserThreadFunctor)();
262 }
263
264
265 // ---------------------------------------------------------------------------
266 // Get this thread's priority.
267 //
268 // PRE: None.
269 // POST: The priority of this thread is returned in the integer pointer
270 //       variable.
271 // ---------------------------------------------------------------------------
272 int
273 vjThreadPosix::getPrio (int* prio) {
274 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
275     int policy, ret_val;
276     sched_param_t fifo_sched_param;
277
278     ret_val = pthread_getschedparam(mThread, &policy, &fifo_sched_param);
279     *prio = fifo_sched_param.sched_priority;
280
281     return ret_val;
282 #else
283     std::cerr << "vjThreadPosix::getPrio(): Not supported\n";
284
285     return -1;
286 #endif
287 }
288
289 // ---------------------------------------------------------------------------
290 // Set this thread's priority.
291 //
292 // PRE: None.
293 // POST: This thread has its priority set to the specified value.
294 // ---------------------------------------------------------------------------
295 int
296 vjThreadPosix::setPrio (int prio) {
297 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
298     sched_param_t fifo_sched_param;
299
300     fifo_sched_param.sched_priority = prio;
301
302     return pthread_setschedparam(mThread, SCHED_FIFO, &fifo_sched_param);
303 #else
304     std::cerr << "vjThreadPosix::setPrio(): Not supported\n";
305
306     return -1;
307 #endif
308 }
309
310 vjBaseThread*
311 vjThreadPosix::self (void)
312 {
313    vjASSERT((statics.mStaticsInitialized==1221) && "Trying to call vjThreadPosix::self before statics are initialized. Don't do that");
314
315    vjBaseThread* my_thread;
316    threadIdKey().getspecific((void**)&my_thread);
317
318    return my_thread;
319 }
320
321
322
323 // ===========================================================================
324 // Private methods follow.
325 // ===========================================================================
326
327 // ---------------------------------------------------------------------------
328 //: Check the status of the thread creation in order to determine if this
329 //+ thread should be registered in the thread table or not.
330 //
331 //! PRE: An attempt must have been made to create a thread using spawn().
332 //! POST: If status is 0, the thread gets registered in the thread table and
333 //+       in the local thread hash.  The count of created threads is
334 //+       incremented as well.
335 //
336 //! ARGS: status - The integer status returned by spawn().
337 // ---------------------------------------------------------------------------
338 /*
339 void
340 vjThreadPosix::checkRegister (int status) {
341     if ( status == 0 ) {
342        mThreadTable.addThread(this, hash());      // Store way to look me up
343        threadIdKey().setspecific((void*)this);     // Store the pointer to me
344        registerThread(true);
345     } else {
346         registerThread(false);   // Failed to create
347     }
348 }
349 */
Note: See TracBrowser for help on using the browser.