ThreadSGI.cpp

Go to the documentation of this file.
00001 /****************** <VPR heading BEGIN do not edit this line> *****************
00002  *
00003  * VR Juggler Portable Runtime
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Patrick Hartling, Kevin Meinert, Carolina Cruz-Neira
00007  *
00008  * -----------------------------------------------------------------
00009  * File:          $RCSfile$
00010  * Date modified: $Date: 2005-06-30 12:05:26 -0500 (Thu, 30 Jun 2005) $
00011  * Version:       $Revision: 17802 $
00012  * -----------------------------------------------------------------
00013  *
00014  ****************** <VPR heading END do not edit this line> ******************/
00015 
00016 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00017  *
00018  * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
00019  *
00020  * Original Authors:
00021  *   Allen Bierbaum, Christopher Just,
00022  *   Patrick Hartling, Kevin Meinert,
00023  *   Carolina Cruz-Neira, Albert Baker
00024  *
00025  * This library is free software; you can redistribute it and/or
00026  * modify it under the terms of the GNU Library General Public
00027  * License as published by the Free Software Foundation; either
00028  * version 2 of the License, or (at your option) any later version.
00029  *
00030  * This library is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00033  * Library General Public License for more details.
00034  *
00035  * You should have received a copy of the GNU Library General Public
00036  * License along with this library; if not, write to the
00037  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00038  * Boston, MA 02111-1307, USA.
00039  *
00040  *************** <auto-copyright.pl END do not edit this line> ***************/
00041 
00042 #include <vpr/vprConfig.h>
00043 
00044 #include <iomanip>
00045 #include <sys/types.h>
00046 #include <sys/wait.h>
00047 #include <sys/prctl.h>
00048 
00049 #include <vpr/Thread/Thread.h>
00050 #include <vpr/Thread/ThreadManager.h>
00051 #include <vpr/Util/Assert.h>
00052 #include <vpr/md/SPROC/Thread/ThreadSGI.h>
00053 
00054 
00055 namespace vpr
00056 {
00057 
00058 // Non-spawning constructor.  This will not start a thread.
00059 ThreadSGI::ThreadSGI(BaseThread::VPRThreadPriority priority,
00060                      BaseThread::VPRThreadScope scope,
00061                      BaseThread::VPRThreadState state, size_t stackSize)
00062    : mUserThreadFunctor(NULL)
00063    , mDeleteFunctor(false)
00064    , mStartFunctor(NULL)
00065    , mRunning(false)
00066 {
00067 }
00068 
00073 ThreadSGI::ThreadSGI(thread_func_t func, void* arg,
00074                      BaseThread::VPRThreadPriority priority,
00075                      BaseThread::VPRThreadScope scope,
00076                      BaseThread::VPRThreadState state, size_t stackSize)
00077    : mUserThreadFunctor(NULL)
00078    , mDeleteFunctor(false)
00079    , mStartFunctor(NULL)
00080    , mRunning(false)
00081 {
00082    // Create the thread functor to start.
00083    mDeleteFunctor = true;
00084    setFunctor(new ThreadNonMemberFunctor(func, arg));
00085    start();
00086 }
00087 
00092 ThreadSGI::ThreadSGI(BaseThreadFunctor* functorPtr,
00093                      BaseThread::VPRThreadPriority priority,
00094                      BaseThread::VPRThreadScope scope,
00095                      BaseThread::VPRThreadState state, size_t stackSize)
00096    : mUserThreadFunctor(NULL)
00097    , mDeleteFunctor(false)
00098    , mStartFunctor(NULL)
00099    , mRunning(false)
00100 {
00101    setFunctor(functorPtr);
00102    start();
00103 }
00104 
00105 ThreadSGI::~ThreadSGI()
00106 {
00107    ThreadManager::instance()->lock();
00108    {
00109       unregisterThread();
00110    }
00111    ThreadManager::instance()->unlock();
00112 
00113    if ( NULL != mStartFunctor )
00114    {
00115       delete mStartFunctor;
00116       mStartFunctor = NULL;
00117    }
00118 
00119    if ( mDeleteFunctor )
00120    {
00121       delete mUserThreadFunctor;
00122       mUserThreadFunctor = NULL;
00123    }
00124 }
00125 
00126 void ThreadSGI::setFunctor(BaseThreadFunctor* functorPtr)
00127 {
00128    vprASSERT(! mRunning && "Thread already running");
00129    vprASSERT(functorPtr->isValid());
00130 
00131    mUserThreadFunctor = functorPtr;
00132 }
00133 
00134 vpr::ReturnStatus ThreadSGI::start()
00135 {
00136    vpr::ReturnStatus status;
00137 
00138    if ( mRunning )
00139    {
00140       vprASSERT(false && "Thread already running");
00141       status.setCode(vpr::ReturnStatus::Fail);
00142    }
00143    else if ( NULL == mUserThreadFunctor )
00144    {
00145       vprASSERT(false && "No functor set");
00146       status.setCode(vpr::ReturnStatus::Fail);
00147    }
00148    else
00149    {
00150       mStartFunctor =
00151          new ThreadMemberFunctor<ThreadSGI>(this, &ThreadSGI::startThread,
00152                                             NULL);
00153 
00154       // Spawn the thread.
00155       status = spawn(mStartFunctor);
00156 
00157       if ( status.success() )
00158       {
00159          mRunning = true;
00160 
00161          ThreadManager::instance()->lock();
00162          {
00163             registerThread(true);
00164          }
00165          ThreadManager::instance()->unlock();
00166       }
00167       else
00168       {
00169          ThreadManager::instance()->lock();
00170          {
00171             registerThread(false);     // Failed to create
00172          }
00173          ThreadManager::instance()->unlock();
00174       }
00175    }
00176 
00177    return status;
00178 }
00179 
00180 vpr::ReturnStatus ThreadSGI::spawn(BaseThreadFunctor* functorPtr)
00181 {
00182    vpr::ReturnStatus status;
00183    mThreadPID = sproc(thread_func_t(&vprThreadFunctorFunction),
00184                       PR_SADDR | PR_SFDS, functorPtr);
00185 
00186    if ( mThreadPID == -1 )
00187    {
00188       status.setCode(vpr::ReturnStatus::Fail);
00189    }
00190 
00191    return status;
00192 }
00193 
00197 void ThreadSGI::startThread(void* null_param)
00198 {
00199    // WE are a new thread... yeah!!!!
00200    // TELL EVERYONE THAT WE LIVE!!!!
00201    ThreadManager::instance()->lock();      // Lock manager
00202    {
00203       setLocalThreadPtr(this);               // Store the pointer to me
00204    }
00205    ThreadManager::instance()->unlock();
00206 
00207    // Tell this thread to die when its parent dies
00208    prctl(PR_SETEXITSIG, 0);
00209    prctl(PR_TERMCHILD);
00210 
00211    // --- CALL USER FUNCTOR --- //
00212    (*mUserThreadFunctor)();
00213 }
00214 
00215 
00220 int ThreadSGI::join(void** arg)
00221 {
00222     int status, retval;
00223     pid_t pid;
00224 
00225     do {
00226         pid = ::waitpid(mThreadPID, &status, 0);
00227     } while ( WIFSTOPPED(status) != 0 );
00228 
00229     if ( pid > -1 ) {
00230         vprASSERT(pid == mThreadPID);
00231 
00232         if ( WIFEXITED(status) != 0 && arg != NULL ) {
00233             **((int**) arg) = WEXITSTATUS(status);
00234         }
00235         else if ( WIFSIGNALED(status) != 0 && arg != NULL ) {
00236             **((int**) arg) = WTERMSIG(status);
00237         }
00238 
00239         retval = 0;
00240     }
00241     else {
00242         retval = -1;
00243     }
00244 
00245     return retval;
00246 }
00247 
00248 std::ostream& ThreadSGI::outStream(std::ostream& out)
00249 {
00250    out.setf(std::ios::right);
00251    out << std::setw(7) << std::setfill('0') << mThreadPID << "/";
00252    out.unsetf(std::ios::right);
00253    BaseThread::outStream(out);
00254    out << std::setfill(' ');
00255    return out;
00256 }
00257 
00258 } // End of vpr namespace

Generated on Thu Jan 4 10:52:11 2007 for VR Juggler Portable Runtime by  doxygen 1.5.1