Changeset 27494 in vbox for trunk/src/VBox
- Timestamp:
- Mar 18, 2010 5:57:25 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceBalloon.cpp
r27217 r27494 36 36 #include "VBoxServiceUtils.h" 37 37 38 #ifdef RT_OS_LINUX 39 # include <sys/mman.h> 40 #endif 41 38 42 39 43 … … 47 51 static RTSEMEVENTMULTI g_MemBalloonEvent = NIL_RTSEMEVENTMULTI; 48 52 49 /** The array holding the R3 pointers of the balloon */53 /** The array holding the R3 pointers of the balloon. */ 50 54 static void **g_pavBalloon = NULL; 55 56 /** True = madvise(MADV_DONTFORK) works, false otherwise. */ 57 static bool g_fSysMadviseWorks; 58 59 60 /** 61 * Check weather madvise() works. 62 */ 63 static 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 */ 77 static 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 */ 128 static 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 } 51 151 52 152 … … 71 171 for (i = g_cMemBalloonChunks; i < cNewChunks; i++) 72 172 { 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; 78 176 rc = VbglR3MemBalloonChange(pv, /* inflate=*/ true); 79 177 if (RT_SUCCESS(rc)) … … 83 181 /* 84 182 * 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. 87 186 */ 88 187 RTMemProtect(pv, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, RTMEM_PROT_NONE); … … 92 191 else 93 192 { 94 RTMemPageFree(pv);193 VBoxServiceBalloonFreeChunk(pv); 95 194 break; 96 195 } … … 112 211 RTMemProtect(pv, VMMDEV_MEMORY_BALLOON_CHUNK_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE); 113 212 #endif 114 RTMemPageFree(g_pavBalloon[i]);213 VBoxServiceBalloonFreeChunk(pv); 115 214 g_pavBalloon[i] = NULL; 116 215 g_cMemBalloonChunks--; … … 151 250 int rc = RTSemEventMultiCreate(&g_MemBalloonEvent); 152 251 AssertRCReturn(rc, rc); 252 253 VBoxServiceBalloonInitMadvise(); 153 254 154 255 g_cMemBalloonChunks = 0;
Note:
See TracChangeset
for help on using the changeset viewer.