root/branches/omniti/vmem_mmap.c

Revision 2, 3.8 kB (checked in by wez, 9 years ago)

Initial revision

  • 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 "vmem_base.h"
44
45 #define ALLOC_PROT      PROT_READ | PROT_WRITE | PROT_EXEC
46 #define FREE_PROT       PROT_NONE
47
48 #define ALLOC_FLAGS     MAP_PRIVATE | MAP_ANON
49 #define FREE_FLAGS      MAP_PRIVATE | MAP_ANON | MAP_NORESERVE
50
51 #ifdef MAP_ALIGN
52 #define CHUNKSIZE       (64*1024)       /* 64 kilobytes */
53 #else
54 static size_t CHUNKSIZE;
55 #endif
56
57 static vmem_t *mmap_heap;
58
59 static void *
60 vmem_mmap_alloc(vmem_t *src, size_t size, int vmflags)
61 {
62         void *ret;
63         int old_errno = errno;
64
65         ret = vmem_alloc(src, size, vmflags);
66 #ifndef _WIN32
67         if (ret != NULL
68                 &&
69             mmap(ret, size, ALLOC_PROT, ALLOC_FLAGS | MAP_FIXED, -1, 0) ==
70             MAP_FAILED
71                 ) {
72                 vmem_free(src, ret, size);
73                 vmem_reap();
74
75                 ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP);
76                 errno = old_errno;
77                 return (NULL);
78         }
79 #endif
80
81         errno = old_errno;
82         return (ret);
83 }
84
85 static void
86 vmem_mmap_free(vmem_t *src, void *addr, size_t size)
87 {
88         int old_errno = errno;
89 #ifdef _WIN32
90         VirtualFree(addr, size, MEM_RELEASE);
91 #else
92         (void) mmap(addr, size, FREE_PROT, FREE_FLAGS | MAP_FIXED, -1, 0);
93 #endif
94         vmem_free(src, addr, size);
95         errno = old_errno;
96 }
97
98 static void *
99 vmem_mmap_top_alloc(vmem_t *src, size_t size, int vmflags)
100 {
101         void *ret;
102         void *buf;
103         int old_errno = errno;
104
105         ret = vmem_alloc(src, size, VM_NOSLEEP);
106
107         if (ret) {
108                 errno = old_errno;
109                 return (ret);
110         }
111         /*
112          * Need to grow the heap
113          */
114 #ifdef _WIN32
115         buf = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
116 #else
117         buf = mmap(
118 #ifdef MAP_ALIGN
119                         (void *)CHUNKSIZE,
120 #else
121                         0,
122 #endif
123                         size, FREE_PROT, FREE_FLAGS
124 #ifdef MAP_ALIGN
125                         | MAP_ALIGN
126 #endif
127                         , -1, 0);
128 #endif
129
130         if (buf != MAP_FAILED) {
131                 ret = _vmem_extend_alloc(src, buf, size, size, vmflags);
132                 if (ret != NULL)
133                         return (ret);
134                 else {
135                         (void) munmap(buf, size);
136                         errno = old_errno;
137                         return (NULL);
138                 }
139         } else {
140                 /*
141                  * Growing the heap failed.  The allocation above will
142                  * already have called umem_reap().
143                  */
144                 ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP);
145
146                 errno = old_errno;
147                 return (NULL);
148         }
149 }
150
151 vmem_t *
152 vmem_mmap_arena(vmem_alloc_t **a_out, vmem_free_t **f_out)
153 {
154 #ifdef _WIN32
155         SYSTEM_INFO info;
156         size_t pagesize;
157 #else
158         size_t pagesize = _sysconf(_SC_PAGESIZE);
159 #endif
160        
161 #ifdef _WIN32
162         GetSystemInfo(&info);
163         pagesize = info.dwPageSize;
164         CHUNKSIZE = info.dwAllocationGranularity;
165 #elif !defined(MAP_ALIGN)
166         CHUNKSIZE = pagesize;
167 #endif
168        
169         if (mmap_heap == NULL) {
170                 mmap_heap = vmem_init("mmap_top",
171                         CHUNKSIZE,
172                     vmem_mmap_top_alloc, vmem_free,
173                     "mmap_heap", NULL, 0, pagesize,
174                     vmem_mmap_alloc, vmem_mmap_free);
175         }
176
177         if (a_out != NULL)
178                 *a_out = vmem_mmap_alloc;
179         if (f_out != NULL)
180                 *f_out = vmem_mmap_free;
181
182         return (mmap_heap);
183 }
Note: See TracBrowser for help on using the browser.