LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 05-22-2004, 01:57 PM   #1
okhan
LQ Newbie
 
Registered: May 2004
Posts: 3

Rep: Reputation: 0
Question HELP: resume and suspend pthreads


Hello ppl!

How do you implement suspend/resume for pthreads? I read somewhere that you have to use a combination of mutex, condition variables and boolean predicates to implement this feature. This is required because i have to port some Windows code to linux and there is this class CPrcThread which is an abstraction for threads. So there are thread.suspend and thread.resume functions in the windows API so thats ok, but how do i do that with pthreads? I have come up with a solution of my own but it has hit a snag. This is my solution

Code:
void CPrcThread<Worker>::suspend()
{
    ifdef WIN32
    //do windows specific things here... 
    #endif

    #ifdef __linux__
     pthread_mutex_lock(&mutex);
     flag--;
     pthread_mutex_unlock(&mutex);
    #endif
}

void CPrcThread<Worker>::resume()
{ 
        #ifdef WIN32
        //do windows specific things here... 
        #endif

        #ifdef __linux__
        pthread_mutex_lock(&mutex);
        flag++;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        #endif
}

void* CPrcThread<Worker>::threadFunc(void* pParameter)
{

while(1)
{

        #ifdef WIN32
        //do windows specific things here... 
        //no member variables accessed here so its ok...
        #endif


         #ifdef __linux__
           pthread_mutex_lock(&mutex);
           while(flag <= 0)
           {
                   pthread_cond_wait(&cond, &mutex);
           }
           pthread_mutex_unlock(&mutex); 
          #endif


          //actual thread work here
 
}

}
mutex, cond, and flag are member variables of CPrcThread.
First of all, i dont know if this is the correct way to implement suspend/resume? Secondly, the bigger problem is that the threadFunc function is static for reasons i cant control. How do i then access the member variables??

Thanks in advance!

Last edited by okhan; 05-22-2004 at 06:07 PM.
 
Old 05-23-2004, 01:50 AM   #2
paulsm4
Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Hi -

I've got Richter ("Programming Applications for MS Windows") open to Chap 7 (to refresh my memory on the specifics of Win32 thread scheduling) and Stevens ("Unix Network Programming, Vol 1") open to Chap 23 (to see if there are any alternatives besides what you're already doing).

You haven't given us any specifics on exactly what the Windows code is trying to do (or why it needs to do it that way) ...

... but, frankly, it sounds like you're absolutely on the right track. The approach you're taking seems to be the right way to do it.

Good luck!
 
Old 05-23-2004, 11:11 AM   #3
okhan
LQ Newbie
 
Registered: May 2004
Posts: 3

Original Poster
Rep: Reputation: 0
thanks for the reply, paulsm4!
in the resume and suspend functions, the windows specific thing just calls the corresponding Windows API resume and suspend functions respectively. while in the threadFunc function, a function is invoked which is the member of an object pointed to by the argument pParameter. Thats all. It doesnt (or at least it shouldnt) change the way what i do for the linux version...no?
 
Old 07-30-2004, 09:32 AM   #4
cppkid
Member
 
Registered: Jul 2004
Location: Pakistan
Distribution: Ubuntu
Posts: 185

Rep: Reputation: 30
Thumbs up

I don't know that you have found the answer to you question or not, coz its too late, but i joined this forum yesterday. Anyway i have witten a few functions for posix threads, including suspend and resume and threadfunction, and are working fine. I am including the cpp and header file with this messege, you can make a (.a) file, i mean library and use these functions, directly. If you need to plz revise the Quit mechanism as it is not that good, due to short time i could not spare more time on it. The thread is created with a Dummy function maped and suspended, then you can resume the thread, and can give the your function (static function), as a parameter to resume function with the refference of class.



________________________________SysThread.h_________________________


#include<pthread.h>

#define SUSPENDED 1
#define EXITED 2
#define RESUMED 3
#define QUITTED 4

class CSysThread
{
private:
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;
int m_nSuspend;
int m_nState;
pthread_t m_ThdID;
void *m_pObjThdFn;
char (*ThreadFunction)(void *);
static char Dummy(void *arg);
static void CallBack(void *arg);
bool IsThdSuspended();

protected:
int m_nErr;

public:
static void *ThdFn(void *pObj);
int Suspend(void);
int Resume(char (*)(void*), void *);
int IsSuspended();
int GetErr();
unsigned long GetThreadID();
int Quit();
int TerminateSysThread();

// Constructer / Destructer
CSysThread();
virtual ~CSysThread();
};





__________________SysThread.cpp____________________________________

