3 * Copyright (C) 2007, The Perl Foundation.
14 memalign related stuff
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!!!
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!!!
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!!!
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!!!
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
{
92 vm_size_t size
; } memalign_marker_t
;
97 Parrot_memalign(size_t align, size_t size)>
99 RT#48260: Not yet documented!!!
106 Parrot_memalign(size_t align
, size_t size
)
108 size_t effectiveAlign
= align
;
110 size_t amountToAllocate
= 0;
112 if (effectiveAlign
< sizeof (void *))
114 effectiveAlign
= roundUpPowerOf2(sizeof (void *));
118 effectiveAlign
= roundUpPowerOf2(effectiveAlign
);
121 if (effectiveAlign
< sizeof (memalign_marker_t
))
123 padding
= sizeof (memalign_marker_t
);
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
)
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
)
170 "Parrot_memalign(%zx, %zx) failed to deallocate extra header space.\n",
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
)
185 "Parrot_memalign(%zx, %zx) failed to deallocate extra footer space.\n",
190 return (void *)returnAddress
;
198 Parrot_free_memalign(void *p)>
200 RT#48260: Not yet documented!!!
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
);
230 * c-file-style: "parrot"
232 * vim: expandtab shiftwidth=4: