]>
Commit | Line | Data |
---|---|---|
34dc7c2f BB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
b128c09f BB |
5 | * Common Development and Distribution License (the "License"). |
6 | * You may not use this file except in compliance with the License. | |
34dc7c2f BB |
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 | */ | |
b128c09f | 21 | |
34dc7c2f | 22 | /* |
b128c09f | 23 | * Copyright 2008 Sun Microsystems, Inc. All rights reserved. |
34dc7c2f BB |
24 | * Use is subject to license terms. |
25 | */ | |
34dc7c2f | 26 | |
b128c09f | 27 | #pragma ident "%Z%%M% %I% %E% SMI" |
34dc7c2f | 28 | |
b128c09f | 29 | #include <unistd.h> |
34dc7c2f | 30 | #include <errno.h> |
34dc7c2f | 31 | #include <sys/mman.h> |
34dc7c2f | 32 | #include <sys/sysmacros.h> |
34dc7c2f BB |
33 | #include "vmem_base.h" |
34 | ||
35 | #define ALLOC_PROT PROT_READ | PROT_WRITE | PROT_EXEC | |
36 | #define FREE_PROT PROT_NONE | |
37 | ||
38 | #define ALLOC_FLAGS MAP_PRIVATE | MAP_ANON | |
39 | #define FREE_FLAGS MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | |
40 | ||
34dc7c2f | 41 | #define CHUNKSIZE (64*1024) /* 64 kilobytes */ |
34dc7c2f BB |
42 | |
43 | static vmem_t *mmap_heap; | |
44 | ||
45 | static void * | |
46 | vmem_mmap_alloc(vmem_t *src, size_t size, int vmflags) | |
47 | { | |
48 | void *ret; | |
49 | int old_errno = errno; | |
50 | ||
51 | ret = vmem_alloc(src, size, vmflags); | |
b128c09f | 52 | if (ret != NULL && |
34dc7c2f | 53 | mmap(ret, size, ALLOC_PROT, ALLOC_FLAGS | MAP_FIXED, -1, 0) == |
b128c09f | 54 | MAP_FAILED) { |
34dc7c2f BB |
55 | vmem_free(src, ret, size); |
56 | vmem_reap(); | |
57 | ||
58 | ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP); | |
59 | errno = old_errno; | |
60 | return (NULL); | |
61 | } | |
34dc7c2f BB |
62 | |
63 | errno = old_errno; | |
64 | return (ret); | |
65 | } | |
66 | ||
67 | static void | |
68 | vmem_mmap_free(vmem_t *src, void *addr, size_t size) | |
69 | { | |
70 | int old_errno = errno; | |
34dc7c2f | 71 | (void) mmap(addr, size, FREE_PROT, FREE_FLAGS | MAP_FIXED, -1, 0); |
34dc7c2f BB |
72 | vmem_free(src, addr, size); |
73 | errno = old_errno; | |
74 | } | |
75 | ||
76 | static void * | |
77 | vmem_mmap_top_alloc(vmem_t *src, size_t size, int vmflags) | |
78 | { | |
79 | void *ret; | |
80 | void *buf; | |
81 | int old_errno = errno; | |
82 | ||
83 | ret = vmem_alloc(src, size, VM_NOSLEEP); | |
84 | ||
85 | if (ret) { | |
86 | errno = old_errno; | |
87 | return (ret); | |
88 | } | |
89 | /* | |
90 | * Need to grow the heap | |
91 | */ | |
b128c09f BB |
92 | buf = mmap((void *)CHUNKSIZE, size, FREE_PROT, FREE_FLAGS | MAP_ALIGN, |
93 | -1, 0); | |
34dc7c2f BB |
94 | |
95 | if (buf != MAP_FAILED) { | |
96 | ret = _vmem_extend_alloc(src, buf, size, size, vmflags); | |
97 | if (ret != NULL) | |
98 | return (ret); | |
99 | else { | |
100 | (void) munmap(buf, size); | |
101 | errno = old_errno; | |
102 | return (NULL); | |
103 | } | |
104 | } else { | |
105 | /* | |
106 | * Growing the heap failed. The allocation above will | |
107 | * already have called umem_reap(). | |
108 | */ | |
109 | ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP); | |
110 | ||
111 | errno = old_errno; | |
112 | return (NULL); | |
113 | } | |
114 | } | |
115 | ||
116 | vmem_t * | |
117 | vmem_mmap_arena(vmem_alloc_t **a_out, vmem_free_t **f_out) | |
118 | { | |
b128c09f BB |
119 | size_t pagesize = sysconf(_SC_PAGESIZE); |
120 | ||
34dc7c2f | 121 | if (mmap_heap == NULL) { |
b128c09f | 122 | mmap_heap = vmem_init("mmap_top", CHUNKSIZE, |
34dc7c2f BB |
123 | vmem_mmap_top_alloc, vmem_free, |
124 | "mmap_heap", NULL, 0, pagesize, | |
125 | vmem_mmap_alloc, vmem_mmap_free); | |
126 | } | |
127 | ||
128 | if (a_out != NULL) | |
129 | *a_out = vmem_mmap_alloc; | |
130 | if (f_out != NULL) | |
131 | *f_out = vmem_mmap_free; | |
132 | ||
133 | return (mmap_heap); | |
134 | } |