Commit 38183310 authored by Paolo Bonzini's avatar Paolo Bonzini Committed by Michael S. Tsirkin
Browse files

memory: move preallocation code out of exec.c



So that backends can use it.

Since we need the page size for efficiency, move code to compute it
out of translate-all.c and into util/oslib-win32.c.

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarHu Tao <hutao@cn.fujitsu.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent e1c57ab8
Loading
Loading
Loading
Loading
+1 −43
Original line number Diff line number Diff line
@@ -1011,13 +1011,6 @@ static long gethugepagesize(const char *path)
    return fs.f_bsize;
}

static sigjmp_buf sigjump;

static void sigbus_handler(int signal)
{
    siglongjmp(sigjump, 1);
}

static void *file_ram_alloc(RAMBlock *block,
                            ram_addr_t memory,
                            const char *path)
@@ -1082,42 +1075,7 @@ static void *file_ram_alloc(RAMBlock *block,
    }

    if (mem_prealloc) {
        int ret, i;
        struct sigaction act, oldact;
        sigset_t set, oldset;

        memset(&act, 0, sizeof(act));
        act.sa_handler = &sigbus_handler;
        act.sa_flags = 0;

        ret = sigaction(SIGBUS, &act, &oldact);
        if (ret) {
            perror("file_ram_alloc: failed to install signal handler");
            exit(1);
        }

        /* unblock SIGBUS */
        sigemptyset(&set);
        sigaddset(&set, SIGBUS);
        pthread_sigmask(SIG_UNBLOCK, &set, &oldset);

        if (sigsetjmp(sigjump, 1)) {
            fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n");
            exit(1);
        }

        /* MAP_POPULATE silently ignores failures */
        for (i = 0; i < (memory/hpagesize); i++) {
            memset(area + (hpagesize*i), 0, 1);
        }

        ret = sigaction(SIGBUS, &oldact, NULL);
        if (ret) {
            perror("file_ram_alloc: failed to reinstall signal handler");
            exit(1);
        }

        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
        os_mem_prealloc(fd, area, memory);
    }

    block->fd = fd;
+2 −0
Original line number Diff line number Diff line
@@ -251,4 +251,6 @@ void qemu_init_auxval(char **envp);

void qemu_set_tty_echo(int fd, bool echo);

void os_mem_prealloc(int fd, char *area, size_t sz);

#endif
+2 −0
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ static inline void os_setup_post(void) {}
void os_set_line_buffering(void);
static inline void os_set_proc_name(const char *dummy) {}

size_t getpagesize(void);

#if !defined(EPROTONOSUPPORT)
# define EPROTONOSUPPORT EINVAL
#endif
+0 −7
Original line number Diff line number Diff line
@@ -295,14 +295,7 @@ void page_size_init(void)
{
    /* NOTE: we can always suppose that qemu_host_page_size >=
       TARGET_PAGE_SIZE */
#ifdef _WIN32
    SYSTEM_INFO system_info;

    GetSystemInfo(&system_info);
    qemu_real_host_page_size = system_info.dwPageSize;
#else
    qemu_real_host_page_size = getpagesize();
#endif
    if (qemu_host_page_size == 0) {
        qemu_host_page_size = qemu_real_host_page_size;
    }
+73 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ extern int daemon(int, int);
#else
#  define QEMU_VMALLOC_ALIGN getpagesize()
#endif
#define HUGETLBFS_MAGIC       0x958458f6

#include <termios.h>
#include <unistd.h>
@@ -58,9 +59,12 @@ extern int daemon(int, int);
#include "qemu/sockets.h"
#include <sys/mman.h>
#include <libgen.h>
#include <setjmp.h>
#include <sys/signal.h>

#ifdef CONFIG_LINUX
#include <sys/syscall.h>
#include <sys/vfs.h>
#endif

#ifdef __FreeBSD__
@@ -332,3 +336,72 @@ char *qemu_get_exec_dir(void)
{
    return g_strdup(exec_dir);
}

static sigjmp_buf sigjump;

static void sigbus_handler(int signal)
{
    siglongjmp(sigjump, 1);
}

static size_t fd_getpagesize(int fd)
{
#ifdef CONFIG_LINUX
    struct statfs fs;
    int ret;

    if (fd != -1) {
        do {
            ret = fstatfs(fd, &fs);
        } while (ret != 0 && errno == EINTR);

        if (ret == 0 && fs.f_type == HUGETLBFS_MAGIC) {
            return fs.f_bsize;
        }
    }
#endif

    return getpagesize();
}

void os_mem_prealloc(int fd, char *area, size_t memory)
{
    int ret, i;
    struct sigaction act, oldact;
    sigset_t set, oldset;
    size_t hpagesize = fd_getpagesize(fd);

    memset(&act, 0, sizeof(act));
    act.sa_handler = &sigbus_handler;
    act.sa_flags = 0;

    ret = sigaction(SIGBUS, &act, &oldact);
    if (ret) {
        perror("os_mem_prealloc: failed to install signal handler");
        exit(1);
    }

    /* unblock SIGBUS */
    sigemptyset(&set);
    sigaddset(&set, SIGBUS);
    pthread_sigmask(SIG_UNBLOCK, &set, &oldset);

    if (sigsetjmp(sigjump, 1)) {
        fprintf(stderr, "os_mem_prealloc: failed to preallocate pages\n");
        exit(1);
    }

    /* MAP_POPULATE silently ignores failures */
    memory = (memory + hpagesize - 1) & -hpagesize;
    for (i = 0; i < (memory/hpagesize); i++) {
        memset(area + (hpagesize*i), 0, 1);
    }

    ret = sigaction(SIGBUS, &oldact, NULL);
    if (ret) {
        perror("os_mem_prealloc: failed to reinstall signal handler");
        exit(1);
    }

    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
}
Loading