VirtualBox

Changeset 27494 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 18, 2010 5:57:25 PM (15 years ago)
Author:
vboxsync
Message:

VBoxServiceBalloon: addressed the fork() todo

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceBalloon.cpp

    r27217 r27494  
    3636#include "VBoxServiceUtils.h"
    3737
     38#ifdef RT_OS_LINUX
     39# include <sys/mman.h>
     40#endif
     41
    3842
    3943
     
    4751static RTSEMEVENTMULTI  g_MemBalloonEvent = NIL_RTSEMEVENTMULTI;
    4852
    49 /** The array holding the R3 pointers of the balloon */
     53/** The array holding the R3 pointers of the balloon. */
    5054static void **g_pavBalloon = NULL;
     55
     56/** True = madvise(MADV_DONTFORK) works, false otherwise. */
     57static bool g_fSysMadviseWorks;
     58
     59
     60/**
     61 * Check weather madvise() works.
     62 */
     63static void VBoxServiceBalloonInitMadvise(void)
     64{
     65#ifdef RT_OS_LINUX
     66    void *pv = RTMemPageAlloc(PAGE_SIZE);
     67    g_fSysMadviseWorks = madvise(pv, PAGE_SIZE, MADV_DONTFORK) == 0;
     68    RTMemPageFree(pv);
     69#endif
     70}
     71
     72
     73/**
     74 * Allocate a chunk of the balloon. Fulfil the prerequisite that we can lock this memory
     75 * and protect it against fork() in R0. See also suplibOsPageAlloc().
     76 */
     77static void* VBoxServiceBalloonAllocChunk(void)
     78{
     79    size_t cb = VMMDEV_MEMORY_BALLOON_CHUNK_SIZE;
     80    char *pu8;
     81
     82#ifdef RT_OS_LINUX
     83    if (!g_fSysMadviseWorks)
     84        cb += 2 * PAGE_SIZE;
     85
     86    pu8 = (char*)mmap(NULL, cb, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     87    if (pu8 == MAP_FAILED)
     88        return NULL;
     89
     90    if (g_fSysMadviseWorks)
     91    {
     92        /*
     93         * It is not fatal if we fail here but a forked child (e.g. the ALSA sound server)
     94         * could crash. Linux < 2.6.16 does not implement madvise(MADV_DONTFORK) but the
     95         * kernel seems to split bigger VMAs and that is all that we want -- later we set the
     96         * VM_DONTCOPY attribute in supdrvOSLockMemOne().
     97         */
     98        madvise(pu8, cb, MADV_DONTFORK);
     99    }
     100    else
     101    {
     102        /*
     103         * madvise(MADV_DONTFORK) is not available (most probably Linux 2.4). Enclose any
     104         * mmapped region by two unmapped pages to guarantee that there is exactly one VM
     105         * area struct of the very same size as the mmap area.
     106         */
     107        RTMemProtect(pu8, PAGE_SIZE, RTMEM_PROT_NONE);
     108        RTMemProtect(pu8 + cb - PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_NONE);
     109        pu8 += PAGE_SIZE;
     110    }
     111
     112#else
     113
     114    pu8 = (char*)RTMemPageAlloc(cb);
     115    if (!pu8)
     116        return pu8;
     117
     118#endif
     119
     120    memset(pu8, 0, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE);
     121    return pu8;
     122}
     123
     124
     125/**
     126 * Free an allocated chunk undoing VBoxServiceBalloonAllocChunk().
     127 */
     128static void VBoxServiceBalloonFreeChunk(void *pv)
     129{
     130    char *pu8 = (char*)pv;
     131    size_t cb = VMMDEV_MEMORY_BALLOON_CHUNK_SIZE;
     132
     133#ifdef RT_OS_LINUX
     134
     135    if (!g_fSysMadviseWorks)
     136    {
     137        cb += 2 * PAGE_SIZE;
     138        pu8 -= PAGE_SIZE;
     139        /* This is not really necessary */
     140        RTMemProtect(pu8, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
     141        RTMemProtect(pu8 + cb - PAGE_SIZE, PAGE_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
     142    }
     143    munmap(pu8, cb);
     144
     145#else
     146
     147    RTMemPageFree(pu8);
     148
     149#endif
     150}
    51151
    52152
     
    71171        for (i = g_cMemBalloonChunks; i < cNewChunks; i++)
    72172        {
    73 /** @todo r=bird: this isn't safe on linux. See suplibOsPageAlloc in
    74  *        SUPLib-linux.cpp. We should probably just fail outright here if
    75  *        linux, just in case...
    76  *        frank: To be more specific, the problem is fork(). */
    77             void *pv = RTMemPageAlloc(VMMDEV_MEMORY_BALLOON_CHUNK_SIZE);
     173            void *pv = VBoxServiceBalloonAllocChunk();
     174            if (!pv)
     175                break;
    78176            rc = VbglR3MemBalloonChange(pv, /* inflate=*/ true);
    79177            if (RT_SUCCESS(rc))
     
    83181                /*
    84182                 * Protect against access by dangling pointers (ignore errors as it may fail).
    85                  * On Solaris it corrupts the address space leaving the process unkillable. This could
    86                  * perhaps be related to what the underlying segment driver does; currently just disable it.
     183                 * On Solaris it corrupts the address space leaving the process unkillable. This
     184                 * could perhaps be related to what the underlying segment driver does; currently
     185                 * just disable it.
    87186                 */
    88187                RTMemProtect(pv, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, RTMEM_PROT_NONE);
     
    92191            else
    93192            {
    94                 RTMemPageFree(pv);
     193                VBoxServiceBalloonFreeChunk(pv);
    95194                break;
    96195            }
     
    112211                RTMemProtect(pv, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE);
    113212#endif
    114                 RTMemPageFree(g_pavBalloon[i]);
     213                VBoxServiceBalloonFreeChunk(pv);
    115214                g_pavBalloon[i] = NULL;
    116215                g_cMemBalloonChunks--;
     
    151250    int rc = RTSemEventMultiCreate(&g_MemBalloonEvent);
    152251    AssertRCReturn(rc, rc);
     252
     253    VBoxServiceBalloonInitMadvise();
    153254
    154255    g_cMemBalloonChunks = 0;
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