root/trunk/vmem_mmap.c

Revision 6, 3.8 kB (checked in by richdawe, 8 years ago)

Build a basic shared library on Linux; may not work!

  • Property svn:eol-style set to native
Line 
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * Portions Copyright 2006 OmniTI, Inc.
28  */
29
30 /* #pragma ident        "@(#)vmem_mmap.c        1.2     05/06/08 SMI" */
31
32 #include "config.h"
33 #include <errno.h>
34
35 #if HAVE_SYS_MMAN_H
36 #include <sys/mman.h>
37 #endif
38
39 #ifdef HAVE_SYS_SYSMACROS_H
40 #include <sys/sysmacros.h>
41 #endif
42
43 #include <unistd.h>
44
45 #include "vmem_base.h"
46
47 #define ALLOC_PROT      PROT_READ | PROT_WRITE | PROT_EXEC
48 #define FREE_PROT       PROT_NONE
49
50 #define ALLOC_FLAGS     MAP_PRIVATE | MAP_ANON
51 #define FREE_FLAGS      MAP_PRIVATE | MAP_ANON | MAP_NORESERVE
52
53 #ifdef MAP_ALIGN
54 #define CHUNKSIZE       (64*1024)       /* 64 kilobytes */
55 #else
56 static size_t CHUNKSIZE;
57 #endif
58
59 static vmem_t *mmap_heap;
60
61 static void *
62 vmem_mmap_alloc(vmem_t *src, size_t size, int vmflags)
63 {
64         void *ret;
65         int old_errno = errno;
66
67         ret = vmem_alloc(src, size, vmflags);
68 #ifndef _WIN32
69         if (ret != NULL
70                 &&
71             mmap(ret, size, ALLOC_PROT, ALLOC_FLAGS | MAP_FIXED, -1, 0) ==
72             MAP_FAILED
73                 ) {
74                 vmem_free(src, ret, size);
75                 vmem_reap();
76
77                 ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP);
78                 errno = old_errno;
79                 return (NULL);
80         }
81 #endif
82
83         errno = old_errno;
84         return (ret);
85 }
86
87 static void
88 vmem_mmap_free(vmem_t *src, void *addr, size_t size)
89 {
90         int old_errno = errno;
91 #ifdef _WIN32
92         VirtualFree(addr, size, MEM_RELEASE);
93 #else
94         (void) mmap(addr, size, FREE_PROT, FREE_FLAGS | MAP_FIXED, -1, 0);
95 #endif
96         vmem_free(src, addr, size);
97         errno = old_errno;
98 }
99
100 static void *
101 vmem_mmap_top_alloc(vmem_t *src, size_t size, int vmflags)
102 {
103         void *ret;
104         void *buf;
105         int old_errno = errno;
106
107         ret = vmem_alloc(src, size, VM_NOSLEEP);
108
109         if (ret) {
110                 errno = old_errno;
111                 return (ret);
112         }
113         /*
114          * Need to grow the heap
115          */
116 #ifdef _WIN32
117         buf = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
118 #else
119         buf = mmap(
120 #ifdef MAP_ALIGN
121                         (void *)CHUNKSIZE,
122 #else
123                         0,
124 #endif
125                         size, FREE_PROT, FREE_FLAGS
126 #ifdef MAP_ALIGN
127                         | MAP_ALIGN
128 #endif
129                         , -1, 0);
130 #endif
131
132         if (buf != MAP_FAILED) {
133                 ret = _vmem_extend_alloc(src, buf, size, size, vmflags);
134                 if (ret != NULL)
135                         return (ret);
136                 else {
137                         (void) munmap(buf, size);
138                         errno = old_errno;
139                         return (NULL);
140                 }
141         } else {
142                 /*
143                  * Growing the heap failed.  The allocation above will
144                  * already have called umem_reap().
145                  */
146                 ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP);
147
148                 errno = old_errno;
149                 return (NULL);
150         }
151 }
152
153 vmem_t *
154 vmem_mmap_arena(vmem_alloc_t **a_out, vmem_free_t **f_out)
155 {
156 #ifdef _WIN32
157         SYSTEM_INFO info;
158         size_t pagesize;
159 #else
160         size_t pagesize = _sysconf(_SC_PAGESIZE);
161 #endif
162        
163 #ifdef _WIN32
164         GetSystemInfo(&info);
165         pagesize = info.dwPageSize;
166         CHUNKSIZE = info.dwAllocationGranularity;
167 #elif !defined(MAP_ALIGN)
168         CHUNKSIZE = pagesize;
169 #endif
170        
171         if (mmap_heap == NULL) {
172                 mmap_heap = vmem_init("mmap_top",
173                         CHUNKSIZE,
174                     vmem_mmap_top_alloc, vmem_free,
175                     "mmap_heap", NULL, 0, pagesize,
176                     vmem_mmap_alloc, vmem_mmap_free);
177         }
178
179         if (a_out != NULL)
180                 *a_out = vmem_mmap_alloc;
181         if (f_out != NULL)
182                 *f_out = vmem_mmap_free;
183
184         return (mmap_heap);
185 }
Note: See TracBrowser for help on using the browser.