MBlock.c 3.07 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* -----------------------------------------------------------------------------
 * $Id: MBlock.c,v 1.2 1998/12/02 13:28:28 simonm Exp $
 *
 * MegaBlock Allocator Interface.  This file contains all the dirty
 * architecture-dependent hackery required to get a chunk of aligned
 * memory from the operating system.
 *
 * ---------------------------------------------------------------------------*/

#define NON_POSIX_SOURCE

#include "Rts.h"
#include "RtsUtils.h"
#include "RtsFlags.h"
#include "MBlock.h"
#include "BlockAlloc.h"

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif

#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif

#if cygwin32_TARGET_OS
#include <windows.h>
#endif

#if freebsd2_TARGET_OS || freebsd3_TARGET_OS
/* Executable is loaded from      0x0
 * Shared libraries are loaded at 0x2000000
 * Stack is at the top of the address space.  The kernel probably owns
 * 0x8000000 onwards, so we'll pick 0x5000000.
 */
#define ASK_FOR_MEM_AT 0x50000000

#elif linux_TARGET_OS
/* Any ideas?
 */
#define ASK_FOR_MEM_AT 0x50000000

#elif cygwin32_TARGET_OS
/* Any ideas?
 */
#define ASK_FOR_MEM_AT 0x50000000

#elif solaris2_TARGET_OS
/* guess */
#define ASK_FOR_MEM_AT 0x50000000

#else
#error Dont know where to get memory from on this architecture
/* ToDo: memory locations on other architectures */
#endif

void *
getMBlock(void)
{
  return getMBlocks(1);
}

void *
getMBlocks(nat n)
{
  static caddr_t next_request = (caddr_t)ASK_FOR_MEM_AT;
  caddr_t ret;
  lnat size = MBLOCK_SIZE * n;
 
#ifdef solaris2_TARGET_OS
  { 
      int fd = open("/dev/zero",O_RDONLY);
      ret = mmap(next_request, size, PROT_READ | PROT_WRITE, 
		 MAP_FIXED | MAP_PRIVATE, fd, 0);
      close(fd);
  }
#else
# ifdef _WIN32
  {
    /* avoid using cygwin32's mmap implementation, it's buggy and
       it's just as easy to do what we want to do directly.
    */
   HANDLE hFile = (HANDLE)0xFFFFFFFF;
   SECURITY_ATTRIBUTES sa;
   HANDLE h;

   sa.nLength = sizeof (SECURITY_ATTRIBUTES);
   sa.bInheritHandle = TRUE;
   sa.lpSecurityDescriptor = 0;

   h = CreateFileMapping(hFile, &sa, PAGE_READWRITE, 0, size, NULL);
   if ( h == 0 ) {
#  ifdef DEBUG
      fprintf(stderr, "getMBlocks: CreateFileMapping failed with: %d\n", GetLastError());
#  endif
      ret=(void*)-1;
   } else {
      ret = MapViewOfFileEx (h, FILE_MAP_WRITE, 0, 0, size, next_request);
      if ( ret != next_request ) {
#  ifdef DEBUG
         fprintf(stderr, "getMBlocks: MapViewOfFileEx failed with: %d\n", GetLastError());
#  endif
         ret =(void*)-1;
      }
   }
  }
# else
  ret = mmap(next_request, size, PROT_READ | PROT_WRITE, 
	     MAP_ANON | MAP_PRIVATE, -1, 0);
# endif
#endif
  
  if (ret == (void *)-1) {
    if (errno == ENOMEM) {
      barf("getMBlock: out of memory");
    } else {
      barf("GetMBlock: mmap failed");
    }
  }

  if (((W_)ret & MBLOCK_MASK) != 0) {
    barf("GetMBlock: misaligned block returned");
  }

  IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));

  next_request += size;

  return ret;
}