@@ -148,53 +148,55 @@ fn test_calloc() {
148148
149149#[ cfg( not( target_os = "windows" ) ) ]
150150fn test_memalign ( ) {
151- // A normal allocation.
152- unsafe {
153- let mut ptr: * mut libc:: c_void = ptr:: null_mut ( ) ;
154- let align = 8 ;
155- let size = 64 ;
156- assert_eq ! ( libc:: posix_memalign( & mut ptr, align, size) , 0 ) ;
157- assert ! ( !ptr. is_null( ) ) ;
158- assert ! ( ptr. is_aligned_to( align) ) ;
159- ptr. cast :: < u8 > ( ) . write_bytes ( 1 , size) ;
160- libc:: free ( ptr) ;
161- }
151+ for _ in 0 ..16 {
152+ // A normal allocation.
153+ unsafe {
154+ let mut ptr: * mut libc:: c_void = ptr:: null_mut ( ) ;
155+ let align = 8 ;
156+ let size = 64 ;
157+ assert_eq ! ( libc:: posix_memalign( & mut ptr, align, size) , 0 ) ;
158+ assert ! ( !ptr. is_null( ) ) ;
159+ assert ! ( ptr. is_aligned_to( align) ) ;
160+ ptr. cast :: < u8 > ( ) . write_bytes ( 1 , size) ;
161+ libc:: free ( ptr) ;
162+ }
162163
163- // Align > size.
164- unsafe {
165- let mut ptr: * mut libc:: c_void = ptr:: null_mut ( ) ;
166- let align = 64 ;
167- let size = 8 ;
168- assert_eq ! ( libc:: posix_memalign( & mut ptr, align, size) , 0 ) ;
169- assert ! ( !ptr. is_null( ) ) ;
170- assert ! ( ptr. is_aligned_to( align) ) ;
171- ptr. cast :: < u8 > ( ) . write_bytes ( 1 , size) ;
172- libc:: free ( ptr) ;
173- }
164+ // Align > size.
165+ unsafe {
166+ let mut ptr: * mut libc:: c_void = ptr:: null_mut ( ) ;
167+ let align = 64 ;
168+ let size = 8 ;
169+ assert_eq ! ( libc:: posix_memalign( & mut ptr, align, size) , 0 ) ;
170+ assert ! ( !ptr. is_null( ) ) ;
171+ assert ! ( ptr. is_aligned_to( align) ) ;
172+ ptr. cast :: < u8 > ( ) . write_bytes ( 1 , size) ;
173+ libc:: free ( ptr) ;
174+ }
174175
175- // Size not multiple of align
176- unsafe {
177- let mut ptr: * mut libc:: c_void = ptr:: null_mut ( ) ;
178- let align = 16 ;
179- let size = 31 ;
180- assert_eq ! ( libc:: posix_memalign( & mut ptr, align, size) , 0 ) ;
181- assert ! ( !ptr. is_null( ) ) ;
182- assert ! ( ptr. is_aligned_to( align) ) ;
183- ptr. cast :: < u8 > ( ) . write_bytes ( 1 , size) ;
184- libc:: free ( ptr) ;
185- }
176+ // Size not multiple of align
177+ unsafe {
178+ let mut ptr: * mut libc:: c_void = ptr:: null_mut ( ) ;
179+ let align = 16 ;
180+ let size = 31 ;
181+ assert_eq ! ( libc:: posix_memalign( & mut ptr, align, size) , 0 ) ;
182+ assert ! ( !ptr. is_null( ) ) ;
183+ assert ! ( ptr. is_aligned_to( align) ) ;
184+ ptr. cast :: < u8 > ( ) . write_bytes ( 1 , size) ;
185+ libc:: free ( ptr) ;
186+ }
186187
187- // Size == 0
188- unsafe {
189- let mut ptr: * mut libc:: c_void = ptr:: null_mut ( ) ;
190- let align = 64 ;
191- let size = 0 ;
192- assert_eq ! ( libc:: posix_memalign( & mut ptr, align, size) , 0 ) ;
193- // Non-null pointer is returned if size == 0.
194- // (This is not a guarantee, it just reflects our current behavior.)
195- assert ! ( !ptr. is_null( ) ) ;
196- assert ! ( ptr. is_aligned_to( align) ) ;
197- libc:: free ( ptr) ;
188+ // Size == 0
189+ unsafe {
190+ let mut ptr: * mut libc:: c_void = ptr:: null_mut ( ) ;
191+ let align = 64 ;
192+ let size = 0 ;
193+ assert_eq ! ( libc:: posix_memalign( & mut ptr, align, size) , 0 ) ;
194+ // Non-null pointer is returned if size == 0.
195+ // (This is not a guarantee, it just reflects our current behavior.)
196+ assert ! ( !ptr. is_null( ) ) ;
197+ assert ! ( ptr. is_aligned_to( align) ) ;
198+ libc:: free ( ptr) ;
199+ }
198200 }
199201
200202 // Non-power of 2 align
@@ -241,6 +243,44 @@ fn test_reallocarray() {
241243 }
242244}
243245
246+ #[ cfg( not( target_os = "windows" ) ) ]
247+ fn test_aligned_alloc ( ) {
248+ // libc doesn't have this function (https://github.com/rust-lang/libc/issues/3689),
249+ // so we declare it ourselves.
250+ extern "C" {
251+ fn aligned_alloc ( alignment : libc:: size_t , size : libc:: size_t ) -> * mut libc:: c_void ;
252+ }
253+ // size not a multiple of the alignment
254+ unsafe {
255+ let p = aligned_alloc ( 16 , 3 ) ;
256+ assert_eq ! ( p, ptr:: null_mut( ) ) ;
257+ }
258+
259+ // alignment not power of 2
260+ unsafe {
261+ let p = aligned_alloc ( 63 , 8 ) ;
262+ assert_eq ! ( p, ptr:: null_mut( ) ) ;
263+ }
264+
265+ // repeated tests on correct alignment/size
266+ for _ in 0 ..16 {
267+ // alignment 1, size 4 should succeed and actually must align to 4 (because C says so...)
268+ unsafe {
269+ let p = aligned_alloc ( 1 , 4 ) ;
270+ assert ! ( !p. is_null( ) ) ;
271+ assert ! ( p. is_aligned_to( 4 ) ) ;
272+ libc:: free ( p) ;
273+ }
274+
275+ unsafe {
276+ let p = aligned_alloc ( 64 , 64 ) ;
277+ assert ! ( !p. is_null( ) ) ;
278+ assert ! ( p. is_aligned_to( 64 ) ) ;
279+ libc:: free ( p) ;
280+ }
281+ }
282+ }
283+
244284fn main ( ) {
245285 test_malloc ( ) ;
246286 test_calloc ( ) ;
@@ -254,6 +294,8 @@ fn main() {
254294 target_os = "wasi" ,
255295 ) ) ) ]
256296 test_reallocarray ( ) ;
297+ #[ cfg( not( target_os = "windows" ) ) ]
298+ test_aligned_alloc ( ) ;
257299
258300 test_memcpy ( ) ;
259301 test_strcpy ( ) ;
0 commit comments