#include "SysThread.h"
#include<iostream.h>
#include<unistd.h>
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________CONSTRUCTER_________________________________________________
//_____________________________________________________________________________________________
CSysThread::CSysThread()
{
int nRet;

ThreadFunction = (char (*)(void*))Dummy;
m_pObjThdFn = NULL;
m_nState = QUITTED;
m_nSuspend = 0;
m_ThdID = 0;
m_nErr = 0;

nRet = pthread_mutex_init(&m_SuspendMutex,NULL); // Return Check
if(nRet != 0)
{
m_nErr = 1;
return;
}

nRet = pthread_cond_init(&m_ResumeCond,NULL); // Return Check
if(nRet != 0)
{
m_nErr = 1;
return;
}


nRet = pthread_create(&m_ThdID, NULL, ThdFn,this);
if(nRet != 0)
{
m_nErr = 1;
return;
}
m_nState = RESUMED;
nRet = pthread_mutex_lock(&m_SuspendMutex); // Return Check
if(nRet != 0)
{
m_nErr = 1;
return;
}

Suspend();
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________DESTRUCTER__________________________________________________
//_____________________________________________________________________________________________
CSysThread::~CSysThread()
{
if(m_ThdID == 0) return;
pthread_exit(0);
m_nState = EXITED;
}

//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_____________________________________SUSPEND_________________________________________________
//_____________________________________________________________________________________________
int CSysThread::Suspend()
{
cout<<"Suspending........\n";

if(IsThdSuspended()) return 0; // Alredy Suspended

m_nSuspend = 1;
return 1;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//______________________________________RESUME_________________________________________________
//_____________________________________________________________________________________________
int CSysThread::Resume(char (*func)(void*), void *pObj)
{
int nCondRet;

if(IsThdSuspended() == false) return -1;

m_pObjThdFn = pObj;
ThreadFunction = (char (*)(void*))func;
nCondRet = pthread_cond_signal(&m_ResumeCond);
if(nCondRet != 0) return -1;
return 1;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//______________________________________IsSuspended____________________________________________
//_____________________________________________________________________________________________

int CSysThread::IsSuspended()
{
return m_nState;
}

bool CSysThread::IsThdSuspended()
{
int nRet;

nRet = pthread_mutex_trylock(&m_SuspendMutex);
if(nRet == 0) // Thread was suspended
{
nRet = pthread_mutex_unlock(&m_SuspendMutex);
return true;
}
return false;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________________GetErr______________________________________________
//_____________________________________________________________________________________________
int CSysThread::GetErr()
{
return m_nErr;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________________GetThreadID______________________________________________
//_____________________________________________________________________________________________
unsigned long CSysThread::GetThreadID()
{
return m_ThdID;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________________TerminateSysThread__________________________________
//_____________________________________________________________________________________________
int CSysThread::TerminateSysThread()
{
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
pthread_cancel(m_ThdID);
m_nState = EXITED;
return 1;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_________________________________________Quit________________________________________________
//_____________________________________________________________________________________________
int CSysThread::Quit()
{
int nRet;

if(m_ThdID == 0) return -1;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
nRet = pthread_cancel(m_ThdID);
m_nState = EXITED;
return nRet;
}

//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_____________________________________________ThdFn___________________________________________
//_____________________________________________________________________________________________

void* CSysThread::ThdFn(void *ptr)
{
char ch;
int nSuspRet;
CSysThread *pCthd = (CSysThread*)ptr;

pthread_cleanup_push(&CallBack,pCthd);}

while(1)
{

if(pCthd->m_nSuspend==1)
{
pCthd->m_nSuspend = 0;
pCthd->m_nState = SUSPENDED;
pthread_cond_wait(&pCthd->m_ResumeCond,&pCthd->m_SuspendMutex);
}
pCthd->m_nState = RESUMED;
usleep(2000);
// check if the funtion is exited, Call the thread cancelation
ch = (*(pCthd->ThreadFunction))(pCthd->m_pObjThdFn);
if(ch < 0)
{
nSuspRet = pCthd->Suspend();
if(nSuspRet < 0)
{
pthread_exit(0);
pCthd->m_nState = EXITED;
}
}
}
}

//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_____________________________________________CallBack___________________________________________
//_____________________________________________________________________________________________

void CSysThread::CallBack(void *ptr)
{
CSysThread *pCthd = (CSysThread*)ptr;

pCthd->m_nState = QUITTED;
pCthd->m_ThdID = 0;
}
//_____________________________________________________________________________________________
//_____________________________________________________________________________________________
//_____________________________________________CallBack___________________________________________
//_____________________________________________________________________________________________
char CSysThread:ummy(void *arg)
{
sleep(1);
return 1;
}




Regards:
Tayyab
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Suspend Fails to Resume dengel Linux - Laptop and Netbook 0 11-27-2005 09:58 AM
No resume from suspend mehlkelm Debian 3 11-22-2005 11:48 AM
laptop suspend/resume zchoyt Fedora 0 10-24-2005 11:21 PM
Can't resume from ACPI S3 suspend cdhgee Fedora 3 08-18-2005 03:39 AM
ssh ->suspend and resume... alaios Linux - Networking 4 01-11-2005 12:57 AM


All times are GMT -5. The time now is 07:28 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration