📄 sprocthread.c++
字号:
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details.*///// SprocThread.c++ - C++ Thread class built on top of IRIX sproc.// ~~~~~~~~~~~~~~~#include <stdlib.h>#include <stdio.h>#include <sched.h>#include <sys/types.h>#include <sys/prctl.h>#include <sys/wait.h>#include <sys/sysmp.h>#include <signal.h>#include <unistd.h>#include <list>#include <OpenThreads/Thread>#include "SprocMutexPrivateData.h"#include "SprocThreadPrivateData.h"#include "SprocThreadPrivateActions.h"using namespace OpenThreads;extern int errno;const char *OPENTHREAD_VERSION_STRING = "Sproc Thread Model, v1.1 ("__DATE__" "__TIME__")";#ifdef DEBUG#define DPRINTF(arg) printf arg; fflush(stdout);#else#define DPRINTF(ARG)#endifstatic void sproc_dead_child_sig_handler(int sigid);//-----------------------------------------------------------------------------// Initialize the static unique ids.//int SprocThreadPrivateData::nextId = 0;//-----------------------------------------------------------------------------// Initialize thread master priority level//Thread::ThreadPriority Thread::s_masterThreadPriority = Thread::THREAD_PRIORITY_MAX;bool Thread::s_isInitialized = false;std::list<Thread *> ThreadPrivateActions::s_threadList;void ThreadPrivateActions::ThreadCancelTest() { OpenThreads::Thread *t = GetThread(getpid()); if(t != 0L) { SprocThreadPrivateData *pd = static_cast<SprocThreadPrivateData *>(t->_prvData); bool *dieflag = GetDeathFlag(t); if(*dieflag==false) return; DPRINTF(("(SPROC THREAD) Thread Cancel Test Passed for %d\n", getpid())); if(!pd->cancelFuncStack.empty()) pd->cancelFuncStack.top().routine(pd->cancelFuncStack.top().arg); t->cancelCleanup(); pd->isRunning = false; exit(1); }}bool *ThreadPrivateActions::GetDeathFlag(Thread *thread) { SprocThreadPrivateData *pd = static_cast<SprocThreadPrivateData *>(thread->_prvData); return (bool *)(&(pd->dieFlag));}Thread *ThreadPrivateActions::GetThread(pid_t thread_id) { std::list<Thread *>::iterator iter; for(iter = s_threadList.begin(); iter != s_threadList.end(); ++iter) { Thread *t = *iter; if(t->getProcessId() == thread_id) return t; } return 0L; // no thread found;};void ThreadPrivateActions::ThreadCancelHandler(int sigid) { Thread *t = GetThread(getpid()); if(t != 0L) { bool * dieflag = GetDeathFlag(t); *dieflag = true; sigset(SIGINT, SIG_DFL); unblockproc(getpid()); }}//-------------------------------------------------------------------------// standard start routine.//void ThreadPrivateActions::StartThread(void *data){ Thread *thread = static_cast<Thread *>(data); if (thread->_prvData==0) return; AddThread(thread); *((Thread **)&PRDA->usr_prda) = (Thread *)thread; SetThreadSchedulingParams(thread); SprocThreadPrivateData *pd = static_cast<SprocThreadPrivateData *>(thread->_prvData); sigset(SIGINT, ThreadCancelHandler); size_t defaultStackSize; prctl(PR_GETSTACKSIZE, &defaultStackSize); if(defaultStackSize < pd->stackSize) { prctl(PR_SETSTACKSIZE, pd->stackSize); } prctl(PR_GETSTACKSIZE, &pd->stackSize); pd->stackSizeLocked = true; pd->isRunning = true; // release the thread that created this thread. pd->threadStartedBlock.release(); thread->run(); pd->isRunning = false; RemoveThread(thread); if(pd->detached == true ) { exit(0); } return;};void ThreadPrivateActions::AddThread(Thread *thread) { s_threadList.push_front(thread); };void ThreadPrivateActions::RemoveThread(Thread *thread) { s_threadList.remove(thread);};void ThreadPrivateActions::PrintThreadSchedulingInfo(Thread *thread) { int status, my_policy, min_priority, max_priority; struct sched_param my_param; status = sched_getparam(thread->getProcessId(), &my_param); my_policy = sched_getscheduler(thread->getProcessId()); if(status != 0 || my_policy == -1) { printf("THREAD INFO (%d) : Get sched param: %s/%s\n", unsigned int(thread->getProcessId()), strerror(status), strerror(errno)); } else { printf( "THREAD INFO (%d) : Thread running at %s / Priority: %d\n", unsigned int(thread->getProcessId()), (my_policy == SCHED_FIFO ? "SCHEDULE_FIFO" : (my_policy == SCHED_RR ? "SCHEDULE_ROUND_ROBIN" : (my_policy == SCHED_TS ? "SCHEDULE_TIME_SHARE" : (my_policy == SCHED_OTHER ? "SCHEDULE_OTHER" : "UNKNOWN")))), my_param.sched_priority); max_priority = sched_get_priority_max(my_policy); min_priority = sched_get_priority_min(my_policy); printf( "THREAD INFO (%d) : Max priority: %d, Min priority: %d\n", unsigned int(thread->getProcessId()), max_priority, min_priority); }}int ThreadPrivateActions::SetThreadSchedulingParams(Thread *thread) { int status; int th_priority; int max_priority, nominal_priority, min_priority; max_priority = 0; // This is as high as we can regularly go. min_priority = 20; nominal_priority = (max_priority + min_priority)/2; switch(thread->getSchedulePriority()) { case Thread::THREAD_PRIORITY_MAX: th_priority = max_priority; break; case Thread::THREAD_PRIORITY_HIGH: th_priority = (max_priority + nominal_priority)/2; break; case Thread::THREAD_PRIORITY_NOMINAL: th_priority = nominal_priority; break; case Thread::THREAD_PRIORITY_LOW: th_priority = (min_priority + nominal_priority)/2; break; case Thread::THREAD_PRIORITY_MIN: th_priority = min_priority; break; default: th_priority = max_priority; break; } status = setpriority(PRIO_PROCESS, thread->getProcessId(), th_priority); if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0) PrintThreadSchedulingInfo(thread); return status;};void ThreadPrivateActions::PushCancelFunction(void (*routine)(void *), void *arg) { Thread *thread = GetThread(getpid()); if(thread != 0L) { SprocThreadPrivateData *pd = static_cast<SprocThreadPrivateData *>(thread->_prvData); SprocThreadPrivateData::CancelFuncStruct c; pd->cancelFuncStack.push(c); SprocThreadPrivateData::CancelFuncStruct *cft = &(pd->cancelFuncStack.top()); cft->routine = routine; cft->arg = arg; }}void ThreadPrivateActions::PopCancelFunction() { Thread *thread = GetThread(getpid()); if(thread != 0L) { SprocThreadPrivateData *pd = static_cast<SprocThreadPrivateData *>(thread->_prvData); if(!pd->cancelFuncStack.empty()) pd->cancelFuncStack.pop(); }}//----------------------------------------------------------------------------//// Description: Set the concurrency level (no-op)//// Use static public//int Thread::SetConcurrency(int concurrencyLevel) { return -1;};//----------------------------------------------------------------------------//// Description: Get the concurrency level//// Use static public//int Thread::GetConcurrency() { return -1;};//----------------------------------------------------------------------------//// Decription: Constructor//// Use: public.//Thread::Thread() { if(!s_isInitialized) Init(); SprocThreadPrivateData *pd = new SprocThreadPrivateData(); pd->stackSize = 128*1024; // Set a minimum of 128K bytes if possible. pd->stackSizeLocked = false; pd->isRunning = false; pd->isCanceled = false; pd->idSet = false; pd->cancelActive = true; pd->detached = false; pd->uniqueId = pd->nextId; pd->nextId++; pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT; pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT; _prvData = static_cast<void *>(pd);}//----------------------------------------------------------------------------//// Decription: Destructor//// Use: public.//Thread::~Thread(){ DPRINTF(("(SPROC THREAD) %s:%d, In OpenThreads::Thread destructor\n", __FILE__, __LINE__)); SprocThreadPrivateData *pd = static_cast<SprocThreadPrivateData *>(_prvData); if(pd->isRunning) { DPRINTF(("(SPROC THREAD) %s:%d, about to kill OpenThreads::Thread\n", __FILE__, __LINE__)); //------------------------------------------------------------------- // Kill the process when the thread is destroyed. // cancel(); while (pd->isRunning == true) { ::usleep(1); } } DPRINTF(("(SPROC THREAD) %s:%d, Thread destroying private data.\n", __FILE__, __LINE__)); delete pd; _prvData = 0;}//-----------------------------------------------------------------------------//// Description: Initialize Threading//// Use: public.//void Thread::Init() { if(s_isInitialized) return;#ifdef GP_DEBUG fprintf(stderr, "%s\n", OPENTHREAD_VERSION_STRING);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -