#include <sys/sleep.h>
#include <sys/signal.h>
class AIXkproc
{
public:
AIXkproc(char *processName);
virtual ~AIXkproc();
int start();
pid_t pid() const;
private:
void destroyProcess();
static void AIX_exitP();
void AIX_lockTerm();
void AIX_unlockTerm();
void AIX_notifyTerm();
void AIX_sleepDuringTerm();
void AIX_sendTermSignal();
int AIX_pidIsValid();
pid_t AIX_creatP();
int AIX_initP();
int AIX_okToContinue();
virtual void processWork() = 0;
struct ObjParm
{
AIXkproc *theObject;
} initStructure;
static void AIX_main(int flag, ObjParm *initStructPtr, int initLength);
unsigned int processDying : 1;
unsigned int wakeupKernel : 1;
unsigned int started : 1;
pid_t thePid;
int terminationLock;
int terminationEvent;
enum { MAX_AIX_PROC_NAME = 4 };
enum { INVALID_PID = -1};
char procName_[MAX_AIX_PROC_NAME+1];
};
AIXkproc::AIXkproc(char *procName)
{
thePid = (pid_t) -1;
started = 0;
terminationLock = LOCK_AVAIL;
processDying = 0;
wakeupKernel = 0;
terminationEvent = EVENT_NULL;
strncpy(procName_, procName, MAX_AIX_PROC_NAME); // Save the ...
procName_[MAX_AIX_PROC_NAME] = '\0'; // ...process name
thePid = AIX_creatP(); // Create a kernel process.
}
// ------------------------------------------------------------------
// Name: AIXkproc::start()
// Function: Start the Processor processing
// Returns: int -- 1 if started, 0 if error
// Notes: We need a separate start function (rather than starting
// in the constructor) so we can be guaranteed that all
// our subclasses' constructors have completed before we
// start the processing
// --------------------------------------------------------------------
int AIXkproc::start()
{
// ---------------------------------------------------------------
// Grab the termination lock in case someone tries to delete us
// while we are initializing
// ---------------------------------------------------------------
AIX_lockTerm();
if (!AIX_pidIsValid())
{
// Process not created properly : Your error handler goes here...
}
else if (AIX_initP() != 0) // Will kickoff AIX_main() execution
{
// failed to initialize process : Your error handler goes here...
}
else
{
started = 1;
}
AIX_unlockTerm();
return started;
}
AIXkproc::~AIXkproc()
{
AIX_lockTerm();
if (started && !processDying)
{
wakeupKernel = 1;
AIX_sendTermSignal();
AIX_sleepDuringTerm();
}
AIX_unlockTerm(); // Release the lock protecting termination .
}
/*------------------------------------------------------------------
/ Name: Process::myMain (int flag, ObjParm *initStructPtr, int initLength)
/ Function: This function is called to start the kproc working.
/ Input: int -- initialization flag
/ ObjParm * -- initialization structure
/ int -- size of initialization structure
/ ------------------------------------------------------------------*/
void AIXkproc::AIX_main(int flag,
AIXkproc::ObjParm *initStructPtr,
int initLength)
{
if ((flag != 0) || (initLength != sizeof(ObjParm)))
{
// invalid flag or struct size : Your error handler goes here...
return;
}
AIXkproc *self = initStructPtr->theObject;
self->processWork();
self->destroyProcess(); // Finished our work. Kill our process.
}
// ------------------------------------------------------------------
// Name: void AIXkproc :: destroyProcess ()
//
// Function: Waits for the right time to terminate and then exits
// Notes: Called by AIX_main() when it is time to kill
// the process. Coordinates with the AIXkproc destructor
// via the termination lock and sleep and wakeup calls. The
// flags must be set and accessed only while holding the
// lock.
// ------------------------------------------------------------------
void AIXkproc::destroyProcess()
{
int wakeup;
AIX_lockTerm();
processDying = 1;
wakeup = wakeupKernel;
AIX_unlockTerm();
if (wakeup)
AIX_notifyTerm(); // Wakeup the parent process running the destructor.
AIX_exitP();
}
pid_t AIXkproc::AIX_creatP() // Create the process. Return the process ID.
{ return creatp();}
int AIXkproc::AIX_initP() // Initialize the process. Return 0 if successful.
{
initStructure.theObject = this;
return
initp (thePid, // process id from AIX_creatP()
AIXkproc::AIX_main, // entry point for new process
&initStructure, // parms containing object
sizeof(initStructure),// size of parms
procName_); // process name
}
void AIXkproc::AIX_notifyTerm() // Send a wakeup to those who wait.
{ e_wakeup(&terminationEvent); }
void AIXkproc::AIX_sendTermSignal() // Tell thePid to terminate.
{ pidsig ( thePid, SIGTERM ); }
int AIXkproc::AIX_okToContinue() // Return 1 if okay to continue processing
{ return ((sig_chk()) != SIGTERM); }
// ------------------------------------------------------------------
// Name: void AIXkproc :: sleepDuringTerm()
// Function: The calling process goes to sleep until event completes.
// Notes: Upon entry this call must atomically release
// the terminationLock and go to sleep.
// Upon return (when woken up) must reacquire the lock.
// ------------------------------------------------------------------
void AIXkproc::AIX_sleepDuringTerm()
{ e_sleepl(&terminationLock, &terminationEvent, EVENT_SHORT); }
void AIXkproc::AIX_exitP()
{ _exit( 0 ); }
int AIXkproc::AIX_pidIsValid() // Returns 1 if process ID is valid, 0 otherwise
{ return ((thePid == INVALID_PID) ? 0 : 1); }
void AIXkproc::AIX_lockTerm() // Get termination lock
{ lockl(&terminationLock, LOCK_SHORT); }
void AIXkproc::AIX_unlockTerm() // Release termination lock
{ unlockl(&terminationLock); }
pid_t AIXkproc::pid() const
{ return thePid; }