VirtualBox

Ignore:
Timestamp:
Apr 3, 2007 4:04:19 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
20136
Message:

Attempt to fix ALSA on Linux kernels <= 2.6.17: use mmap not memalign for allocating pages. Use madvise or mprotect to separater VM area structs inside the kernel. Most SUP* functions work on cPages now (not cBytes anymore). The free functions take a cPages parameter which is used for munmap on Linux.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp

    r1 r1890  
    2727#include <sys/fcntl.h>
    2828#include <sys/ioctl.h>
     29#include <sys/mman.h>
    2930#include <errno.h>
    3031#include <unistd.h>
     
    3536#include <VBox/sup.h>
    3637#include <VBox/types.h>
     38#include <VBox/log.h>
    3739#include <iprt/path.h>
    3840#include <iprt/assert.h>
     
    4951#define DEVICE_NAME     "/dev/vboxdrv"
    5052
     53#ifndef MADV_DONTFORK
     54#define MADV_DONTFORK      10
     55#endif
    5156
    5257
     
    5863/** Flags whether or not we've loaded the kernel module. */
    5964static bool     g_fLoadedModule = false;
     65/** Checks */
     66static bool     g_fSysMadviseWorks = false;
    6067
    6168
     
    125132
    126133    /*
     134     * Check if madvise works.
     135     */
     136    void *pv = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     137    if (!pv)
     138        return VERR_NO_MEMORY;
     139    g_fSysMadviseWorks = (0 == madvise(pv, PAGE_SIZE, MADV_DONTFORK));
     140    munmap(pv, PAGE_SIZE);
     141
     142    /*
    127143     * We're done.
    128144     */
     
    249265    return RTErrConvertFromErrno(rc);
    250266#else
    251     *ppvPages = memalign(PAGE_SIZE, cPages << PAGE_SHIFT);
    252     if (*ppvPages)
    253     {
     267    size_t cbMmap = (g_fSysMadviseWorks ? cPages : cPages + 2) << PAGE_SHIFT;
     268    char *pvPages = (char*)mmap(NULL, cbMmap, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     269    if (pvPages)
     270    {
     271        if (g_fSysMadviseWorks)
     272        {
     273            /*
     274             * It is not fatal if we fail here but a forked child (e.g. the ALSA sound server)
     275             * could crash. Linux < 2.6.16 does not implement madvise(MADV_DONTFORK) but the
     276             * kernel seems to split bigger VMAs and that is all that we want -- later we set the
     277             * VM_DONTCOPY attribute in supdrvOSLockMemOne().
     278             */
     279            if (madvise (pvPages, cbMmap, MADV_DONTFORK))
     280                LogRel(("SUPLib: madvise %p-%p failed\n", pvPages, cbMmap));
     281            *ppvPages = pvPages;
     282        }
     283        else
     284        {
     285            /*
     286             * madvise(MADV_DONTFORK) is not available (most probably Linux 2.4). Enclose any
     287             * mmapped region by two unmapped pages to guarantee that there is exactly one VM
     288             * area struct of the very same size as the mmap area.
     289             */
     290            mprotect(pvPages,                      PAGE_SIZE, PROT_NONE);
     291            mprotect(pvPages + cbMmap - PAGE_SIZE, PAGE_SIZE, PROT_NONE);
     292            *ppvPages = pvPages + PAGE_SIZE;
     293        }
    254294        memset(*ppvPages, 0, cPages << PAGE_SHIFT);
    255295        return VINF_SUCCESS;
     
    266306 * @param   pvPages     Pointer to pages.
    267307 */
    268 int     suplibOsPageFree(void *pvPages)
    269 {
    270     free(pvPages);
     308int     suplibOsPageFree(void *pvPages, size_t cPages)
     309{
     310    munmap(pvPages, cPages << PAGE_SHIFT);
    271311    return VINF_SUCCESS;
    272312}
    273 
    274 
    275 
    276 
    277 
Note: See TracChangeset for help on using the changeset viewer.

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