1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/include/zptr.h
Alexandre Abadie fce6e4032d
sys/zptr: fix typos
- 'bounderies' -> 'boundaries'
- 'compressable' -> 'compressible'
- 'Substracts' -> 'Subtracts'
2020-10-02 08:15:00 +02:00

140 lines
3.4 KiB
C

/*
* Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup sys_util_zptr Pointer Compression
* @ingroup sys
* @brief Provides 32bit -> 16bit pointer compression
*
* On many platforms, some pointers may have to be aligned, e.g., to 4 byte
* boundaries.
* On 32bit platforms, that makes it possible to store all possible aligned
* 32bit pointers in a 16bit value as long as the total memory is small (e.g.,
* with 4 byte alignment, all pointers within 256kb RAM can be represented by a
* 16bit value). This can save memory, at the cost of some instructions for
* compression/decompression.
*
* In order to use pointer compression, ZPTR_BASE needs to be defined to a (4
* byte aligned) base address.
*
* A printf format macro (PRIzptr) is provided.
*
* You can then use zptr_t instead of a pointer type, using the supplied functions to compress / decompress,
* e.g.,
*
* void func(void *ptr) {
* printf("%"PRIzptr"\n", ptr);
* ...
* free(ptr);
* }
*
* ... would become
*
* void func(zptr_t zptr);
* printf("%"PRIzptr"\n", zptr);
* ...
* free(zptrd(zptr));
* }
*
*
* If ZPTR_BASE is unset, @ref zptr_t / @ref zptrc() / @ref zptrd() will
* transparently and without overhead compile to normal (uncompressed) pointer
* operations.
*
* @{
*
* @file
* @brief 32bit -> 16bit pointer compression implementation
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifndef ZPTR_H
#define ZPTR_H
#include <assert.h>
#include <stdint.h>
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
#if ZPTR_BASE || defined(DOXYGEN)
/**
* @brief zptr type definition
*/
typedef uint16_t zptr_t;
/**
* @brief zptr printf format definition
*/
#define PRIzptr PRIu16
/**
* @brief zptr highest compressible address
*/
#define ZPTR_MAX_ADDR ((uintptr_t)ZPTR_BASE + (1 << 18))
/**
* @brief Determine if a pointer is compressible by zptrc()
* @param[in] pointer pointer to check
* @returns 1 if pointer can be compressed, 0 if not
*/
static inline int zptr_check(void *pointer)
{
uintptr_t int_ptr = (uintptr_t)pointer;
return ((!(int_ptr & 0x3)) \
&& (int_ptr >= (uintptr_t)ZPTR_BASE) \
&& (int_ptr < ZPTR_MAX_ADDR));
}
/**
* @brief Compress a pointer (if possible)
*
* Subtracts ZPTR_BASE, then right-shifts @p pointer by two.
*
* @param[in] pointer pointer to compress
* @returns compressed pointer
*/
static inline zptr_t zptrc(void *pointer)
{
assert(zptr_check(pointer));
return (uint16_t)(((uint32_t)pointer - (uint32_t)ZPTR_BASE) >> 2);
}
/**
* @brief Decompress a pointer
*
* Left-shifts zptr_t by two, then adds ZPTR_BASE.
*
* @param[in] zptr compressed pointer
* @returns decompressed pointer
*/
static inline void *zptrd(zptr_t zptr)
{
return (void *)(ZPTR_BASE + ((uint32_t)zptr << 2));
}
#else /* ZPTR_BASE */
/* fallback implementation */
typedef void *zptr_t;
#define PRIzptr "p"
static inline int zptr_check(void *pointer) { (void)pointer; return 0; }
static inline zptr_t zptrc(void *pointer) { return (zptr_t)pointer; }
static inline void *zptrd(zptr_t zptr) { return (void *)zptr; }
#endif
#ifdef __cplusplus
}
#endif
#endif /* ZPTR_H */
/** @} */