1#ifndef foopulsememblockhfoo
2#define foopulsememblockhfoo
3
4/***
5  This file is part of PulseAudio.
6
7  Copyright 2004-2006 Lennart Poettering
8  Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
9
10  PulseAudio is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as
12  published by the Free Software Foundation; either version 2.1 of the
13  License, or (at your option) any later version.
14
15  PulseAudio is distributed in the hope that it will be useful, but
16  WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19
20  You should have received a copy of the GNU Lesser General Public
21  License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
22***/
23
24typedef struct pa_memblock pa_memblock;
25
26#include <sys/types.h>
27#include <inttypes.h>
28
29#include <pulse/def.h>
30#include <pulse/xmalloc.h>
31#include <pulsecore/atomic.h>
32#include <pulsecore/memchunk.h>
33#include <pulsecore/mem.h>
34#include <pulsecore/flist.h>
35#include <pulsecore/refcnt.h>
36#include <pulsecore/shm.h>
37#include <pulsecore/memtrap.h>
38
39/* A pa_memblock is a reference counted memory block. PulseAudio
40 * passes references to pa_memblocks around instead of copying
41 * data. See pa_memchunk for a structure that describes parts of
42 * memory blocks. */
43
44/* The type of memory this block points to */
45typedef enum pa_memblock_type {
46    PA_MEMBLOCK_POOL,             /* Memory is part of the memory pool */
47    PA_MEMBLOCK_POOL_EXTERNAL,    /* Data memory is part of the memory pool but the pa_memblock structure itself is not */
48    PA_MEMBLOCK_APPENDED,         /* The data is appended to the memory block */
49    PA_MEMBLOCK_USER,             /* User supplied memory, to be freed with free_cb */
50    PA_MEMBLOCK_FIXED,            /* Data is a pointer to fixed memory that needs not to be freed */
51    PA_MEMBLOCK_IMPORTED,         /* Memory is imported from another process via shm */
52    PA_MEMBLOCK_TYPE_MAX
53} pa_memblock_type_t;
54
55typedef struct pa_mempool pa_mempool;
56typedef struct pa_mempool_stat pa_mempool_stat;
57typedef struct pa_memimport_segment pa_memimport_segment;
58typedef struct pa_memimport pa_memimport;
59typedef struct pa_memexport pa_memexport;
60
61struct pa_memblock {
62    PA_REFCNT_DECLARE; /* the reference counter */
63    pa_mempool *pool;
64
65    pa_memblock_type_t type;
66
67    bool read_only : 1;
68    bool is_silence : 1;
69
70    pa_atomic_ptr_t data;
71    size_t length;
72
73    pa_atomic_t n_acquired;
74    pa_atomic_t please_signal;
75
76    union {
77        struct {
78            /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */
79            pa_free_cb_t free_cb;
80            /* If type == PA_MEMBLOCK_USER this is passed as free_cb argument */
81            void *free_cb_data;
82        } user;
83
84        struct {
85            uint32_t id;
86            pa_memimport_segment *segment;
87        } imported;
88    } per_type;
89};
90
91struct pa_memimport_segment {
92    pa_memimport *import;
93    pa_shm memory;
94    pa_memtrap *trap;
95    unsigned n_blocks;
96    bool writable;
97};
98
99
100typedef void (*pa_memimport_release_cb_t)(pa_memimport *i, uint32_t block_id, void *userdata);
101typedef void (*pa_memexport_revoke_cb_t)(pa_memexport *e, uint32_t block_id, void *userdata);
102
103/* Please note that updates to this structure are not locked,
104 * i.e. n_allocated might be updated at a point in time where
105 * n_accumulated is not yet. Take these values with a grain of salt,
106 * they are here for purely statistical reasons.*/
107struct pa_mempool_stat {
108    pa_atomic_t n_allocated;
109    pa_atomic_t n_accumulated;
110    pa_atomic_t n_imported;
111    pa_atomic_t n_exported;
112    pa_atomic_t allocated_size;
113    pa_atomic_t accumulated_size;
114    pa_atomic_t imported_size;
115    pa_atomic_t exported_size;
116
117    pa_atomic_t n_too_large_for_pool;
118    pa_atomic_t n_pool_full;
119
120    pa_atomic_t n_allocated_by_type[PA_MEMBLOCK_TYPE_MAX];
121    pa_atomic_t n_accumulated_by_type[PA_MEMBLOCK_TYPE_MAX];
122};
123
124/* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL or PA_MEMBLOCK_APPENDED, depending on the size */
125pa_memblock *pa_memblock_new(pa_mempool *, size_t length);
126
127/* Allocate a new memory block of type PA_MEMBLOCK_MEMPOOL. If the requested size is too large, return NULL */
128pa_memblock *pa_memblock_new_pool(pa_mempool *, size_t length);
129
130/* Allocate a new memory block of type PA_MEMBLOCK_USER */
131pa_memblock *pa_memblock_new_user(pa_mempool *, void *data, size_t length, pa_free_cb_t free_cb, void *free_cb_data, bool read_only);
132
133/* A special case of pa_memblock_new_user: take a memory buffer previously allocated with pa_xmalloc()  */
134static inline pa_memblock *pa_memblock_new_malloced(pa_mempool *p, void *data, size_t length) {
135    return pa_memblock_new_user(p, data, length, pa_xfree, data, 0);
136}
137
138/* Allocate a new memory block of type PA_MEMBLOCK_FIXED */
139pa_memblock *pa_memblock_new_fixed(pa_mempool *, void *data, size_t length, bool read_only);
140
141void pa_memblock_unref(pa_memblock*b);
142pa_memblock* pa_memblock_ref(pa_memblock*b);
143
144/* This special unref function has to be called by the owner of the
145memory of a static memory block when they want to release all
146references to the memory. This causes the memory to be copied and
147converted into a pool of malloc'ed memory block. Please note that this
148function is not multiple caller safe, i.e. needs to be locked
149manually if called from more than one thread at the same time. */
150void pa_memblock_unref_fixed(pa_memblock*b);
151
152bool pa_memblock_is_ours(pa_memblock *b);
153bool pa_memblock_is_read_only(pa_memblock *b);
154bool pa_memblock_is_silence(pa_memblock *b);
155bool pa_memblock_ref_is_one(pa_memblock *b);
156void pa_memblock_set_is_silence(pa_memblock *b, bool v);
157
158void* pa_memblock_acquire(pa_memblock *b);
159void *pa_memblock_acquire_chunk(const pa_memchunk *c);
160void pa_memblock_release(pa_memblock *b);
161
162size_t pa_memblock_get_length(pa_memblock *b);
163
164/* Note! Always unref the returned pool after use */
165pa_mempool * pa_memblock_get_pool(pa_memblock *b);
166
167pa_memblock *pa_memblock_will_need(pa_memblock *b);
168
169/* The memory block manager */
170pa_mempool *pa_mempool_new(pa_mem_type_t type, size_t size, bool per_client);
171void pa_mempool_unref(pa_mempool *p);
172pa_mempool* pa_mempool_ref(pa_mempool *p);
173const pa_mempool_stat* pa_mempool_get_stat(pa_mempool *p);
174void pa_mempool_vacuum(pa_mempool *p);
175int pa_mempool_get_shm_id(pa_mempool *p, uint32_t *id);
176bool pa_mempool_is_shared(pa_mempool *p);
177bool pa_mempool_is_memfd_backed(const pa_mempool *p);
178bool pa_mempool_is_global(pa_mempool *p);
179bool pa_mempool_is_per_client(pa_mempool *p);
180bool pa_mempool_is_remote_writable(pa_mempool *p);
181void pa_mempool_set_is_remote_writable(pa_mempool *p, bool writable);
182size_t pa_mempool_block_size_max(pa_mempool *p);
183
184int pa_mempool_take_memfd_fd(pa_mempool *p);
185int pa_mempool_get_memfd_fd(pa_mempool *p);
186
187/* For receiving blocks from other nodes */
188pa_memimport* pa_memimport_new(pa_mempool *p, pa_memimport_release_cb_t cb, void *userdata);
189void pa_memimport_free(pa_memimport *i);
190int pa_memimport_attach_memfd(pa_memimport *i, uint32_t shm_id, int memfd_fd, bool writable);
191pa_memblock* pa_memimport_get(pa_memimport *i, pa_mem_type_t type, uint32_t block_id,
192                              uint32_t shm_id, size_t offset, size_t size, bool writable);
193int pa_memimport_process_revoke(pa_memimport *i, uint32_t block_id);
194
195/* For sending blocks to other nodes */
196pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void *userdata);
197void pa_memexport_free(pa_memexport *e);
198int pa_memexport_put(pa_memexport *e, pa_memblock *b, pa_mem_type_t *type, uint32_t *block_id,
199                     uint32_t *shm_id, size_t *offset, size_t * size);
200int pa_memexport_process_release(pa_memexport *e, uint32_t id);
201
202#endif
203