3c5225fe8a64741016eda7dd49dea64b89a5877a
[ghc-hetmet.git] / ghc / rts / MBlock.c
1 /* -----------------------------------------------------------------------------
2  * $Id: MBlock.c,v 1.3 1999/01/13 17:25:40 simonm Exp $
3  *
4  * MegaBlock Allocator Interface.  This file contains all the dirty
5  * architecture-dependent hackery required to get a chunk of aligned
6  * memory from the operating system.
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #define NON_POSIX_SOURCE
11
12 #include "Rts.h"
13 #include "RtsUtils.h"
14 #include "RtsFlags.h"
15 #include "MBlock.h"
16 #include "BlockAlloc.h"
17
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21
22 #ifdef HAVE_SYS_TYPES_H
23 #include <sys/types.h>
24 #endif
25
26 #ifdef HAVE_SYS_MMAN_H
27 #include <sys/mman.h>
28 #endif
29
30 #ifdef HAVE_FCNTL_H
31 #include <fcntl.h>
32 #endif
33
34 #if cygwin32_TARGET_OS
35 #include <windows.h>
36 #endif
37
38 #if freebsd2_TARGET_OS || freebsd3_TARGET_OS
39 /* Executable is loaded from      0x0
40  * Shared libraries are loaded at 0x2000000
41  * Stack is at the top of the address space.  The kernel probably owns
42  * 0x8000000 onwards, so we'll pick 0x5000000.
43  */
44 #define ASK_FOR_MEM_AT 0x50000000
45
46 #elif linux_TARGET_OS
47 /* Any ideas?
48  */
49 #define ASK_FOR_MEM_AT 0x50000000
50
51 #elif cygwin32_TARGET_OS
52 /* Any ideas?
53  */
54 #define ASK_FOR_MEM_AT 0x50000000
55
56 #elif solaris2_TARGET_OS
57 /* guess */
58 #define ASK_FOR_MEM_AT 0x50000000
59
60 #else
61 #error Dont know where to get memory from on this architecture
62 /* ToDo: memory locations on other architectures */
63 #endif
64
65 lnat mblocks_allocated = 0;
66
67 void *
68 getMBlock(void)
69 {
70   return getMBlocks(1);
71 }
72
73 void *
74 getMBlocks(nat n)
75 {
76   static caddr_t next_request = (caddr_t)ASK_FOR_MEM_AT;
77   caddr_t ret;
78   lnat size = MBLOCK_SIZE * n;
79  
80 #ifdef solaris2_TARGET_OS
81   { 
82       int fd = open("/dev/zero",O_RDONLY);
83       ret = mmap(next_request, size, PROT_READ | PROT_WRITE, 
84                  MAP_FIXED | MAP_PRIVATE, fd, 0);
85       close(fd);
86   }
87 #else
88 # ifdef _WIN32
89   {
90     /* avoid using cygwin32's mmap implementation, it's buggy and
91        it's just as easy to do what we want to do directly.
92     */
93    HANDLE hFile = (HANDLE)0xFFFFFFFF;
94    SECURITY_ATTRIBUTES sa;
95    HANDLE h;
96
97    sa.nLength = sizeof (SECURITY_ATTRIBUTES);
98    sa.bInheritHandle = TRUE;
99    sa.lpSecurityDescriptor = 0;
100
101    h = CreateFileMapping(hFile, &sa, PAGE_READWRITE, 0, size, NULL);
102    if ( h == 0 ) {
103 #  ifdef DEBUG
104       fprintf(stderr, "getMBlocks: CreateFileMapping failed with: %d\n", GetLastError());
105 #  endif
106       ret=(void*)-1;
107    } else {
108       ret = MapViewOfFileEx (h, FILE_MAP_WRITE, 0, 0, size, next_request);
109       if ( ret != next_request ) {
110 #  ifdef DEBUG
111          fprintf(stderr, "getMBlocks: MapViewOfFileEx failed with: %d\n", GetLastError());
112 #  endif
113          ret =(void*)-1;
114       }
115    }
116   }
117 # else
118   ret = mmap(next_request, size, PROT_READ | PROT_WRITE, 
119              MAP_ANON | MAP_PRIVATE, -1, 0);
120 # endif
121 #endif
122   
123   if (ret == (void *)-1) {
124     if (errno == ENOMEM) {
125       barf("getMBlock: out of memory");
126     } else {
127       barf("GetMBlock: mmap failed");
128     }
129   }
130
131   if (((W_)ret & MBLOCK_MASK) != 0) {
132     barf("GetMBlock: misaligned block returned");
133   }
134
135   IF_DEBUG(gc,fprintf(stderr,"Allocated %d megablock(s) at %x\n",n,(nat)ret));
136
137   next_request += size;
138
139   mblocks_allocated += n;
140   
141   return ret;
142 }