Subject: bug#14599: An option to make vector allocation aligned

From: [email-masked] (Ludovic Courtès)
Date: Wed, 12 Jun 2013 16:59:01 +0200

severity 14599 wishlist
thanks

Hi!

Jan Schukat <[email-masked]> skribis:

> If you want to access native uniform vectors from c, sometimes you
> really want guarantees about the alignment.

[...]

> This isn't necessarily true for vectors created from pre-existing
> buffers (the take_*vector functions), but there you have control over
> the pointer you pass, so you can make it true if needed.
>
> So if there is interest, maybe this could be integrated into the build
> system as a configuration like this:
>
>
> --- libguile/bytevectors.c    2013-04-11 02:16:30.000000000 +0200
> +++ bytevectors.c    2013-06-12 14:45:16.000000000 +0200
> @@ -223,10 +223,18 @@
>
>        c_len = len * (scm_i_array_element_type_sizes[element_type] / 8);
>
> +#ifdef SCM_VECTOR_ALIGN
> +      contents = scm_gc_malloc_pointerless
> (SCM_BYTEVECTOR_HEADER_BYTES + c_len + SCM_VECTOR_ALIGN,
> +                        SCM_GC_BYTEVECTOR);
> +      ret = PTR2SCM (contents);
> +      contents += SCM_BYTEVECTOR_HEADER_BYTES;
> +      contents += (addr + (SCM_VECTOR_ALIGN - 1)) & -SCM_VECTOR_ALIGN;
> +#else
>        contents = scm_gc_malloc_pointerless
> (SCM_BYTEVECTOR_HEADER_BYTES + c_len,
>                          SCM_GC_BYTEVECTOR);
>        ret = PTR2SCM (contents);
>        contents += SCM_BYTEVECTOR_HEADER_BYTES;
> +#endif
>
>        SCM_BYTEVECTOR_SET_LENGTH (ret, c_len);
>        SCM_BYTEVECTOR_SET_CONTENTS (ret, contents);

I don’t think it should be a compile-time option, because it would be
inflexible and inconvenient.

Instead, I would suggest using the scm_take_ functions if allocating
from C, as you noted.

In Scheme, I came up with the following hack:

--8<---------------cut here---------------start------------->8---
(use-modules (system foreign)
             (rnrs bytevectors)
             (ice-9 match))

(define (memalign len alignment)
  (let* ((b (make-bytevector (+ len alignment)))
         (p (bytevector->pointer b))
         (a (pointer-address p)))
    (match (modulo a alignment)
      (0 b)
      (padding
       (let ((p (make-pointer (+ a (- alignment padding)))))
         ;; XXX: Keep a weak reference to B or it can be collected
         ;; behind our back.
         (pointer->bytevector p len))))))
--8<---------------cut here---------------end--------------->8---

Not particularly elegant, but it does the job.  ;-)

Do you think there’s additional support that should be provided?

Thanks,
Ludo’.