xref: /btstack/tool/btstack_memory_generator.py (revision 2a95308bb24d40c8fec7aa678b716693da8d28ba)
1#!/usr/bin/env python3
2import os
3import sys
4
5import os
6import sys
7
8copyright = """/*
9 * Copyright (C) 2014 BlueKitchen GmbH
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the copyright holders nor the names of
21 *    contributors may be used to endorse or promote products derived
22 *    from this software without specific prior written permission.
23 * 4. Any redistribution, use, or modification is done solely for
24 *    personal benefit and not for any commercial purpose or for
25 *    monetary gain.
26 *
27 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
30 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
31 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
33 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
34 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
35 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
37 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * Please inquire about commercial licensing options at
41 * [email protected]
42 *
43 */
44"""
45
46hfile_header_begin = """
47
48/*
49 *  btstack_memory.h
50 *
51 *  @brief BTstack memory management via configurable memory pools
52 *
53 */
54
55#ifndef BTSTACK_MEMORY_H
56#define BTSTACK_MEMORY_H
57
58#if defined __cplusplus
59extern "C" {
60#endif
61
62#include "btstack_config.h"
63
64// Core
65#include "hci.h"
66#include "l2cap.h"
67
68// Classic
69#include "classic/bnep.h"
70#include "classic/hfp.h"
71#include "classic/btstack_link_key_db.h"
72#include "classic/btstack_link_key_db_memory.h"
73#include "classic/rfcomm.h"
74#include "classic/sdp_server.h"
75#include "classic/avdtp_sink.h"
76#include "classic/avdtp_source.h"
77#include "classic/avrcp.h"
78
79// BLE
80#ifdef ENABLE_BLE
81#include "ble/gatt_client.h"
82#include "ble/sm.h"
83#endif
84
85#ifdef ENABLE_MESH
86#include "mesh/mesh_network.h"
87#include "mesh/mesh_keys.h"
88#include "mesh/mesh_virtual_addresses.h"
89#endif
90
91/* API_START */
92
93/**
94 * @brief Initializes BTstack memory pools.
95 */
96void btstack_memory_init(void);
97
98/**
99 * @brief Deinitialize BTstack memory pools
100 * @note if HAVE_MALLOC is defined, all previously allocated buffers are free'd
101 */
102void btstack_memory_deinit(void);
103
104/* API_END */
105"""
106
107hfile_header_end = """
108#if defined __cplusplus
109}
110#endif
111
112#endif // BTSTACK_MEMORY_H
113"""
114
115cfile_header_begin = """
116#define BTSTACK_FILE__ "btstack_memory.c"
117
118
119/*
120 *  btstack_memory.c
121 *
122 *  @brief BTstack memory management via configurable memory pools
123 *
124 *  @note code generated by tool/btstack_memory_generator.py
125 *  @note returnes buffers are initialized with 0
126 *
127 */
128
129#include "btstack_memory.h"
130#include "btstack_memory_pool.h"
131#include "btstack_debug.h"
132
133#include <stdlib.h>
134
135#ifdef HAVE_MALLOC
136typedef struct btstack_memory_buffer {
137    struct btstack_memory_buffer * next;
138    struct btstack_memory_buffer * prev;
139} btstack_memory_buffer_t;
140
141static btstack_memory_buffer_t * btstack_memory_malloc_buffers;
142
143static void btstack_memory_tracking_add(btstack_memory_buffer_t * buffer){
144    btstack_assert(buffer != NULL);
145    btstack_memory_malloc_buffers = buffer;
146    buffer->prev = NULL;
147    buffer->next = btstack_memory_malloc_buffers;
148    btstack_memory_malloc_buffers = buffer;
149}
150
151static void btstack_memory_tracking_remove(btstack_memory_buffer_t * buffer){
152    btstack_assert(buffer != NULL);
153    if (buffer->prev == NULL){
154        // first item
155        btstack_memory_malloc_buffers = buffer->next;
156    } else {
157        buffer->prev->next = buffer->next;
158    }
159    if (buffer->next != NULL){
160        buffer->next->prev = buffer->prev;
161    }
162}
163#endif
164
165void btstack_memory_deinit(void){
166#ifdef HAVE_MALLOC
167    while (btstack_memory_malloc_buffers != NULL){
168        btstack_memory_buffer_t * buffer = btstack_memory_malloc_buffers;
169        btstack_memory_malloc_buffers = buffer->next;
170        free(buffer);
171    }
172#endif
173}
174"""
175
176header_template = """STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void);
177void   btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME);"""
178
179code_template = """
180// MARK: STRUCT_TYPE
181#if !defined(HAVE_MALLOC) && !defined(POOL_COUNT)
182    #if defined(POOL_COUNT_OLD_NO)
183        #error "Deprecated POOL_COUNT_OLD_NO defined instead of POOL_COUNT. Please update your btstack_config.h to use POOL_COUNT."
184    #else
185        #define POOL_COUNT 0
186    #endif
187#endif
188
189#ifdef POOL_COUNT
190#if POOL_COUNT > 0
191static STRUCT_TYPE STRUCT_NAME_storage[POOL_COUNT];
192static btstack_memory_pool_t STRUCT_NAME_pool;
193STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){
194    void * buffer = btstack_memory_pool_get(&STRUCT_NAME_pool);
195    if (buffer){
196        memset(buffer, 0, sizeof(STRUCT_TYPE));
197    }
198    return (STRUCT_NAME_t *) buffer;
199}
200void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){
201    btstack_memory_pool_free(&STRUCT_NAME_pool, STRUCT_NAME);
202}
203#else
204STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){
205    return NULL;
206}
207void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){
208    UNUSED(STRUCT_NAME);
209};
210#endif
211#elif defined(HAVE_MALLOC)
212
213typedef struct {
214    STRUCT_NAME_t data;
215    btstack_memory_buffer_t tracking;
216} btstack_memory_STRUCT_NAME_t;
217
218STRUCT_NAME_t * btstack_memory_STRUCT_NAME_get(void){
219    btstack_memory_STRUCT_NAME_t * buffer = (btstack_memory_STRUCT_NAME_t *) malloc(sizeof(btstack_memory_STRUCT_NAME_t));
220    if (buffer){
221        memset(buffer, 0, sizeof(STRUCT_NAME_t));
222        btstack_memory_tracking_add(&buffer->tracking);
223        return &buffer->data;
224    } else {
225        return NULL;
226    }
227}
228void btstack_memory_STRUCT_NAME_free(STRUCT_NAME_t *STRUCT_NAME){
229    btstack_memory_STRUCT_NAME_t * buffer =  (btstack_memory_STRUCT_NAME_t *) STRUCT_NAME;
230    btstack_memory_tracking_remove(&buffer->tracking);
231    free(buffer);
232}
233#endif
234"""
235
236init_template = """#if POOL_COUNT > 0
237    btstack_memory_pool_create(&STRUCT_NAME_pool, STRUCT_NAME_storage, POOL_COUNT, sizeof(STRUCT_TYPE));
238#endif"""
239
240def writeln(f, data):
241    f.write(data + "\n")
242
243def replacePlaceholder(template, struct_name):
244    struct_type = struct_name + '_t'
245    if struct_name.endswith('try'):
246        pool_count = "MAX_NR_" + struct_name.upper()[:-3] + "TRIES"
247    else:
248        pool_count = "MAX_NR_" + struct_name.upper() + "S"
249    pool_count_old_no = pool_count.replace("MAX_NR_", "MAX_NO_")
250    snippet = template.replace("STRUCT_TYPE", struct_type).replace("STRUCT_NAME", struct_name).replace("POOL_COUNT_OLD_NO", pool_count_old_no).replace("POOL_COUNT", pool_count)
251    return snippet
252
253list_of_structs = [
254    ["hci_connection"],
255    ["l2cap_service", "l2cap_channel"],
256]
257list_of_classic_structs = [
258    ["rfcomm_multiplexer", "rfcomm_service", "rfcomm_channel"],
259    ["btstack_link_key_db_memory_entry"],
260    ["bnep_service", "bnep_channel"],
261    ["hfp_connection"],
262    ["service_record_item"],
263    ["avdtp_stream_endpoint"],
264    ["avdtp_connection"],
265    ["avrcp_connection"],
266    ["avrcp_browsing_connection"],
267]
268list_of_le_structs = [
269    ["gatt_client", "whitelist_entry", "sm_lookup_entry"],
270]
271list_of_mesh_structs = [
272    ['mesh_network_pdu', 'mesh_segmented_pdu', 'mesh_upper_transport_pdu', 'mesh_network_key', 'mesh_transport_key', 'mesh_virtual_address', 'mesh_subnet']
273]
274
275btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/..')
276file_name = btstack_root + "/src/btstack_memory"
277print ('Generating %s.[h|c]' % file_name)
278
279f = open(file_name+".h", "w")
280writeln(f, copyright)
281writeln(f, hfile_header_begin)
282for struct_names in list_of_structs:
283    writeln(f, "// "+ ", ".join(struct_names))
284    for struct_name in struct_names:
285        writeln(f, replacePlaceholder(header_template, struct_name))
286    writeln(f, "")
287writeln(f, "#ifdef ENABLE_CLASSIC")
288for struct_names in list_of_classic_structs:
289    writeln(f, "// "+ ", ".join(struct_names))
290    for struct_name in struct_names:
291        writeln(f, replacePlaceholder(header_template, struct_name))
292    writeln(f, "")
293writeln(f, "#endif")
294writeln(f, "#ifdef ENABLE_BLE")
295for struct_names in list_of_le_structs:
296    writeln(f, "// "+ ", ".join(struct_names))
297    for struct_name in struct_names:
298        writeln(f, replacePlaceholder(header_template, struct_name))
299writeln(f, "#endif")
300writeln(f, "#ifdef ENABLE_MESH")
301for struct_names in list_of_mesh_structs:
302    writeln(f, "// "+ ", ".join(struct_names))
303    for struct_name in struct_names:
304        writeln(f, replacePlaceholder(header_template, struct_name))
305writeln(f, "#endif")
306writeln(f, hfile_header_end)
307f.close();
308
309
310f = open(file_name+".c", "w")
311writeln(f, copyright)
312writeln(f, cfile_header_begin)
313for struct_names in list_of_structs:
314    for struct_name in struct_names:
315        writeln(f, replacePlaceholder(code_template, struct_name))
316    writeln(f, "")
317writeln(f, "#ifdef ENABLE_CLASSIC")
318for struct_names in list_of_classic_structs:
319    for struct_name in struct_names:
320        writeln(f, replacePlaceholder(code_template, struct_name))
321    writeln(f, "")
322writeln(f, "#endif")
323writeln(f, "#ifdef ENABLE_BLE")
324for struct_names in list_of_le_structs:
325    for struct_name in struct_names:
326        writeln(f, replacePlaceholder(code_template, struct_name))
327    writeln(f, "")
328writeln(f, "#endif")
329writeln(f, "#ifdef ENABLE_MESH")
330for struct_names in list_of_mesh_structs:
331    for struct_name in struct_names:
332        writeln(f, replacePlaceholder(code_template, struct_name))
333    writeln(f, "")
334writeln(f, "#endif")
335
336
337writeln(f, "// init")
338writeln(f, "void btstack_memory_init(void){")
339for struct_names in list_of_structs:
340    for struct_name in struct_names:
341        writeln(f, replacePlaceholder(init_template, struct_name))
342writeln(f, "#ifdef ENABLE_CLASSIC")
343for struct_names in list_of_classic_structs:
344    for struct_name in struct_names:
345        writeln(f, replacePlaceholder(init_template, struct_name))
346writeln(f, "#endif")
347writeln(f, "#ifdef ENABLE_BLE")
348for struct_names in list_of_le_structs:
349    for struct_name in struct_names:
350        writeln(f, replacePlaceholder(init_template, struct_name))
351writeln(f, "#endif")
352writeln(f, "#ifdef ENABLE_MESH")
353for struct_names in list_of_mesh_structs:
354    for struct_name in struct_names:
355        writeln(f, replacePlaceholder(init_template, struct_name))
356writeln(f, "#endif")
357writeln(f, "}")
358f.close();
359
360