<commit_before>/* Copyright (c) 2011 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef RAMCLOUD_LARGEBLOCKOFMEMORY_H
#define RAMCLOUD_LARGEBLOCKOFMEMORY_H

#include <limits.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include "Common.h"

namespace RAMCloud {

/**
 * A wrapper for a large block of memory.
 * \tparam T
 *      The type of object that will be stored in this block of memory.
 */
template<typename T = void>
struct LargeBlockOfMemory {
    /**
     * Allocates anonymous backing pages for a block of memory, pins them,
     * and zeros them.
     * \param length
     *      The number of bytes of memory to allocate.
     * \throw FatalError
     *      If the memory could not be allocated.
     */
    explicit LargeBlockOfMemory(size_t length)
        : length(length)
        , block(static_cast<T*>(mmap(NULL, length, PROT_READ | PROT_WRITE,
                                     MAP_SHARED | MAP_ANONYMOUS |
                                     MAP_LOCKED | MAP_POPULATE, -1, 0)))
    {
        if (block == NULL) {
            if (length == 0)
                return;
            throw FatalError(HERE,
                             format("Could not allocate %lu bytes", length),
                             errno);
        }
        // Force the OS to populate backing pages,
        // because MAP_POPULATE doesn't seem to do the trick.
        uint64_t pageSize = sysconf(_SC_PAGESIZE);
        for (uint64_t i = 0; i < length; i += pageSize)
            reinterpret_cast<uint8_t*>(block)[i] = 0;
    }

    /**
     * Creates a file of the desired length and mmaps pages from it, pins them,
     * and zeros them. This is intended to be used with hugetlbfs to get
     * superpage-backed memory.<commit_msg>Fix mmap return value check<commit_after>/* Copyright (c) 2011 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef RAMCLOUD_LARGEBLOCKOFMEMORY_H
#define RAMCLOUD_LARGEBLOCKOFMEMORY_H

#include <limits.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
#include "Common.h"

namespace RAMCloud {

/**
 * A wrapper for a large block of memory.
 * \tparam T
 *      The type of object that will be stored in this block of memory.
 */
template<typename T = void>
struct LargeBlockOfMemory {
    /**
     * Allocates anonymous backing pages for a block of memory, pins them,
     * and zeros them.
     * \param length
     *      The number of bytes of memory to allocate.
     * \throw FatalError
     *      If the memory could not be allocated.
     */
    explicit LargeBlockOfMemory(size_t length)
        : length(length)
        , block(static_cast<T*>(mmap(NULL, length, PROT_READ | PROT_WRITE,
                                     MAP_SHARED | MAP_ANONYMOUS |
                                     MAP_LOCKED | MAP_POPULATE, -1, 0)))
    {
        if (block == MAP_FAILED) {
            if (length == 0)
                return;
            throw FatalError(HERE,
                             format("Could not allocate %lu bytes", length),
                             errno);
        }
        // Force the OS to populate backing pages,
        // because MAP_POPULATE doesn't seem to do the trick.
        uint64_t pageSize = sysconf(_SC_PAGESIZE);
        for (uint64_t i = 0; i < length; i += pageSize)
            reinterpret_cast<uint8_t*>(block)[i] = 0;
    }

    /**
     * Creates a file of the desired length and mmaps pages from it, pins them,
     * and zeros them. This is intended to be used with hugetlbfs to get
     * superpage-backed memory.
{'fraction_non_alphanumeric': 0.07588932806324111, 'fraction_numerical': 0.005533596837944664, 'mean_word_length': 2.473575840768703, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2066414', 'n_tokens_mistral': 1500, 'n_tokens_neox': 1401, 'n_words': 567}