VirtualBox

Changeset 18645 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Apr 2, 2009 3:38:31 PM (16 years ago)
Author:
vboxsync
Message:

VMSetRuntimeError[V] refactoring: fFatal -> fFlags, may return informational status codes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/VMAll.cpp

    r13832 r18645  
    3030#include <VBox/vm.h>
    3131#include <VBox/err.h>
     32#include <VBox/log.h>
    3233
    3334#include <iprt/assert.h>
    3435#include <iprt/string.h>
     36#ifndef IN_RC
     37# include <iprt/thread.h>
     38#endif
    3539
    3640
     
    184188/**
    185189 * Sets the runtime error message.
     190 *
    186191 * As opposed VMSetError(), this method is intended to inform the VM user about
    187192 * errors and error-like conditions that happen at an arbitrary point during VM
    188193 * execution (like "host memory low" or "out of host disk space").
    189194 *
    190  * The @a fFatal parameter defines whether the error is fatal or not. If it is
    191  * true, then it is expected that the caller has already paused the VM execution
    192  * before calling this method. The VM user is supposed to power off the VM
    193  * immediately after it has received the runtime error notification via the
    194  * FNVMATRUNTIMEERROR callback.
    195  *
    196  * If @a fFatal is false, then the paused state of the VM defines the kind of
    197  * the error. If the VM is paused before calling this method, it means that
    198  * the VM user may try to fix the error condition (i.e. free more host memory)
    199  * and then resume the VM execution. If the VM is not paused before calling
    200  * this method, it means that the given error is a warning about an error
    201  * condition that may happen soon but that doesn't directly affect the
    202  * VM execution by the time of the call.
    203  *
    204  * The @a pszErrorID parameter defines an unique error identificator.
    205  * It is used by the front-ends to show a proper message to the end user
    206  * containig possible actions (for example, Retry/Ignore). For this reason,
    207  * an error ID assigned once to some particular error condition should not
    208  * change in the future. The format of this parameter is "someErrorCondition".
    209  *
    210  * @param   pVM             VM handle. Must be non-NULL.
    211  * @param   fFatal          Whether it is a fatal error or not.
    212  * @param   pszErrorID      Error ID string.
     195 * @returns VBox status code. For some flags the status code needs to be
     196 *          propagated up the stack, but this may depend on where the call was
     197 *          made.
     198 *
     199 * @param   pVM             The VM handle.
     200 *
     201 * @param   fFlags          Flags indicating which actions to take.
     202 *                          See VMSETRTERR_FLAGS_* for details on each flag.
     203 *
     204 * @param   pszErrorId      Unique error identificator string. This is used by
     205 *                          the frontends and maybe other devices or drivers, so
     206 *                          once an ID has been selected it's essentially
     207 *                          unchangable. Employ camelcase when constructing the
     208 *                          string, leave out spaces.
     209 *
     210 *                          The registered runtime error callbacks should string
     211 *                          switch on this and handle the ones it knows
     212 *                          specifically and the unknown ones generically.
     213 *
    213214 * @param   pszFormat       Error message format string.
    214215 * @param   ...             Error message arguments.
    215216 *
    216  * @return  VBox status code (whether the error has been successfully set
    217  *          and delivered to callbacks or not).
    218  *
    219217 * @thread  Any
    220  * @todo    r=bird: The pausing/suspending of the VM should be done here, we'll just end
    221  *                  up duplicating code all over the place otherwise. In the case of
    222  *                  devices/drivers/etc they might not be trusted to pause/suspend the
    223  *                  vm even. Change fFatal to fFlags and define action flags and a fatal flag.
    224  *
    225  *                  Also, why a string ID and not an enum?
    226  */
    227 VMMDECL(int) VMSetRuntimeError(PVM pVM, bool fFatal, const char *pszErrorID,
    228                                const char *pszFormat, ...)
    229 {
    230     va_list args;
    231     va_start(args, pszFormat);
    232     int rc = VMSetRuntimeErrorV(pVM, fFatal, pszErrorID, pszFormat, args);
    233     va_end(args);
     218 */
     219VMMDECL(int) VMSetRuntimeError(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
     220{
     221    va_list va;
     222    va_start(va, pszFormat);
     223    int rc = VMSetRuntimeErrorV(pVM, fFlags, pszErrorId, pszFormat, va);
     224    va_end(va);
    234225    return rc;
    235226}
     
    239230 * va_list version of VMSetRuntimeError.
    240231 *
    241  * @param   pVM             VM handle. Must be non-NULL.
    242  * @param   fFatal          Whether it is a fatal error or not.
    243  * @param   pszErrorID      Error ID string.
    244  * @param   pszFormat       Error message format string.
    245  * @param   args            Error message arguments.
    246  *
    247  * @return  VBox status code (whether the error has been successfully set
    248  *          and delivered to callbacks or not).
     232 * @returns VBox status code. For some flags the status code needs to be
     233 *          propagated up the stack, but this may depend on where the call was
     234 *          made. For most actions, there is a force action flag mopping up if
     235 *          the status code can't be propagated.
     236 *
     237 * @param   pVM             The VM handle.
     238 * @param   fFlags          Flags indicating which actions to take. See
     239 *                          VMSETRTERR_FLAGS_*.
     240 * @param   pszErrorId      Error ID string.
     241 * @param   pszFormat       Error message format string.
     242 * @param   va              Error message arguments.
    249243 *
    250244 * @thread  Any
    251245 */
    252 VMMDECL(int) VMSetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID,
    253                                const char *pszFormat, va_list args)
    254 {
     246VMMDECL(int) VMSetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
     247{
     248    Log(("VMSetRuntimeErrorV: fFlags=%#x pszErrorId=%s\n", fFlags, pszErrorId));
     249
     250    /*
     251     * Relaxed parameter validation.
     252     */
     253    AssertPtr(pVM);
     254    AssertMsg(fFlags & ~(VMSETRTERR_FLAGS_NO_WAIT | VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_FATAL), ("%#x\n", fFlags));
     255    Assert(!(fFlags & VMSETRTERR_FLAGS_NO_WAIT) || !VM_IS_EMT(pVM));
     256    Assert(!(fFlags & VMSETRTERR_FLAGS_SUSPEND) || !(fFlags & VMSETRTERR_FLAGS_FATAL));
     257    AssertPtr(pszErrorId);
     258    Assert(*pszErrorId);
     259    Assert(memchr(pszErrorId, '\0', 128) != NULL);
     260    AssertPtr(pszFormat);
     261    Assert(memchr(pszFormat, '\0', 512) != NULL);
     262
    255263#ifdef IN_RING3
    256264    /*
     
    258266     */
    259267    va_list va2;
    260     va_copy(va2, args); /* Have to make a copy here or GCC will break. */
     268    va_copy(va2, va); /* Have to make a copy here or GCC will break. */
     269    int rc;
    261270    PVMREQ pReq;
    262     VMR3ReqCall(pVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3SetRuntimeErrorV, 5,
    263                 pVM, fFatal, pszErrorID, pszFormat, &va2);
     271    if (    !(fFlags & VMSETRTERR_FLAGS_NO_WAIT)
     272        ||  VM_IS_EMT(pVM))
     273    {
     274        rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_ANY, &pReq, RT_INDEFINITE_WAIT, VMREQFLAGS_VBOX_STATUS,
     275                          (PFNRT)vmR3SetRuntimeErrorV, 5, pVM, fFlags, pszErrorId, pszFormat, &va2);
     276        if (RT_SUCCESS(rc))
     277            rc = pReq->iStatus;
     278    }
     279    else
     280        rc = VMR3ReqCallU(pVM->pUVM, VMREQDEST_ANY, &pReq, 0, VMREQFLAGS_VBOX_STATUS | VMREQFLAGS_NO_WAIT,
     281                          (PFNRT)vmR3SetRuntimeErrorV, 5, pVM, fFlags, pszErrorId, pszFormat, &va2);
    264282    VMR3ReqFree(pReq);
    265283    va_end(va2);
     
    267285#else
    268286    /*
    269      * We're already on the EMT thread and can safely create a VMRUNTIMEERROR chunk.
    270      */
    271     vmSetRuntimeErrorCopy(pVM, fFatal, pszErrorID, pszFormat, args);
     287     * We're already on the EMT and can safely create a VMRUNTIMEERROR chunk.
     288     */
     289    AssertReleaseMsgFailed(("Congratulations! You will have the pleasure of debugging the RC/R0 path.\n"));
     290    vmSetRuntimeErrorCopy(pVM, fFlags, pszErrorId, pszFormat, va);
    272291
    273292# ifdef IN_RC
    274     VMMGCCallHost(pVM, VMMCALLHOST_VM_SET_RUNTIME_ERROR, 0);
    275 # elif defined(IN_RING0)
    276     VMMR0CallHost(pVM, VMMCALLHOST_VM_SET_RUNTIME_ERROR, 0);
     293    int rc = VMMGCCallHost(pVM, VMMCALLHOST_VM_SET_RUNTIME_ERROR, 0);
    277294# else
     295    int rc = VMMR0CallHost(pVM, VMMCALLHOST_VM_SET_RUNTIME_ERROR, 0);
    278296# endif
    279297#endif
    280     return VINF_SUCCESS;
     298
     299    Log(("VMSetRuntimeErrorV: returns %Rrc (pszErrorId=%s)\n", rc, pszErrorId));
     300    return rc;
    281301}
    282302
     
    285305 * Copies the error to a VMRUNTIMEERROR structure.
    286306 *
    287  * This is mainly intended for Ring-0 and GC where the error must be copied to
     307 * This is mainly intended for Ring-0 and RC where the error must be copied to
    288308 * memory accessible from ring-3. But it's just possible that we might add
    289309 * APIs for retrieving the VMRUNTIMEERROR copy later.
    290310 *
    291311 * @param   pVM             VM handle. Must be non-NULL.
    292  * @param   fFatal          Whether it is a fatal error or not.
    293  * @param   pszErrorID      Error ID string.
    294  * @param   pszFormat       Error message format string.
    295  * @param   args            Error message arguments.
     312 * @param   fFlags          The error flags.
     313 * @param   pszErrorId      Error ID string.
     314 * @param   pszFormat       Error message format string.
     315 * @param   va              Error message arguments. This is of course spoiled
     316 *                          by this call.
    296317 * @thread  EMT
    297318 */
    298 void vmSetRuntimeErrorCopy(PVM pVM, bool fFatal, const char *pszErrorID,
    299                            const char *pszFormat, va_list args)
     319void vmSetRuntimeErrorCopy(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
    300320{
    301321#if 0 /// @todo implement Ring-0 and GC VMSetError
     
    308328
    309329    /* calc reasonable start size. */
    310     size_t cchErrorID = pszErrorID ? strlen(pszErrorID) : 0;
     330    size_t cchErrorID = pszErrorId ? strlen(pszErrorId) : 0;
    311331    size_t cchFormat = strlen(pszFormat);
    312332    size_t cb = sizeof(VMRUNTIMEERROR)
     
    322342        PVMRUNTIMEERROR pErr = (PVMRUNTIMEERROR)pv;
    323343        pErr->cbAllocated = cb;
     344        pErr->fFlags = fFlags;
    324345        pErr->off = sizeof(PVMRUNTIMEERROR);
    325         pErr->offErrorID = = 0;
     346        pErr->offErrorID = 0;
    326347
    327348        if (cchErrorID)
    328349        {
    329350            pErr->offErrorID = pErr->off;
    330             memcpy((uint8_t *)pErr + pErr->off, pszErrorID, cchErrorID + 1);
     351            memcpy((uint8_t *)pErr + pErr->off, pszErrorId, cchErrorID + 1);
    331352            pErr->off += cchErrorID + 1;
    332353        }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette