Message ID | 20250721104622.1550908-7-barnabas.pocze@ideasonboard.com |
---|---|
State | New |
Headers | show |
Series |
|
Related | show |
Hi Barnabás On Mon, Jul 21, 2025 at 12:46:06PM +0200, Barnabás Pőcze wrote: > Add a couple internal functions to check alignment, and to > align integers, pointer up to a given alignment. > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > --- > include/libcamera/base/details/align.h | 78 ++++++++++++++++++++++++++ > include/libcamera/base/meson.build | 1 + Just as a reminder, we will need documentation as well :) > 2 files changed, 79 insertions(+) > create mode 100644 include/libcamera/base/details/align.h > > diff --git a/include/libcamera/base/details/align.h b/include/libcamera/base/details/align.h > new file mode 100644 > index 000000000..e9569613b > --- /dev/null > +++ b/include/libcamera/base/details/align.h > @@ -0,0 +1,78 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2025, Ideas on Board Oy > + * > + * Alignment utilities > + */ > + > +#pragma once > + > +#include <cassert> > +#include <cstddef> > +#include <cstdint> > + > +#include <libcamera/base/details/cxx20.h> > + > +namespace libcamera::details::align { > + > +inline bool is(const void *p, std::uintptr_t alignment) > +{ > + assert(alignment > 0); > + > + return reinterpret_cast<std::uintptr_t>(p) % alignment == 0; > +} > + > +template<typename T> > +constexpr T up(T x, cxx20::type_identity_t<T> alignment) > +{ > + static_assert(std::is_unsigned_v<T>); > + assert(alignment > 0); > + > + const auto padding = (alignment - (x % alignment)) % alignment; > + assert(x + padding >= x); > + > + return x + padding; > +} > + > +template<typename T> > +auto *up(T *p, std::uintptr_t alignment) > +{ > + using U = std::conditional_t< > + std::is_const_v<T>, > + const std::byte, > + std::byte > + >; > + > + return reinterpret_cast<U *>(up(reinterpret_cast<std::uintptr_t>(p), alignment)); > +} > + > +template<typename T> > +T *up(std::size_t size, std::size_t alignment, T *&ptr, std::size_t *avail = nullptr) > +{ > + assert(alignment > 0); > + > + auto p = reinterpret_cast<std::uintptr_t>(ptr); > + const auto padding = (alignment - (p % alignment)) % alignment; > + > + if (avail) { > + if (size > *avail || padding > *avail - size) > + return nullptr; > + > + *avail -= size + padding; > + } > + > + p += padding; > + ptr = reinterpret_cast<T *>(p + size); > + > + return reinterpret_cast<T *>(p); > +} > + > +template<typename U, typename T> > +U *up(T *&ptr, std::size_t *avail = nullptr) > +{ > + return reinterpret_cast<std::conditional_t<std::is_const_v<T>, const U, U> *>( > + up(sizeof(U), alignof(U), ptr, avail) > + ); > +} I'm curious to see this how this will look like when used. Do you use all these overloads in the rest of the series ? > + > +} /* namespace libcamera::details::align */ > diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build > index 9836daff9..1554b996b 100644 > --- a/include/libcamera/base/meson.build > +++ b/include/libcamera/base/meson.build > @@ -33,6 +33,7 @@ libcamera_base_private_headers = files([ > > libcamera_base_details_headers = files([ > 'details/cxx20.h', > + 'details/align.h', > ]) > > libcamera_base_headers = [ > -- > 2.50.1 >
Hi 2025. 07. 25. 15:35 keltezéssel, Jacopo Mondi írta: > Hi Barnabás > > On Mon, Jul 21, 2025 at 12:46:06PM +0200, Barnabás Pőcze wrote: >> Add a couple internal functions to check alignment, and to >> align integers, pointer up to a given alignment. >> >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> >> --- >> include/libcamera/base/details/align.h | 78 ++++++++++++++++++++++++++ >> include/libcamera/base/meson.build | 1 + > > Just as a reminder, we will need documentation as well :) Things in a `details` namespace are ignored by doxygen; I could still add some documentation in the header files. > >> 2 files changed, 79 insertions(+) >> create mode 100644 include/libcamera/base/details/align.h >> >> diff --git a/include/libcamera/base/details/align.h b/include/libcamera/base/details/align.h >> new file mode 100644 >> index 000000000..e9569613b >> --- /dev/null >> +++ b/include/libcamera/base/details/align.h >> @@ -0,0 +1,78 @@ >> +/* SPDX-License-Identifier: LGPL-2.1-or-later */ >> +/* >> + * Copyright (C) 2025, Ideas on Board Oy >> + * >> + * Alignment utilities >> + */ >> + >> +#pragma once >> + >> +#include <cassert> >> +#include <cstddef> >> +#include <cstdint> >> + >> +#include <libcamera/base/details/cxx20.h> >> + >> +namespace libcamera::details::align { >> + >> +inline bool is(const void *p, std::uintptr_t alignment) >> +{ >> + assert(alignment > 0); >> + >> + return reinterpret_cast<std::uintptr_t>(p) % alignment == 0; >> +} >> + >> +template<typename T> >> +constexpr T up(T x, cxx20::type_identity_t<T> alignment) >> +{ >> + static_assert(std::is_unsigned_v<T>); >> + assert(alignment > 0); >> + >> + const auto padding = (alignment - (x % alignment)) % alignment; >> + assert(x + padding >= x); >> + >> + return x + padding; >> +} >> + >> +template<typename T> >> +auto *up(T *p, std::uintptr_t alignment) >> +{ >> + using U = std::conditional_t< >> + std::is_const_v<T>, >> + const std::byte, >> + std::byte >> + >; >> + >> + return reinterpret_cast<U *>(up(reinterpret_cast<std::uintptr_t>(p), alignment)); >> +} >> + >> +template<typename T> >> +T *up(std::size_t size, std::size_t alignment, T *&ptr, std::size_t *avail = nullptr) >> +{ >> + assert(alignment > 0); >> + >> + auto p = reinterpret_cast<std::uintptr_t>(ptr); >> + const auto padding = (alignment - (p % alignment)) % alignment; >> + >> + if (avail) { >> + if (size > *avail || padding > *avail - size) >> + return nullptr; >> + >> + *avail -= size + padding; >> + } >> + >> + p += padding; >> + ptr = reinterpret_cast<T *>(p + size); >> + >> + return reinterpret_cast<T *>(p); >> +} >> + >> +template<typename U, typename T> >> +U *up(T *&ptr, std::size_t *avail = nullptr) >> +{ >> + return reinterpret_cast<std::conditional_t<std::is_const_v<T>, const U, U> *>( >> + up(sizeof(U), alignof(U), ptr, avail) >> + ); >> +} > > I'm curious to see this how this will look like when used. > Do you use all these overloads in the rest of the series ? All of these should be used somewhere. std::byte *buf = ...; std::size_t avail = ...; auto *p = details::align::up<SomeType>(buf, &avail); // allocate suitable aligned and sized storage auto *x = new (p) SomeType { ... }; // construct object in said storage Regards, Barnabás Pőcze > >> + >> +} /* namespace libcamera::details::align */ >> diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build >> index 9836daff9..1554b996b 100644 >> --- a/include/libcamera/base/meson.build >> +++ b/include/libcamera/base/meson.build >> @@ -33,6 +33,7 @@ libcamera_base_private_headers = files([ >> >> libcamera_base_details_headers = files([ >> 'details/cxx20.h', >> + 'details/align.h', >> ]) >> >> libcamera_base_headers = [ >> -- >> 2.50.1 >>
diff --git a/include/libcamera/base/details/align.h b/include/libcamera/base/details/align.h new file mode 100644 index 000000000..e9569613b --- /dev/null +++ b/include/libcamera/base/details/align.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2025, Ideas on Board Oy + * + * Alignment utilities + */ + +#pragma once + +#include <cassert> +#include <cstddef> +#include <cstdint> + +#include <libcamera/base/details/cxx20.h> + +namespace libcamera::details::align { + +inline bool is(const void *p, std::uintptr_t alignment) +{ + assert(alignment > 0); + + return reinterpret_cast<std::uintptr_t>(p) % alignment == 0; +} + +template<typename T> +constexpr T up(T x, cxx20::type_identity_t<T> alignment) +{ + static_assert(std::is_unsigned_v<T>); + assert(alignment > 0); + + const auto padding = (alignment - (x % alignment)) % alignment; + assert(x + padding >= x); + + return x + padding; +} + +template<typename T> +auto *up(T *p, std::uintptr_t alignment) +{ + using U = std::conditional_t< + std::is_const_v<T>, + const std::byte, + std::byte + >; + + return reinterpret_cast<U *>(up(reinterpret_cast<std::uintptr_t>(p), alignment)); +} + +template<typename T> +T *up(std::size_t size, std::size_t alignment, T *&ptr, std::size_t *avail = nullptr) +{ + assert(alignment > 0); + + auto p = reinterpret_cast<std::uintptr_t>(ptr); + const auto padding = (alignment - (p % alignment)) % alignment; + + if (avail) { + if (size > *avail || padding > *avail - size) + return nullptr; + + *avail -= size + padding; + } + + p += padding; + ptr = reinterpret_cast<T *>(p + size); + + return reinterpret_cast<T *>(p); +} + +template<typename U, typename T> +U *up(T *&ptr, std::size_t *avail = nullptr) +{ + return reinterpret_cast<std::conditional_t<std::is_const_v<T>, const U, U> *>( + up(sizeof(U), alignof(U), ptr, avail) + ); +} + +} /* namespace libcamera::details::align */ diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build index 9836daff9..1554b996b 100644 --- a/include/libcamera/base/meson.build +++ b/include/libcamera/base/meson.build @@ -33,6 +33,7 @@ libcamera_base_private_headers = files([ libcamera_base_details_headers = files([ 'details/cxx20.h', + 'details/align.h', ]) libcamera_base_headers = [
Add a couple internal functions to check alignment, and to align integers, pointer up to a given alignment. Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> --- include/libcamera/base/details/align.h | 78 ++++++++++++++++++++++++++ include/libcamera/base/meson.build | 1 + 2 files changed, 79 insertions(+) create mode 100644 include/libcamera/base/details/align.h