Patch title: Release 85 bulk changes
Abstract:
File: /pliant/language/memory/page.c
Key:
    Removed line
    Added line
// Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation.
//
// 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
// version 2 along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

/*
abstract
  text "These functions allow to reserve some space in the memory, then map and unmap pages in that space."
doc
  text "This way of processing is driven modern processors architecture rather than Pliant design choice.[lf]"
  text "The Linux version is ugly because I could not find a clean way for reserving memory space without committing the pages."
*/


#if defined(_LINUX_API_) || defined(_POSIX_API_)
  #if defined(_FreeBSD_) || defined(_OpenBSD_)
    #include <sys/types.h>
    #include <sys/mman.h>
    #define MAP_ANONYMOUS MAP_ANON
  #elif defined(_POSIX_API_)
    #include <sys/mman.h>
    #ifndef MAP_ANONYMOUS
      #define MAP_ANONYMOUS 0
    #endif
  #endif

  FUNCTION Address memory_page_reserve(Address wished_address,Int size) {
    Address address;
    check(size>0);
    check(size%memory_page_size==0);
    if (G.memory_base_address!=null) {
      if(wished_address==null) {
        if(G.memory_limit_address!=null && (uInt)G.memory_limit_address-(uInt)G.memory_base_address<(uInt)size)
          error_notify_fatalz(error_id_memory_starvation,"Failed to reserve memory pages !");
        address=G.memory_base_address;
        G.memory_base_address=address_translate(G.memory_base_address,size); }
    other
      address=wished_address; }
    address=mmap(address,size,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
    if(address==null)
      error_notify_fatalz(error_id_memory_starvation,"Failed to reserve memory pages !");
    return address; }


  FUNCTION Void memory_page_commit(Address address,Int size) {
    check(integer_from_address(address)%memory_page_size==0);
    check(size>0);
    check(size%memory_page_size==0);
    address=mmap(address,size,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0);
    if(address==(Address)-1)
      error_notify_fatalz(error_id_memory_starvation,"Failed to commit memory pages !");
    atomic_add(&G.memory_current_consumed,size);
    G.memory_maximum_consumed=maximum(G.memory_maximum_consumed,G.memory_current_consumed); }


  FUNCTION Void memory_page_decommit(Address address,Int size) {
    check(integer_from_address(address)%memory_page_size==0);
    check(size>0);
    check(size%memory_page_size==0);
    address=mmap(address,size,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,-1,0);
    if(address==(Address)-1)
      error_notify_fatalz(error_id_os,"Failed to decommit memory pages !");
    atomic_add(&G.memory_current_consumed,-size); }


  FUNCTION Void memory_page_release(Address address,Int size) {
    check(integer_from_address(address)%memory_page_size==0);
    check(size>0);
    check(size%memory_page_size==0);
    if(munmap(address,size))
      error_notify_fatalz(error_id_os,"Failed to release memory pages !");
    if(address_translate(address,size)==G.memory_base_address)
      G.memory_base_address=address; }

#endif


#ifdef _WIN32_API_

  FUNCTION Address memory_page_reserve(Address wished_address,Int size) {
    Address address;
    check(size>0);
    check(size%memory_page_size==0);
    if (G.memory_base_address!=null) {
      if(wished_address==null) {
        if(G.memory_limit_address!=null && (uInt)G.memory_limit_address-(uInt)G.memory_base_address<(uInt)size)
          error_notify_fatalz(error_id_starvation,"Failed to reserve memory pages !");
        address=G.memory_base_address;
        G.memory_base_address=address_translate(G.memory_base_address,size); }
    other
      address=wished_address; }
    address=VirtualAlloc(address,size,MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    if(address==null)
      error_notify_fatalz(error_id_memory_starvation,"Failed to reserve memory pages !");
    return address; }


  FUNCTION Void memory_page_commit(Address address,Int size) {
    check(integer_from_address(address)%memory_page_size==0);
    check(size>0);
    check(size%memory_page_size==0);
    if(!VirtualAlloc(address,size,MEM_COMMIT,PAGE_EXECUTE_READWRITE))
      error_notify_fatalz(error_id_memory_starvation,"Failed to commit memory pages !");
    atomic_add(&G.memory_current_consumed,size);
    G.memory_maximum_consumed=maximum(G.memory_maximum_consumed,G.memory_current_consumed); }


  FUNCTION Void memory_page_decommit(Address address,Int size) {
    check(integer_from_address(address)%memory_page_size==0);
    check(size>0);
    check(size%memory_page_size==0);
    if(!VirtualFree(address,size,MEM_DECOMMIT))
      error_notify_fatalz(error_id_os,"Failed to decommit memory pages !");
    atomic_add(&G.memory_current_consumed,-size); }


  FUNCTION Void memory_page_release(Address address,Int size) {
    check(integer_from_address(address)%memory_page_size==0);
    check(size>0);
    check(size%memory_page_size==0);
    if(!VirtualFree(address,0,MEM_RELEASE))
      error_notify_fatalz(error_id_os,"Failed to release memory pages !");
    if(address_translate(address,size)==G.memory_base_address)
      G.memory_base_address=address; }

#endif


#ifdef _OS2_API_

  FUNCTION Address memory_page_reserve(Address address,Int size) {
    check(size>0);
    check(size%memory_page_size==0);
    if(DosAllocMem(&address,size,PAG_READ|PAG_WRITE|PAG_EXECUTE))
      error_notify_fatalz(error_id_memory_starvation,"Failed to reserve memory pages !");
    return address; }


  FUNCTION Void memory_page_commit(Address address,Int size) {
    G.memory_commit_hook(size);
    check(integer_from_address(address)%memory_page_size==0);
    check(size>0);
    check(size%memory_page_size==0);
    if(DosSetMem(address,size,PAG_COMMIT|PAG_READ|PAG_WRITE|PAG_EXECUTE))
      error_notify_fatalz(error_id_memory_starvation,"Failed to commit memory pages !");
    atomic_add(&G.memory_current_consumed,size);
    G.memory_maximum_consumed=maximum(G.memory_maximum_consumed,G.memory_current_consumed); }


  FUNCTION Void memory_page_decommit(Address address,Int size) {
    check(integer_from_address(address)%memory_page_size==0);
    check(size>0);
    check(size%memory_page_size==0);
    if(DosSetMem(address,size,PAG_DECOMMIT))
      error_notify_fatalz(error_id_os,"Failed to decommit memory pages !");
    atomic_add(&G.memory_current_consumed,-size); }


  FUNCTION Void memory_page_release(Address address,Int size) {
    if(DosFreeMem(address))
      error_notify_fatalz(error_id_os,"Failed to release memory pages !"); }

#endif