Fix FS#12824 : Malfunctioning FFT plugin in Sansa Clip Zip
[maemo-rb.git] / firmware / include / buflib.h
blob6c9ccf74028ee138f0907cd33f4b9fbb69e3a4ac
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * This is a memory allocator designed to provide reasonable management of free
11 * space and fast access to allocated data. More than one allocator can be used
12 * at a time by initializing multiple contexts.
14 * Copyright (C) 2009 Andrew Mahone
15 * Copyright (C) 2011 Thomas Martitz
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
23 * KIND, either express or implied.
25 ****************************************************************************/
27 #ifndef _BUFLIB_H_
28 #define _BUFLIB_H_
29 #include <stdint.h>
30 #include <stdbool.h>
31 #include <string.h>
33 /* enable single block debugging */
34 #define BUFLIB_DEBUG_BLOCK_SINGLE
36 union buflib_data
38 intptr_t val;
39 char name[1]; /* actually a variable sized string */
40 struct buflib_callbacks* ops;
41 char* alloc;
42 union buflib_data *handle;
45 struct buflib_context
47 union buflib_data *handle_table;
48 union buflib_data *first_free_handle;
49 union buflib_data *last_handle;
50 union buflib_data *buf_start;
51 union buflib_data *alloc_end;
52 bool compact;
55 /**
56 * Callbacks used by the buflib to inform allocation that compaction
57 * is happening (before data is moved)
59 * Note that buflib tries to move to satisfy new allocations before shrinking.
60 * So if you have something to resize try to do it outside of the callback.
62 * Regardless of the above, if the allocation is SHRINKABLE, but not
63 * MUST_NOT_MOVE buflib will move the allocation before even attempting to
64 * shrink.
66 struct buflib_callbacks {
67 /**
68 * This is called before data is moved. Use this to fix up any cached
69 * pointers pointing to inside the allocation. The size is unchanged.
71 * This is not needed if you don't cache the data pointer (but always
72 * call buflib_get_data()) and don't pass pointer to the data to yielding
73 * functions.
75 * handle: The corresponding handle
76 * current: The current start of the allocation
77 * new: The new start of the allocation, after data movement
79 * Return: Return BUFLIB_CB_OK, or BUFLIB_CB_CANNOT_MOVE if movement
80 * is impossible at this moment.
82 * If NULL: this allocation must not be moved around by the buflib when
83 * compation occurs
85 int (*move_callback)(int handle, void* current, void* new);
86 /**
87 * This is called when the buflib desires to shrink a buffer
88 * in order to satisfy new allocation. This happens when buflib runs
89 * out of memory, e.g. because buflib_alloc_maximum() was called.
90 * Move data around as you need to make space and call core_shrink() as
91 * appropriate from within the callback to complete the shrink operation.
92 * buflib will not move data as part of shrinking.
94 * hint: bit mask containing hints on how shrinking is desired (see below)
95 * handle: The corresponding handle
96 * start: The old start of the allocation
98 * Return: Return BUFLIB_CB_OK, or BUFLIB_CB_CANNOT_SHRINK if shirinking
99 * is impossible at this moment.
101 * if NULL: this allocation cannot be resized.
102 * It is recommended that allocation that must not move are
103 * at least shrinkable
105 int (*shrink_callback)(int handle, unsigned hints, void* start, size_t old_size);
107 * This is called when special steps must be taken for synchronization
108 * both before the move_callback is called and after the data has been
109 * moved.
111 void (*sync_callback)(int handle, bool sync_on);
114 #define BUFLIB_SHRINK_POS_MASK ((1<<0|1<<1)<<30)
115 #define BUFLIB_SHRINK_SIZE_MASK (~BUFLIB_SHRINK_POS_MASK)
116 #define BUFLIB_SHRINK_POS_FRONT (1u<<31)
117 #define BUFLIB_SHRINK_POS_BACK (1u<<30)
120 * Possible return values for the callbacks, some of them can cause
121 * compaction to fail and therefore new allocations to fail
123 /* Everything alright */
124 #define BUFLIB_CB_OK 0
125 /* Tell buflib that moving failed. Buflib may retry to move at any point */
126 #define BUFLIB_CB_CANNOT_MOVE 1
127 /* Tell buflib that resizing failed, possibly future making allocations fail */
128 #define BUFLIB_CB_CANNOT_SHRINK 1
131 * Initializes buflib with a caller allocated context instance and memory pool.
133 * The buflib_context instance needs to be passed to every other buflib
134 * function. It's should be considered opaque, even though it is not yet
135 * (that's to make inlining core_get_data() possible). The documentation
136 * of the other functions will not describe the context
137 * instance paramter further as it's obligatory.
139 * context: The new buflib instance to be initialized, allocated by the caller
140 * size: The size of the memory pool
142 void buflib_init(struct buflib_context *context, void *buf, size_t size);
146 * Returns how many bytes left the buflib has to satisfy allocations.
148 * This function does not yet consider possible compaction so there might
149 * be more space left. This may change in the future.
151 * Returns: The number of bytes left in the memory pool.
153 size_t buflib_available(struct buflib_context *ctx);
157 * Allocates memory from buflib's memory pool
159 * size: How many bytes to allocate
161 * Returns: A positive integer handle identifying this allocation, or
162 * a negative value on error (0 is also not a valid handle)
164 int buflib_alloc(struct buflib_context *context, size_t size);
168 * Allocates memory from the buflib's memory pool with additional callbacks
169 * and flags
171 * name: A string identifier giving this allocation a name
172 * size: How many bytes to allocate
173 * ops: a struct with pointers to callback functions (see above)
175 * Returns: A positive integer handle identifying this allocation, or
176 * a negative value on error (0 is also not a valid handle)
178 int buflib_alloc_ex(struct buflib_context *ctx, size_t size, const char *name,
179 struct buflib_callbacks *ops);
183 * Gets all available memory from buflib, for temporary use.
185 * Since this effectively makes all future allocations fail (unless
186 * another allocation is freed in the meantime), you should definitely provide
187 * a shrink callback if you plan to hold the buffer for a longer period. This
188 * will allow buflib to permit allocations by shrinking the buffer returned by
189 * this function.
191 * Note that this currently gives whatever buflib_available() returns. However,
192 * do not depend on this behavior, it may change.
194 * name: A string identifier giving this allocation a name
195 * size: The actual size will be returned into size
196 * ops: a struct with pointers to callback functions
198 * Returns: A positive integer handle identifying this allocation, or
199 * a negative value on error (0 is also not a valid handle)
201 int buflib_alloc_maximum(struct buflib_context* ctx, const char* name,
202 size_t *size, struct buflib_callbacks *ops);
205 * Queries the data pointer for the given handle. It's actually a cheap
206 * operation, don't hesitate using it extensivly.
208 * Notice that you need to re-query after every direct or indirect yield(),
209 * because compaction can happen by other threads which may get your data
210 * moved around (or you can get notified about changes by callbacks,
211 * see further above).
213 * handle: The handle corresponding to the allocation
215 * Returns: The start pointer of the allocation
217 static inline void* buflib_get_data(struct buflib_context *context, int handle)
219 return (void*)(context->handle_table[-handle].alloc);
223 * Shrink the memory allocation associated with the given handle
224 * Mainly intended to be used with the shrink callback, but it can also
225 * be called outside as well, e.g. to give back buffer space allocated
226 * with buflib_alloc_maximum().
228 * Note that you must move/copy data around yourself before calling this,
229 * buflib will not do this as part of shrinking.
231 * handle: The handle identifying this allocation
232 * new_start: the new start of the allocation
233 * new_size: the new size of the allocation
235 * Returns: true if shrinking was successful. Otherwise it returns false,
236 * without having modified memory.
239 bool buflib_shrink(struct buflib_context *ctx, int handle, void* newstart, size_t new_size);
242 * Frees memory associated with the given handle
244 * Returns: 0 (to invalidate handles in one line, 0 is not a valid handle)
246 int buflib_free(struct buflib_context *context, int handle);
249 * Moves the underlying buflib buffer up by size bytes (as much as
250 * possible for size == 0) without moving the end. This effectively
251 * reduces the available space by taking away managable space from the
252 * front. This space is not available for new allocations anymore.
254 * To make space available in the front, everything is moved up.
255 * It does _NOT_ call the move callbacks
258 * size: size in bytes to move the buffer up (take away). The actual
259 * bytes moved is returned in this
260 * Returns: The new start of the underlying buflib buffer
262 void* buflib_buffer_out(struct buflib_context *ctx, size_t *size);
265 * Moves the underlying buflib buffer down by size bytes without
266 * moving the end. This grows the buflib buffer by adding space to the front.
267 * The new bytes are available for new allocations.
269 * Everything is moved down, and the new free space will be in the middle.
270 * It does _NOT_ call the move callbacks.
272 * size: size in bytes to move the buffer down (new free space)
274 void buflib_buffer_in(struct buflib_context *ctx, int size);
276 /* debugging */
279 * Returns the name, as given to core_alloc() and core_allloc_ex(), of the
280 * allocation associated with the given handle
282 * handle: The handle indicating the allocation
284 * Returns: A pointer to the string identifier of the allocation
286 const char* buflib_get_name(struct buflib_context *ctx, int handle);
289 * Prints an overview of all current allocations with the help
290 * of the passed printer helper
292 * This walks only the handle table and prints only valid allocations
294 * Only available if BUFLIB_DEBUG_BLOCKS is defined
296 void buflib_print_allocs(struct buflib_context *ctx, void (*print)(int, const char*));
299 * Prints an overview of all blocks in the buflib buffer, allocated
300 * or unallocated, with the help pf the passted printer helper
302 * This walks the entire buffer and prints unallocated space also.
303 * The output is also different from buflib_print_allocs().
305 * Only available if BUFLIB_DEBUG_BLOCKS is defined
307 void buflib_print_blocks(struct buflib_context *ctx, void (*print)(int, const char*));
310 * Gets the number of blocks in the entire buffer, allocated or unallocated
312 * Only available if BUFLIB_DEBUG_BLOCK_SIGNLE is defined
314 int buflib_get_num_blocks(struct buflib_context *ctx);
317 * Print information about a single block as indicated by block_num
318 * into buf
320 * buflib_get_num_blocks() beforehand to get the total number of blocks,
321 * as passing an block_num higher than that is undefined
323 * Only available if BUFLIB_DEBUG_BLOCK_SIGNLE is defined
325 void buflib_print_block_at(struct buflib_context *ctx, int block_num,
326 char* buf, size_t bufsize);
327 #endif