btstackのメモリ管理部分の実装を読みました。
btstackは組込み向けのbluetoothプロトコルスタックです。
btstackは組込み向けのportではメモリプールを使う実装になっています。
ソース
- https://github.com/bluekitchen/btstack
- https://github.com/bluekitchen/btstack/blob/master/src/btstack_memory.c
- https://github.com/bluekitchen/btstack/blob/master/src/btstack_memory.h
- https://github.com/bluekitchen/btstack/blob/master/src/btstack_memory.c
- https://github.com/bluekitchen/btstack/blob/master/src/btstack_memory.h
メモリの初期化 (メモリプールの場合)
- btstack_memory.c の btstack_memory_init()で初期化する。
- btstack_memory_pool_create()で種類毎のメモリプールを作る。
- hci_connection
- l2cap_service
- rfcomm_multiplexer
- rfcomm_service
- rfcomm_channel
- btstack_link_key_db_memory_entry
- bnep_service
- bnep_channel
- hfp_connection
- service_record_item
- gatt_client
- whitelist_entry
- sm_lookup_entry
btstack_memory.c
void btstack_memory_init(void){
# if MAX_NR_HCI_CONNECTIONS > 0
btstack_memory_pool_create(&hci_connection_pool, hci_connection_storage, MAX_NR_HCI_CONNECTIONS, sizeof(hci_connection_t));
...
- storageにブロックサイズblock_sizeバイトのメモリブロックをcount個作成する。メモリプール管理情報はpoolにある。
btstack_memory_pool.c
void btstack_memory_pool_create(btstack_memory_pool_t *pool, void * storage, int count, int block_size){
node_t *free_blocks = (node_t*) pool;
char *mem_ptr = (char *) storage;
int i;
// create singly linked list of all available blocks
free_blocks->next = NULL;
for (i = 0 ; i < count ; i++){
btstack_memory_pool_free(pool, mem_ptr);
mem_ptr += block_size;
}
}
- storageは静的に確保する
btstack_memory.c
static hci_connection_t hci_connection_storage[MAX_NR_HCI_CONNECTIONS];
メモリの確保と解放
コンパイルオプションで3種類ある
- メモリプール 個数1以上
- メモリプール 個数0
- malloc()/free()を利用
メモリの確保と解放 メモリプール 個数1以上
- MAX_NR_HCI_CONNECTIONS > 0 の場合
btstack_memory.c
# ifdef MAX_NR_HCI_CONNECTIONS
# if MAX_NR_HCI_CONNECTIONS > 0
static hci_connection_t hci_connection_storage[MAX_NR_HCI_CONNECTIONS];
static btstack_memory_pool_t hci_connection_pool;
hci_connection_t * btstack_memory_hci_connection_get(void){
return (hci_connection_t *) btstack_memory_pool_get(&hci_connection_pool);
}
void btstack_memory_hci_connection_free(hci_connection_t *hci_connection){
btstack_memory_pool_free(&hci_connection_pool, hci_connection);
}
# else
# endif
# endif
btstack_memory_pool_get
- 空いているメモリブロックを返す。
btstack_memory_pool.c
void * btstack_memory_pool_get(btstack_memory_pool_t *pool){
node_t *free_blocks = (node_t*) pool;
if (!free_blocks->next) return NULL;
// remove first
node_t *node = free_blocks->next;
free_blocks->next = node->next;
return (void*) node;
}
btstack_memory_pool_free
- 二重解放をチェックする
- 空きメモリブロックリストに追加する
btstack_memory_pool.c
void btstack_memory_pool_free(btstack_memory_pool_t *pool, void * block){
node_t *free_blocks = (node_t*) pool;
node_t *node = (node_t*) block;
// raise error and abort if node already in list
node_t * it;
for (it = free_blocks->next; it ; it = it->next){
if (it == node) {
log_error("btstack_memory_pool_free: block %p freed twice for pool %p", block, pool);
return;
}
}
// add block as node to list
node->next = free_blocks->next;
free_blocks->next = node;
}
メモリの確保と解放 メモリプール 個数0
- MAX_NR_HCI_CONNECTIONS == 0 の場合。 どう使うのか不明。
btstack_memory.c
# ifdef MAX_NR_HCI_CONNECTIONS
# if MAX_NR_HCI_CONNECTIONS > 0
# else
hci_connection_t * btstack_memory_hci_connection_get(void){
return NULL;
}
void btstack_memory_hci_connection_free(hci_connection_t *hci_connection){
// silence compiler warning about unused parameter in a portable way
(void) hci_connection;
};
# endif
# endif
メモリの確保と解放 malloc()/free()を利用
- 単純に malloc()とfree() する。
btstack_memory.c
# elif defined(HAVE_MALLOC)
hci_connection_t * btstack_memory_hci_connection_get(void){
return (hci_connection_t*) malloc(sizeof(hci_connection_t));
}
void btstack_memory_hci_connection_free(hci_connection_t *hci_connection){
free(hci_connection);
}
# endif
各portのHCIのメモリ確保の種類
メモリプール (MAX_NR_HCI_CONNECTIONS 1)
- arduino
- ez430-rf2560
- msp430f5229lp-cc2564b
- msp-exp430f5438-cc2564b
- nrf5x
- pic32-harmony
- wiced
- stm32-f103rb-nucleo
malloc (HAVE_MALLOC)
- libusb
- posix-h4
- posix-h5
- ios