/* vim: set ts=4 sw=4 tw=99 et:
 *
 * Copyright (C) 2012 David Anderson
 *
 * This file is part of JITCraft.
 *
 * JITCraft 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 3 of the License, or (at your option)
 * any later version.
 * 
 * Foobar 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
 * JITCraft. If not, see http://www.gnu.org/licenses/.
 */
#ifndef _include_jitcraft_platform_h_
#define _include_jitcraft_platform_h_

#include "Utility.h"

namespace ke {

namespace OS {
    enum Protection {
        Prot_ReadWrite,         // rw-, for the heap
        Prot_ReadExecute,       // r-x, for code
        Prot_ReadWriteExecute   // rwx, if disabling r-x for code.
    };

    enum MapMode {
        Map_Reserve,            // don't ask for actual pages yet
        Map_Commit              // ask for pages right away
    };

    Address MapMemory(size_t amount, MapMode mode, Protection prot);
    bool CommitMemory(Address address, size_t amount, Protection prot);
    void UnmapMemory(Address address, size_t size);

    class AlignableMapping {
        Address base_;
        Address aligned_;
        size_t size_;

      public:
        AlignableMapping(Address ptr, size_t alignment, size_t size)
          : base_(ptr),
            size_(size)
        {
            aligned_ = base_;
            if (!IsAligned(aligned_, alignment))
                aligned_ = AlignedBase(aligned_, alignment) + alignment;
        }

        AlignableMapping() : base_(NULL), aligned_(NULL), size_(0)
        {
        }

        Address base() const {
            return base_;
        }
        bool isValid() const {
            return !!base_;
        }
        size_t size() const {
            return size_;
        }
        Address aligned() const {
            return aligned_;
        }
    };

    // MapAlignedMemory is guaranteed to return zeroed memory.
    AlignableMapping MapAlignedMemory(size_t amount, size_t alignment, MapMode mode);
    void UnmapAlignedMemory(Address address, size_t size);

    // The default alignment of memory returned via MapMemory().
    // :TODO: better ifdefs
#ifdef _MSC_VER
    static const size_t kPageAlignment = 64 * kKB;
#else
    static const size_t kPageAlignment = 4 * kKB;
#endif

}

}

#endif // _include_jitcraft_platform_h_
