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

Revision 6928, 11.2 kB (checked in by patrickh, 7 years ago)

RedHat? 7.2 doesn't appear to define CAP_SCHED_MGT (I could have sworn 7.1
had it…). Since we default to PTHREAD_SCOPE_SYSTEM on Linux anyway,
testing the capability doesn't really buy us anything. So, to "fix" this
annoying problem, I'm #ifdef'ing it out on Linux.

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