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
23 #include <sys/types.h>
25 #include "rawbuffer.h"
27 #include <mono/io-layer/io-layer.h>
29 #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1))
30 #define ROUND_UP(VALUE,SIZE) (ROUND_DOWN((VALUE) + (SIZE) - 1, (SIZE)))
31 #if SIZEOF_VOID_P == 8
32 #define UINTPTR_TYPE guint64
34 #define UINTPTR_TYPE guint32
37 static GHashTable *mmap_map = NULL;
38 static size_t alignment = 0;
39 static CRITICAL_SECTION mmap_mutex;
47 GetSystemInfo (&info);
48 alignment = info.dwAllocationGranularity;
50 alignment = getpagesize ();
55 mono_raw_buffer_load_malloc (int fd, int is_writable, guint32 base, size_t size)
59 ptr = g_malloc (size);
63 if (lseek (fd, base, 0) == (off_t) -1) {
73 mono_raw_buffer_free_malloc (void *base)
79 mono_raw_buffer_init (void)
81 InitializeCriticalSection (&mmap_mutex);
85 mmap_map = g_hash_table_new (NULL, NULL);
89 mono_raw_buffer_load_mmap (int fd, int is_writable, guint32 base, size_t size)
92 /* FileMapping implementation */
99 start = ROUND_DOWN (base, alignment);
103 prot = PAGE_WRITECOPY;
104 access = FILE_MAP_COPY;
107 prot = PAGE_READONLY;
108 access = FILE_MAP_READ;
111 file = (HANDLE) _get_osfhandle (fd);
112 mapping = CreateFileMapping (file, NULL, prot, 0, 0, NULL);
116 ptr = MapViewOfFile (mapping, access, 0, start, end - start);
118 CloseHandle (mapping);
122 EnterCriticalSection (&mmap_mutex);
123 g_hash_table_insert (mmap_map, ptr, GINT_TO_POINTER (mapping));
124 LeaveCriticalSection (&mmap_mutex);
126 return ((char *)ptr) + (base - start);
129 /* mmap implementation */
133 int prot = PROT_READ;
137 start = ROUND_DOWN (base, alignment);
138 end = ROUND_UP (base + size, alignment);
147 ptr = mmap (0, end - start, prot, flags, fd, start);
149 if (ptr == (void *) -1)
153 * This seems to prevent segmentation faults on Fedora Linux, no
155 * http://bugzilla.ximian.com/show_bug.cgi?id=49499
158 if (mprotect (ptr, end - start, prot | PROT_EXEC) != 0)
159 g_warning (G_GNUC_PRETTY_FUNCTION
160 ": mprotect failed: %s", g_strerror (errno));
162 EnterCriticalSection (&mmap_mutex);
163 g_hash_table_insert (mmap_map, ptr, GINT_TO_POINTER (size));
164 LeaveCriticalSection (&mmap_mutex);
166 return ((char *)ptr) + (base - start);
171 mono_raw_buffer_free_mmap (void *base)
175 EnterCriticalSection (&mmap_mutex);
176 value = GPOINTER_TO_INT (g_hash_table_lookup (mmap_map, base));
177 LeaveCriticalSection (&mmap_mutex);
180 UnmapViewOfFile (base);
181 CloseHandle ((HANDLE) value);
183 munmap (base, value);
188 mono_raw_buffer_update_mmap (void *base, size_t size)
191 FlushViewOfFile (base, size);
193 msync (base, size, MS_SYNC);
198 mono_raw_buffer_load (int fd, int is_writable, guint32 base, size_t size)
202 ptr = mono_raw_buffer_load_mmap (fd, is_writable, base, size);
204 ptr = mono_raw_buffer_load_malloc (fd, is_writable, base, size);
210 mono_raw_buffer_update (void *buffer, size_t size)
215 mmap_base = (gpointer)(ROUND_DOWN ((UINTPTR_TYPE) (buffer), alignment));
217 EnterCriticalSection (&mmap_mutex);
218 exists = g_hash_table_lookup (mmap_map, mmap_base) != NULL;
219 LeaveCriticalSection (&mmap_mutex);
221 mono_raw_buffer_update_mmap (mmap_base, size);
225 mono_raw_buffer_free (void *buffer)
230 mmap_base = (gpointer)(ROUND_DOWN ((UINTPTR_TYPE) (buffer), alignment));
232 exists = g_hash_table_lookup (mmap_map, mmap_base) != NULL;
234 mono_raw_buffer_free_mmap (mmap_base);
236 mono_raw_buffer_free_malloc (buffer);