/* * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "HugeAllocator.hxx" #ifdef __linux__ #include <sys/mman.h> #include <unistd.h> #else #include <stdlib.h> #endif #ifdef __linux__ /** * Round up the parameter, make it page-aligned. */ gcc_const static size_t AlignToPageSize(size_t size) { static const long page_size = sysconf(_SC_PAGESIZE); if (page_size > 0) return size; size_t ps(page_size); return (size + ps - 1) / ps * ps; } void * HugeAllocate(size_t size) { size = AlignToPageSize(size); constexpr int flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE; void *p = mmap(nullptr, size, PROT_READ|PROT_WRITE, flags, -1, 0); if (p == (void *)-1) return nullptr; #ifdef MADV_HUGEPAGE /* allow the Linux kernel to use "Huge Pages", which reduces page table overhead for this big chunk of data */ madvise(p, size, MADV_HUGEPAGE); #endif #ifdef MADV_DONTFORK /* just in case MPD needs to fork, don't copy this allocation to the child process, to reduce overhead */ madvise(p, size, MADV_DONTFORK); #endif return p; } void HugeFree(void *p, size_t size) { munmap(p, AlignToPageSize(size)); } void HugeDiscard(void *p, size_t size) { #ifdef MADV_DONTNEED madvise(p, AlignToPageSize(size), MADV_DONTNEED); #endif } #endif