tagged release 0.6.4
[parrot.git] / config / gen / platform / darwin / memalign.c
blob71be30366365e9e1937c48d94b6fb324696a3352
1 /*
2 * $Id$
3 * Copyright (C) 2007, The Perl Foundation.
4 */
6 /*
8 =head1 NAME
10 memalign.c
12 =head1 DESCRIPTION
14 memalign related stuff
16 =head2 Functions
18 =over 4
20 =cut
24 #include <mach/vm_map.h>
25 #include <mach/mach_init.h>
29 =item C<static unsigned log2int(unsigned x)>
31 RT#48260: Not yet documented!!!
33 =cut
37 static unsigned log2int(unsigned x) {
38 return (x<2) ? 0 : log2int(x>>1)+1;
43 =item C<static unsigned roundDownPowerOf2(unsigned x)>
45 RT#48260: Not yet documented!!!
47 =cut
51 static unsigned roundDownPowerOf2(unsigned x) {
52 return (1 << log2int(x));
57 =item C<static unsigned roundUpPowerOf2(unsigned x)>
59 RT#48260: Not yet documented!!!
61 =cut
65 static unsigned roundUpPowerOf2(unsigned x)
67 static unsigned one = 1;
68 unsigned log2Int = log2int(x);
70 return ((one << log2Int) == x) ? x : (one << (log2Int + 1));
75 =item C<static unsigned roundUpToPageBoundary(unsigned x)>
77 RT#48260: Not yet documented!!!
79 =cut
83 static unsigned roundUpToPageBoundary(unsigned x)
85 unsigned roundedDown = trunc_page(x);
87 return (roundedDown == x) ? x : (roundedDown + vm_page_size);
90 typedef struct _memalign_marker_t {
91 vm_address_t start;
92 vm_size_t size; } memalign_marker_t;
96 =item C<void *
97 Parrot_memalign(size_t align, size_t size)>
99 RT#48260: Not yet documented!!!
101 =cut
105 void *
106 Parrot_memalign(size_t align, size_t size)
108 size_t effectiveAlign = align;
109 size_t padding = 0;
110 size_t amountToAllocate = 0;
112 if (effectiveAlign < sizeof (void *))
114 effectiveAlign = roundUpPowerOf2(sizeof (void *));
116 else
118 effectiveAlign = roundUpPowerOf2(effectiveAlign);
121 if (effectiveAlign < sizeof (memalign_marker_t))
123 padding = sizeof (memalign_marker_t);
125 else
127 padding = effectiveAlign;
130 amountToAllocate = roundUpToPageBoundary(size + padding);
133 vm_address_t p = (vm_address_t)NULL;
134 kern_return_t status = vm_allocate(mach_task_self(), &p,
135 amountToAllocate, 1);
137 if (status != KERN_SUCCESS)
139 return NULL;
141 else
143 vm_size_t logEffectiveAlign = log2int(effectiveAlign);
144 vm_address_t lowestAvaliableAddress =
145 p + sizeof (memalign_marker_t);
146 vm_address_t roundedDownAddress =
147 ((lowestAvaliableAddress >> logEffectiveAlign)
148 << logEffectiveAlign);
149 vm_address_t returnAddress =
150 (roundedDownAddress == lowestAvaliableAddress) ?
151 lowestAvaliableAddress :
152 (roundedDownAddress + effectiveAlign);
153 vm_address_t firstUnneededPage = 0;
155 memalign_marker_t *marker =
156 (memalign_marker_t *)returnAddress - 1;
158 /* lowest address used, then round down to vm_page boundary */
159 vm_address_t usedPageBase = trunc_page((vm_address_t)marker);
160 marker->start = usedPageBase;
161 marker->size = returnAddress + size - usedPageBase;
163 if (usedPageBase > p)
165 status = vm_deallocate(mach_task_self(), p, usedPageBase - p);
167 if (status != KERN_SUCCESS)
169 fprintf(stderr,
170 "Parrot_memalign(%zx, %zx) failed to deallocate extra header space.\n",
171 align, size);
175 firstUnneededPage = roundUpToPageBoundary(returnAddress + size);
177 if (firstUnneededPage < p + amountToAllocate)
179 status = vm_deallocate(mach_task_self(), firstUnneededPage,
180 p + amountToAllocate - firstUnneededPage);
182 if (status != KERN_SUCCESS)
184 fprintf(stderr,
185 "Parrot_memalign(%zx, %zx) failed to deallocate extra footer space.\n",
186 align, size);
190 return (void *)returnAddress;
197 =item C<void
198 Parrot_free_memalign(void *p)>
200 RT#48260: Not yet documented!!!
202 =cut
206 void
207 Parrot_free_memalign(void *p)
209 memalign_marker_t *marker = (memalign_marker_t *)p - 1;
211 kern_return_t status = vm_deallocate(mach_task_self(),
212 marker->start, marker->size);
214 if (status != KERN_SUCCESS)
216 fprintf(stderr, "Parrot_free_memalign(%p) failed!\n", p);
222 =back
224 =cut
229 * Local variables:
230 * c-file-style: "parrot"
231 * End:
232 * vim: expandtab shiftwidth=4: