PDMThread.cpp revision 0f240a6c7a0b78877f400eda02f2a6520de082ca
/* $Id$ */
/** @file
* PDM Thread - VM Thread Management.
*/
/*
* Copyright (C) 2007 innotek GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*
* If you received this file as part of a commercial VirtualBox
* distribution, then only the terms of your commercial VirtualBox
* license agreement apply instead of the previous paragraph.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
///@todo #define LOG_GROUP LOG_GROUP_PDM_THREAD
#include "PDMInternal.h"
#include <iprt/semaphore.h>
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/**
* Wrapper around ASMAtomicCmpXchgSize.
*/
DECLINLINE(bool) pdmR3AtomicCmpXchgState(PPDMTHREAD pThread, PDMTHREADSTATE enmNewState, PDMTHREADSTATE enmOldState)
{
bool fRc;
return fRc;
}
/**
* Does the wakeup call.
*
* @returns VBox status code. Already asserted on failure.
* @param pThread The PDM thread.
*/
{
int rc;
{
case PDMTHREADTYPE_DEVICE:
break;
case PDMTHREADTYPE_DRIVER:
break;
case PDMTHREADTYPE_INTERNAL:
break;
case PDMTHREADTYPE_EXTERNAL:
break;
default:
break;
}
return rc;
}
/**
* Allocates new thread instance.
*
* @returns VBox status code.
* @param pVM The VM handle.
* @param ppThread Where to store the pointer to the instance.
*/
{
if (RT_FAILURE(rc))
return rc;
return VINF_SUCCESS;
}
/**
* Initialize a new thread, this actually creates the thread.
*
* @returns VBox status code.
* @param pVM The VM handle.
* @param ppThread Where the thread instance data handle is.
* @param cbStack The stack size, see RTThreadCreate().
* @param enmType The thread type, see RTThreadCreate().
* @param pszName The thread name, see RTThreadCreate().
*/
static int pdmR3ThreadInit(PVM pVM, PPPDMTHREAD ppThread, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
{
/*
* Initialize the remainder of the structure.
*/
if (RT_SUCCESS(rc))
{
/*
* Create the thread and wait for it to initialize.
*/
rc = RTThreadCreate(&pThread->Thread, pdmR3ThreadMain, pThread, cbStack, enmType, RTTHREADFLAGS_WAITABLE, pszName);
if (RT_SUCCESS(rc))
{
if ( RT_SUCCESS(rc)
if (RT_SUCCESS(rc))
{
return rc;
}
/* bailout */
}
}
return rc;
}
PDMR3DECL(int) PDMR3ThreadCreateDevice(PVM pVM, PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
{
if (RT_SUCCESS(rc))
{
}
return rc;
}
/**
* Destroys a PDM thread.
*
* This will wakeup the thread, tell it to terminate, and wait for it terminate.
*
* @returns VBox status code.
* This reflects the success off destroying the thread and not the exit code
* of the thread as this is stored in *pRcThread.
* @param pThread The thread to destroy.
* @param pRcThread Where to store the thread exit code. Optional.
* @thread The emulation thread (EMT).
*/
{
/*
* Assert sanity.
*/
/*
* Advance the thread to the terminating state.
*/
int rc = VINF_SUCCESS;
{
for (;;)
{
switch (enmState)
{
case PDMTHREADSTATE_RUNNING:
continue;
break;
case PDMTHREADSTATE_SUSPENDED:
case PDMTHREADSTATE_RESUMING:
continue;
break;
break;
default:
break;
}
break;
}
}
/*
* Wait for it to terminate and the do cleanups.
*/
if (RT_SUCCESS(rc2))
{
/* make it invalid. */
/* unlink */
else
{
if (pPrev)
}
{
}
/* free it */
}
else if (RT_SUCCESS(rc))
return rc;
}
{
int rc = VINF_SUCCESS;
while (pThread)
{
{
}
}
return rc;
}
{
int rc = VINF_SUCCESS;
while (pThread)
{
{
}
}
return rc;
}
/**
* Called For VM power off.
*
* @param pVM The VM handle.
*/
{
while (pThread)
{
}
}
/**
* Initiate termination of the thread (self) because something failed in a bad way.
*
* @param pThread The PDM thread.
*/
{
for (;;)
{
switch (enmState)
{
case PDMTHREADSTATE_SUSPENDED:
case PDMTHREADSTATE_RESUMING:
case PDMTHREADSTATE_RUNNING:
continue;
break;
break;
default:
break;
}
break;
}
}
/**
* Called by the PDM thread in response to a wakeup call with
* suspending as the new state.
*
* The thread will block in side this call until the state is changed in
* PDMR3ThreadResume API.
*
* @returns VBox status code.
* On failure, terminate the thread.
* @param pThread The PDM thread.
*/
{
/*
* Assert sanity.
*/
|| enmState == PDMTHREADSTATE_INITIALIZING);
/*
* Update the state, notify the control thread (the API caller) and go to sleep.
*/
int rc = VERR_WRONG_ORDER;
{
if (RT_SUCCESS(rc))
{
if ( RT_SUCCESS(rc)
return rc;
if (RT_SUCCESS(rc))
}
}
return rc;
}
/**
* Called by the PDM thread in response to a resuming state.
*
* The purpose of this API is to tell the PDMR3ThreadResume caller that
* the the PDM thread has successfully resumed. It will also do the
* state transition from the resuming to the running state.
*
* @returns VBox status code.
* On failure, terminate the thread.
* @param pThread The PDM thread.
*/
{
/*
* Assert sanity.
*/
/*
* Update the state and tell the control thread (the guy calling the resume API).
*/
int rc = VERR_WRONG_ORDER;
{
if (RT_SUCCESS(rc))
return rc;
}
return rc;
}
/**
* The PDM thread function.
*
* @returns return from pfnThread.
*
* @param Thread The thread handle.
* @param pvUser Pointer to the PDMTHREAD structure.
*/
{
Log(("PDMThread: Initializing thread %RTthrd / %p / '%s'...\n", Thread, pThread, RTThreadGetName(Thread)));
/*
* The run loop.
*
* It handles simple thread functions which returns when they see a suspending
* request and leaves the PDMR3ThreadIAmSuspending and PDMR3ThreadIAmRunning
* parts to us.
*/
int rc;
for (;;)
{
{
case PDMTHREADTYPE_DEVICE:
break;
case PDMTHREADTYPE_DRIVER:
break;
case PDMTHREADTYPE_INTERNAL:
break;
case PDMTHREADTYPE_EXTERNAL:
break;
default:
break;
}
if (RT_FAILURE(rc))
break;
/*
* If this is a simple thread function, the state will be suspending
* or initializing now. If it isn't we're supposed to terminate.
*/
{
break;
}
if (RT_FAILURE(rc))
break;
{
break;
}
if (RT_FAILURE(rc))
break;
}
/*
* Advance the state to terminating and then on to terminated.
*/
for (;;)
{
if ( enmState == PDMTHREADSTATE_TERMINATING
break;
}
Log(("PDMThread: Terminating thread %RTthrd / %p / '%s': %Rrc\n", Thread, pThread, RTThreadGetName(Thread), rc));
return rc;
}
/**
* Initiate termination of the thread because something failed in a bad way.
*
* @param pThread The PDM thread.
*/
{
for (;;)
{
switch (enmState)
{
case PDMTHREADSTATE_SUSPENDED:
continue;
break;
case PDMTHREADSTATE_RESUMING:
continue;
break;
case PDMTHREADSTATE_RUNNING:
continue;
break;
break;
default:
break;
}
break;
}
}
/**
* Suspends the thread.
*
* This can be called the power off / suspend notifications to suspend the
* PDM thread a bit early. The thread will be automatically suspend upon
*
* The caller is responsible for serializing the control operations on the
* thread. That basically means, always do these calls from the EMT.
*
* @returns VBox status code.
* @param pThread The PDM thread.
*/
{
/*
* Assert sanity.
*/
/*
* Change the state to resuming and kick the thread.
*/
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
{
if (RT_SUCCESS(rc))
{
/*
* Wait for the thread to reach the suspended state.
*/
if ( RT_SUCCESS(rc)
if (RT_SUCCESS(rc))
return rc;
}
}
}
}
/*
* Something failed, initialize termination.
*/
return rc;
}
/**
* Suspend all running threads.
*
* This is called by PDMR3Suspend() and PDMR3PowerOff() after all the devices
* and drivers have been notified about the suspend / power off.
*
* @return VBox status code.
* @param pVM The VM handle.
*/
{
{
case PDMTHREADSTATE_RUNNING:
{
break;
}
default:
break;
}
return VINF_SUCCESS;
}
/**
* Resumes the thread.
*
* This can be called the power on / resume notifications to resume the
* PDM thread a bit early. The thread will be automatically resumed upon
*
* The caller is responsible for serializing the control operations on the
* thread. That basically means, always do these calls from the EMT.
*
* @returns VBox status code.
* @param pThread The PDM thread.
*/
{
/*
* Assert sanity.
*/
/*
* Change the state to resuming and kick the thread.
*/
if (RT_SUCCESS(rc))
{
{
if (RT_SUCCESS(rc))
{
/*
* Wait for the thread to reach the running state.
*/
if ( RT_SUCCESS(rc)
if (RT_SUCCESS(rc))
return rc;
}
}
}
/*
* Something failed, initialize termination.
*/
return rc;
}
/**
* Resumes all threads not running.
*
* This is called by PDMR3Resume() and PDMR3PowerOn() after all the devices
* and drivers have been notified about the resume / power on .
*
* @return VBox status code.
* @param pVM The VM handle.
*/
{
{
case PDMTHREADSTATE_SUSPENDED:
{
break;
}
default:
break;
}
return VINF_SUCCESS;
}