@@ -15,11 +15,7 @@ extern "C" {
1515
1616/* Test visibility macro for internal functions */
1717#ifndef MEM_ALLOC_API_INTER
18- #ifdef WAMR_BUILD_TEST
19- #define MEM_ALLOC_API_INTER
20- #else
21- #define MEM_ALLOC_API_INTER static
22- #endif
18+ #define MEM_ALLOC_API_INTER WASM_RUNTIME_API_INTERN
2319#endif
2420
2521/* HMU (heap memory unit) basic block type */
@@ -102,22 +98,120 @@ hmu_verify(void *vheap, hmu_t *hmu);
10298 + (((x) > 8) ? (x) : 8))
10399
104100/*
105- * Aligned allocation uses metadata in the header to store the offset
101+ * ============================================================================
102+ * Aligned Memory Allocation
103+ * ============================================================================
106104 *
107- * ### Memory Layout
105+ * This module implements aligned memory allocation similar to C11
106+ * aligned_alloc() and POSIX posix_memalign() for WAMR's garbage collector.
108107 *
109- * Aligned allocations use over-allocation with metadata storage:
108+ * POSIX aligned_alloc() Specification:
109+ * ------------------------------------
110+ * From C11 §7.22.3.1 and POSIX.1-2017:
111+ * void *aligned_alloc(size_t alignment, size_t size);
110112 *
111- * ```
112- * [HMU][PREFIX][...padding...][METADATA][ALIGNED_OBJ][SUFFIX]
113- * ^8 bytes ^returned pointer (aligned)
114- * ```
113+ * Requirements:
114+ * - alignment: Must be a valid alignment supported by the implementation,
115+ * typically a power of 2
116+ * - size: Must be an integral multiple of alignment
117+ * - Returns: Pointer aligned to the specified alignment boundary, or NULL
118+ * - Memory must be freed with free() (not realloc'd)
119+ * - Behavior: If size is 0, may return NULL or unique pointer (impl-defined)
120+ *
121+ * IMPORTANT: POSIX does not require realloc() to preserve alignment.
122+ * Calling realloc() on aligned_alloc() memory has undefined behavior.
123+ *
124+ * WAMR Implementation Strategy:
125+ * -----------------------------
126+ * We implement alignment through over-allocation with metadata tracking:
127+ *
128+ * 1. **Validation Phase**:
129+ * - Check alignment is power-of-2, >= 8 bytes, <= system page size
130+ * - Check size is multiple of alignment
131+ * - Return NULL if validation fails
132+ *
133+ * 2. **Over-Allocation**:
134+ * - Allocate (size + alignment + metadata_overhead) bytes
135+ * - Extra space allows us to find an aligned boundary within the block
136+ * - Calculate log2(alignment) for efficient offset storage
137+ *
138+ * 3. **Alignment Adjustment**:
139+ * - Find next aligned address within allocated block
140+ * - Calculate offset from original allocation to aligned address
141+ * - Store offset in metadata for later free() operation
142+ *
143+ * 4. **Magic Marker Storage**:
144+ * - Store magic marker (0xA11C0000 | offset) in 4 bytes before user pointer
145+ * - Upper 16 bits: 0xA11C identifies aligned allocation
146+ * - Lower 16 bits: offset from HMU to aligned pointer (max 65535 bytes)
147+ * - This marker prevents unsafe realloc() operations
148+ *
149+ * 5. **Realloc Prevention**:
150+ * - gc_realloc_vo_internal() checks for magic marker
151+ * - Returns NULL if realloc attempted on aligned allocation
152+ * - User must manually allocate new memory and copy data
153+ *
154+ * Memory Layout Diagram:
155+ * ----------------------
156+ *
157+ * Low Address High Address
158+ * ┌─────────────┬──────────┬────────────────┬──────────────┬─────────────┐
159+ * │ HMU Header │ Padding │ Magic + Offset │ Aligned Data │ Padding │
160+ * │ (meta) │ (0-align)│ (4 bytes) │ (size) │ (overhead) │
161+ * └─────────────┴──────────┴────────────────┴──────────────┴─────────────┘
162+ * ▲ ▲
163+ * │ │
164+ * magic_ptr user_ptr (returned, aligned)
115165 *
116- * Magic value for aligned allocation detection
166+ * Constraints and Limitations:
167+ * ----------------------------
168+ * - Minimum alignment: 8 bytes (GC_MIN_ALIGNMENT)
169+ * - Maximum alignment: System page size (os_getpagesize(), typically 4KB)
170+ * - Maximum offset: 65535 bytes (16-bit storage limit)
171+ * - Realloc support: None - returns NULL (prevents alignment loss)
172+ * - Free support: Full - use mem_allocator_free() / wasm_runtime_free()
173+ * - Thread safety: Protected by LOCK_HEAP/UNLOCK_HEAP
174+ *
175+ * Usage Example:
176+ * --------------
177+ * // Allocate 256 bytes aligned to 64-byte boundary (e.g., for SIMD)
178+ * void *ptr = wasm_runtime_aligned_alloc(256, 64);
179+ * assert((uintptr_t)ptr % 64 == 0); // Guaranteed aligned
180+ *
181+ * // Use the memory...
182+ *
183+ * // Free normally (alignment metadata handled automatically)
184+ * wasm_runtime_free(ptr);
185+ *
186+ * // INVALID: Cannot realloc aligned memory
187+ * void *new_ptr = wasm_runtime_realloc(ptr, 512); // Returns NULL!
117188 */
189+
190+ /* Aligned allocation magic markers */
118191#define ALIGNED_ALLOC_MAGIC_MASK 0xFFFF0000
119192#define ALIGNED_ALLOC_MAGIC_VALUE 0xA11C0000
120193
194+ /**
195+ * Check if a gc_object was allocated with alignment requirements.
196+ *
197+ * Aligned allocations store a magic marker (0xA11C0000) in the 4 bytes
198+ * immediately before the object pointer. This marker is used to identify
199+ * aligned allocations to prevent unsafe realloc operations.
200+ *
201+ * @param obj the gc_object to check (user-visible pointer)
202+ * @return true if obj is an aligned allocation, false otherwise
203+ */
204+ static inline bool
205+ gc_is_aligned_allocation (gc_object_t obj )
206+ {
207+ if (!obj )
208+ return false;
209+
210+ uint32_t * magic_ptr = (uint32_t * )((char * )obj - 4 );
211+ return ((* magic_ptr & ALIGNED_ALLOC_MAGIC_MASK )
212+ == ALIGNED_ALLOC_MAGIC_VALUE );
213+ }
214+
121215/**
122216 * hmu bit operation
123217 */
0 commit comments