2 * rawbuffer.c: Manages buffers that might have been mmapped or malloced
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
10 #if defined(PLATFORM_WIN32)
11 #define USE_WIN32_API 1
22 #include <sys/types.h>
24 #include "rawbuffer.h"
26 #include <mono/io-layer/io-layer.h>
28 #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
29 #define ROUND_UP(VALUE,SIZE) (ROUND_DOWN((VALUE) + (SIZE) - 1, (SIZE)))
30 #if SIZEOF_VOID_P == 8
31 #define UINTPTR_TYPE guint64
33 #define UINTPTR_TYPE guint32
36 static GHashTable
*mmap_map
= NULL
;
37 static size_t alignment
= 0;
38 static CRITICAL_SECTION mmap_mutex
;
46 GetSystemInfo (&info
);
47 alignment
= info
.dwAllocationGranularity
;
49 alignment
= getpagesize ();
54 mono_raw_buffer_load_malloc (int fd
, int is_writable
, guint32 base
, size_t size
)
58 ptr
= g_malloc (size
);
62 if (lseek (fd
, base
, 0) == (off_t
) -1) {
72 mono_raw_buffer_free_malloc (void *base
)
78 mono_raw_buffer_init (void)
80 InitializeCriticalSection (&mmap_mutex
);
84 mmap_map
= g_hash_table_new (NULL
, NULL
);
88 mono_raw_buffer_load_mmap (int fd
, int is_writable
, guint32 base
, size_t size
)
91 /* FileMapping implementation */
98 start
= ROUND_DOWN (base
, alignment
);
102 prot
= PAGE_WRITECOPY
;
103 access
= FILE_MAP_COPY
;
106 prot
= PAGE_READONLY
;
107 access
= FILE_MAP_READ
;
110 file
= (HANDLE
) _get_osfhandle (fd
);
111 mapping
= CreateFileMapping (file
, NULL
, prot
, 0, 0, NULL
);
115 ptr
= MapViewOfFile (mapping
, access
, 0, start
, end
- start
);
117 CloseHandle (mapping
);
121 EnterCriticalSection (&mmap_mutex
);
122 g_hash_table_insert (mmap_map
, ptr
, GINT_TO_POINTER (mapping
));
123 LeaveCriticalSection (&mmap_mutex
);
125 return ((char *)ptr
) + (base
- start
);
128 /* mmap implementation */
132 int prot
= PROT_READ
;
136 start
= ROUND_DOWN (base
, alignment
);
137 end
= ROUND_UP (base
+ size
, alignment
);
146 ptr
= mmap (0, end
- start
, prot
, flags
, fd
, start
);
148 if (ptr
== (void *) -1)
152 * This seems to prevent segmentation faults on Fedora Linux, no
154 * http://bugzilla.ximian.com/show_bug.cgi?id=49499
157 if (mprotect (ptr
, end
- start
, prot
| PROT_EXEC
) != 0)
158 g_warning (G_GNUC_PRETTY_FUNCTION
159 ": mprotect failed: %s", g_strerror (errno
));
161 EnterCriticalSection (&mmap_mutex
);
162 g_hash_table_insert (mmap_map
, ptr
, GINT_TO_POINTER (size
));
163 LeaveCriticalSection (&mmap_mutex
);
165 return ((char *)ptr
) + (base
- start
);
170 mono_raw_buffer_free_mmap (void *base
)
174 EnterCriticalSection (&mmap_mutex
);
175 value
= GPOINTER_TO_INT (g_hash_table_lookup (mmap_map
, base
));
176 LeaveCriticalSection (&mmap_mutex
);
179 UnmapViewOfFile (base
);
180 CloseHandle ((HANDLE
) value
);
182 munmap (base
, value
);
187 mono_raw_buffer_update_mmap (void *base
, size_t size
)
190 FlushViewOfFile (base
, size
);
192 msync (base
, size
, MS_SYNC
);
197 mono_raw_buffer_load (int fd
, int is_writable
, guint32 base
, size_t size
)
201 ptr
= mono_raw_buffer_load_mmap (fd
, is_writable
, base
, size
);
203 ptr
= mono_raw_buffer_load_malloc (fd
, is_writable
, base
, size
);
209 mono_raw_buffer_update (void *buffer
, size_t size
)
214 mmap_base
= (gpointer
)(ROUND_DOWN ((UINTPTR_TYPE
) (buffer
), alignment
));
216 EnterCriticalSection (&mmap_mutex
);
217 exists
= g_hash_table_lookup (mmap_map
, mmap_base
) != NULL
;
218 LeaveCriticalSection (&mmap_mutex
);
220 mono_raw_buffer_update_mmap (mmap_base
, size
);
224 mono_raw_buffer_free (void *buffer
)
229 mmap_base
= (gpointer
)(ROUND_DOWN ((UINTPTR_TYPE
) (buffer
), alignment
));
231 exists
= g_hash_table_lookup (mmap_map
, mmap_base
) != NULL
;
233 mono_raw_buffer_free_mmap (mmap_base
);
235 mono_raw_buffer_free_malloc (buffer
);