root/trunk/vmem_mmap.c

Revision 59, 3.8 kB (checked in by wez, 4 years ago)

Sync with the current sources from onnv-gate.

The solaris sources use a non-portable create-thread-suspended flag when
spawning the update thread; I've thrown together a pthreads portable
equivalent. This has not had any real level of testing.

These changes include a lock around the underlying brk() call; the lack of lock
in earlier revisions of this repo may be the reason that
UMEM_OPTIONS=backend=sbrk was flaky.

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