| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- #ifndef PORTABLE_H
- #define PORTABLE_H
- /*
- * Architecture portability layer.
- * Target: Raspberry Pi 5 (BCM2712, Cortex-A76, aarch64 LP64, 8GB RAM)
- * and x86_64 dev host. Both are little-endian; PS/RTP/ISUP wire
- * formats are BIG-ENDIAN, so every multi-byte field on the wire is
- * built via explicit shift writers (never by casting a char* to a
- * wider type, which is undefined on strict-alignment ABIs and
- * endian-wrong on any host).
- */
- #include <stdint.h>
- #include <stddef.h>
- #include <pthread.h>
- #include <unistd.h>
- #include <limits.h>
- #include <errno.h>
- /* char is UNSIGNED by default on the ARM AAPCS (aarch64). Never rely on
- * signedness of plain char for byte values: always use uint8_t or int. */
- /* Fixed-width, ABI-stable types. On LP64 'long' is 8 bytes while on ILP32
- * it is 4; we therefore avoid long/int for cross-arch fields. */
- typedef int32_t hk_i32;
- typedef uint32_t hk_u32;
- typedef int64_t hk_i64;
- typedef uint64_t hk_u64;
- /* Big-endian byte writers (wire order). Unaligned-safe via memcpy, correct
- * on x86_64 and aarch64 alike. */
- static inline void be_write16(uint8_t *p, uint16_t v){
- p[0]=(uint8_t)(v>>8); p[1]=(uint8_t)v;
- }
- static inline void be_write24(uint8_t *p, uint32_t v){
- p[0]=(uint8_t)(v>>16); p[1]=(uint8_t)(v>>8); p[2]=(uint8_t)v;
- }
- static inline void be_write32(uint8_t *p, uint32_t v){
- p[0]=(uint8_t)(v>>24); p[1]=(uint8_t)(v>>16); p[2]=(uint8_t)(v>>8); p[3]=(uint8_t)v;
- }
- static inline void be_write48(uint8_t *p, uint64_t v){
- for(int i=0;i<6;i++) p[i]=(uint8_t)(v>>((5-i)*8));
- }
- /* Big-endian readers */
- static inline uint16_t be_read16(const uint8_t *p){ return (uint16_t)((p[0]<<8)|p[1]); }
- static inline uint32_t be_read32(const uint8_t *p){
- return ((uint32_t)p[0]<<24)|((uint32_t)p[1]<<16)|((uint32_t)p[2]<<8)|(uint32_t)p[3];
- }
- /* Monotonic milliseconds (immune to wall-clock jumps / NTP on Pi). */
- int64_t portable_now_ms(void);
- /* Portable sleep (nanosleep; usleep is deprecated on newer glibc). */
- void portable_sleep_ms(int ms);
- /* Configure a thread with an explicit stack size (Pi5 default 8MB is fine,
- * but big PS buffers are heap-allocated so worker threads get a modest
- * 256KB stack -> predictable on 8GB board and embedded builds). */
- int portable_thread_create(pthread_t *t, void*(*fn)(void*), void*arg, size_t stack_bytes);
- #endif /* PORTABLE_H */
|