mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
mem: add a PW_MEMBLOCK_FLAG_MAPPABLE flag and pass it around
This flags means that the fd can be mmaped without special handling. It is the equivalent of the SPA_DATA_FLAG_MAPPABLE. Refuse to map memory that is not mappable. Make sure we make all allocated MemFd memory MAPPABLE by default. We can then remove the stream and filter special handling for MemFd types and just check the more generic MAPPABLE flag. Make one exception when a client uploads MemFd buffer memory. We must manually set the MAPPABLE flag for MemFd to make things backwards compatible.
This commit is contained in:
parent
45984fef77
commit
2f8740dee8
12 changed files with 63 additions and 38 deletions
|
|
@ -858,6 +858,8 @@ do_port_use_buffers(struct impl *impl,
|
|||
{
|
||||
uint32_t flags = PW_MEMBLOCK_FLAG_DONT_CLOSE;
|
||||
|
||||
if (d->flags & SPA_DATA_FLAG_MAPPABLE)
|
||||
flags |= PW_MEMBLOCK_FLAG_MAPPABLE;
|
||||
if (d->flags & SPA_DATA_FLAG_READABLE)
|
||||
flags |= PW_MEMBLOCK_FLAG_READABLE;
|
||||
if (d->flags & SPA_DATA_FLAG_WRITABLE)
|
||||
|
|
@ -1084,16 +1086,27 @@ static int client_node_port_buffers(void *data,
|
|||
for (j = 0; j < b->buffer.n_datas; j++) {
|
||||
struct spa_chunk *oldchunk = oldbuf->datas[j].chunk;
|
||||
struct spa_data *d = &newbuf->datas[j];
|
||||
uint32_t flags = d->flags;
|
||||
|
||||
if (d->type == SPA_DATA_MemFd &&
|
||||
!SPA_FLAG_IS_SET(flags, SPA_DATA_FLAG_MAPPABLE)) {
|
||||
spa_log_debug(impl->log, "buffer:%d data:%d has non mappable MemFd, "
|
||||
"fixing to ensure backwards compatibility.",
|
||||
i, j);
|
||||
flags |= SPA_DATA_FLAG_MAPPABLE;
|
||||
}
|
||||
|
||||
/* overwrite everything except the chunk */
|
||||
oldbuf->datas[j] = *d;
|
||||
oldbuf->datas[j].flags = flags;
|
||||
oldbuf->datas[j].chunk = oldchunk;
|
||||
|
||||
b->datas[j].type = d->type;
|
||||
b->datas[j].flags = flags;
|
||||
b->datas[j].fd = d->fd;
|
||||
|
||||
spa_log_debug(impl->log, " data %d type:%d fl:%08x fd:%d, offs:%d max:%d",
|
||||
j, d->type, d->flags, (int) d->fd, d->mapoffset,
|
||||
j, d->type, flags, (int) d->fd, d->mapoffset,
|
||||
d->maxsize);
|
||||
}
|
||||
}
|
||||
|
|
@ -1342,8 +1355,9 @@ static int add_area(struct impl *impl)
|
|||
|
||||
area = pw_mempool_alloc(impl->context_pool,
|
||||
PW_MEMBLOCK_FLAG_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_MAP |
|
||||
PW_MEMBLOCK_FLAG_SEAL,
|
||||
PW_MEMBLOCK_FLAG_SEAL |
|
||||
PW_MEMBLOCK_FLAG_MAPPABLE |
|
||||
PW_MEMBLOCK_FLAG_MAP,
|
||||
SPA_DATA_MemFd, size);
|
||||
if (area == NULL)
|
||||
return -errno;
|
||||
|
|
|
|||
|
|
@ -701,14 +701,14 @@ client_node_port_use_buffers(void *_data,
|
|||
d->type = bm->type;
|
||||
d->data = NULL;
|
||||
|
||||
pw_log_debug(" data %d %u -> fd %d maxsize %d",
|
||||
j, bm->id, bm->fd, d->maxsize);
|
||||
pw_log_debug(" data %d %u -> fd %d maxsize %d flags:%08x",
|
||||
j, bm->id, bm->fd, d->maxsize, d->flags);
|
||||
} else if (d->type == SPA_DATA_MemPtr) {
|
||||
int offs = SPA_PTR_TO_INT(d->data);
|
||||
d->data = SPA_PTROFF(mm->ptr, offs, void);
|
||||
d->fd = -1;
|
||||
pw_log_debug(" data %d id:%u -> mem:%p offs:%d maxsize:%d",
|
||||
j, bid->id, d->data, offs, d->maxsize);
|
||||
pw_log_debug(" data %d id:%u -> mem:%p offs:%d maxsize:%d flags:%08x",
|
||||
j, bid->id, d->data, offs, d->maxsize, d->flags);
|
||||
} else {
|
||||
pw_log_warn("unknown buffer data type %d", d->type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -191,8 +191,9 @@ pw_client_node0_transport_new(struct pw_context *context,
|
|||
|
||||
impl->mem = pw_mempool_alloc(pw_context_get_mempool(context),
|
||||
PW_MEMBLOCK_FLAG_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_MAP |
|
||||
PW_MEMBLOCK_FLAG_SEAL,
|
||||
PW_MEMBLOCK_FLAG_SEAL |
|
||||
PW_MEMBLOCK_FLAG_MAPPABLE |
|
||||
PW_MEMBLOCK_FLAG_MAP,
|
||||
SPA_DATA_MemFd, area_get_size(&area));
|
||||
if (impl->mem == NULL) {
|
||||
free(impl);
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ static int alloc_buffers(struct pw_mempool *pool,
|
|||
m = pw_mempool_alloc(pool,
|
||||
PW_MEMBLOCK_FLAG_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_SEAL |
|
||||
PW_MEMBLOCK_FLAG_MAPPABLE |
|
||||
PW_MEMBLOCK_FLAG_MAP,
|
||||
SPA_DATA_MemFd,
|
||||
n_buffers * info.mem_size);
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ int pw_control_add_link(struct pw_control *control, uint32_t cmix,
|
|||
impl->mem = pw_mempool_alloc(control->context->pool,
|
||||
PW_MEMBLOCK_FLAG_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_SEAL |
|
||||
PW_MEMBLOCK_FLAG_MAPPABLE |
|
||||
PW_MEMBLOCK_FLAG_MAP,
|
||||
SPA_DATA_MemFd, size);
|
||||
if (impl->mem == NULL) {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ static void core_event_add_mem(void *data, uint32_t id, uint32_t type, int fd, u
|
|||
struct pw_core *this = data;
|
||||
struct pw_memblock *m;
|
||||
|
||||
pw_log_debug("%p: add mem %u type:%u fd:%d flags:%u", this, id, type, fd, flags);
|
||||
pw_log_debug("%p: add mem %u type:%u fd:%d flags:%08x", this, id, type, fd, flags);
|
||||
|
||||
m = pw_mempool_import(this->pool, flags, type, fd);
|
||||
if (m->id != id) {
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ PW_LOG_TOPIC_EXTERN(log_filter);
|
|||
|
||||
static bool mlock_warned = false;
|
||||
|
||||
static uint32_t mappable_dataTypes = (1<<SPA_DATA_MemFd);
|
||||
|
||||
struct buffer {
|
||||
struct pw_buffer this;
|
||||
uint32_t id;
|
||||
|
|
@ -218,7 +216,7 @@ static void fix_datatype(struct spa_pod *param)
|
|||
pw_log_debug("dataType: %u", dataType);
|
||||
if (dataType & (1u << SPA_DATA_MemPtr)) {
|
||||
SPA_POD_VALUE(struct spa_pod_int, &vals[0]) =
|
||||
dataType | mappable_dataTypes;
|
||||
dataType | (1<<SPA_DATA_MemFd);
|
||||
pw_log_debug("Change dataType: %u -> %u", dataType,
|
||||
SPA_POD_VALUE(struct spa_pod_int, &vals[0]));
|
||||
}
|
||||
|
|
@ -780,8 +778,7 @@ static void clear_buffers(struct port *port)
|
|||
if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_MAPPED)) {
|
||||
for (j = 0; j < b->this.buffer->n_datas; j++) {
|
||||
struct spa_data *d = &b->this.buffer->datas[j];
|
||||
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE) ||
|
||||
(mappable_dataTypes & (1<<d->type)) > 0) {
|
||||
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE)) {
|
||||
pw_log_debug("%p: clear buffer %d mem",
|
||||
impl, b->id);
|
||||
unmap_data(impl, d);
|
||||
|
|
@ -948,8 +945,7 @@ static int impl_port_use_buffers(void *object,
|
|||
if (SPA_FLAG_IS_SET(impl_flags, PW_FILTER_PORT_FLAG_MAP_BUFFERS)) {
|
||||
for (j = 0; j < buffers[i]->n_datas; j++) {
|
||||
struct spa_data *d = &buffers[i]->datas[j];
|
||||
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE) ||
|
||||
(mappable_dataTypes & (1<<d->type)) > 0) {
|
||||
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE)) {
|
||||
if ((res = map_data(impl, d, prot)) < 0)
|
||||
return res;
|
||||
SPA_FLAG_SET(b->flags, BUFFER_FLAG_MAPPED);
|
||||
|
|
@ -959,6 +955,8 @@ static int impl_port_use_buffers(void *object,
|
|||
return -EINVAL;
|
||||
}
|
||||
buf_size += d->maxsize;
|
||||
pw_log_debug("%p: data:%d type:%d flags:%08x size:%d", filter, j,
|
||||
d->type, d->flags, d->maxsize);
|
||||
}
|
||||
|
||||
if (size > 0 && buf_size != size) {
|
||||
|
|
@ -967,7 +965,7 @@ static int impl_port_use_buffers(void *object,
|
|||
} else
|
||||
size = buf_size;
|
||||
}
|
||||
pw_log_debug("%p: got buffer %d %d datas, mapped size %d", filter, i,
|
||||
pw_log_debug("%p: got buffer id:%d datas:%d mapped size %d", filter, i,
|
||||
buffers[i]->n_datas, size);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ static void pool_added(void *data, struct pw_memblock *block)
|
|||
if (client->core_resource) {
|
||||
pw_core_resource_add_mem(client->core_resource,
|
||||
block->id, block->type, block->fd,
|
||||
block->flags & PW_MEMBLOCK_FLAG_READWRITE);
|
||||
block->flags & (PW_MEMBLOCK_FLAG_READWRITE | PW_MEMBLOCK_FLAG_MAPPABLE));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1446,6 +1446,7 @@ struct pw_impl_node *pw_context_create_node(struct pw_context *context,
|
|||
this->activation = pw_mempool_alloc(this->context->pool,
|
||||
PW_MEMBLOCK_FLAG_READWRITE |
|
||||
PW_MEMBLOCK_FLAG_SEAL |
|
||||
PW_MEMBLOCK_FLAG_MAPPABLE |
|
||||
PW_MEMBLOCK_FLAG_MAP,
|
||||
SPA_DATA_MemFd, size);
|
||||
if (this->activation == NULL) {
|
||||
|
|
|
|||
|
|
@ -323,6 +323,11 @@ static struct mapping * memblock_map(struct memblock *b,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!(b->this.flags & PW_MEMBLOCK_FLAG_MAPPABLE)) {
|
||||
pw_log_error("%p: block:%p can't be mmaped", p, &b->this);
|
||||
errno = EPERM;
|
||||
return NULL;
|
||||
}
|
||||
if (b->this.fd == -1) {
|
||||
pw_log_error("%p: block:%p cannot map memory with stale fd", p, b);
|
||||
errno = EINVAL;
|
||||
|
|
@ -349,8 +354,8 @@ static struct mapping * memblock_map(struct memblock *b,
|
|||
b->this.ref++;
|
||||
spa_list_append(&b->mappings, &m->link);
|
||||
|
||||
pw_log_debug("%p: block:%p fd:%d map:%p ptr:%p (%u %u) block-ref:%d", p, &b->this,
|
||||
b->this.fd, m, m->ptr, offset, size, b->this.ref);
|
||||
pw_log_debug("%p: block:%p fd:%d flags:%08x map:%p ptr:%p (%u %u) block-ref:%d", p, &b->this,
|
||||
b->this.fd, b->this.flags, m, m->ptr, offset, size, b->this.ref);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
|
@ -435,8 +440,8 @@ struct pw_memmap * pw_memblock_map(struct pw_memblock *block,
|
|||
mm->this.size = size;
|
||||
mm->this.ptr = SPA_PTROFF(m->ptr, range.start, void);
|
||||
|
||||
pw_log_debug("%p: map:%p block:%p fd:%d ptr:%p (%u %u) mapping:%p ref:%d", p,
|
||||
&mm->this, b, b->this.fd, mm->this.ptr, offset, size, m, m->ref);
|
||||
pw_log_debug("%p: map:%p block:%p fd:%d flags:%08x ptr:%p (%u %u) mapping:%p ref:%d", p,
|
||||
&mm->this, b, b->this.fd, b->this.flags, mm->this.ptr, offset, size, m, m->ref);
|
||||
|
||||
if (tag) {
|
||||
memcpy(mm->this.tag, tag, sizeof(mm->this.tag));
|
||||
|
|
@ -524,6 +529,12 @@ struct pw_memblock * pw_mempool_alloc(struct pw_mempool *pool, enum pw_memblock_
|
|||
if (b == NULL)
|
||||
return NULL;
|
||||
|
||||
if (type != SPA_DATA_MemFd) {
|
||||
res = -ENOTSUP;
|
||||
pw_log_error("%p: alloc failure: only MemFd is supported", pool);
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
b->this.ref = 1;
|
||||
b->this.pool = pool;
|
||||
b->this.flags = flags;
|
||||
|
|
@ -594,8 +605,8 @@ struct pw_memblock * pw_mempool_alloc(struct pw_mempool *pool, enum pw_memblock_
|
|||
|
||||
b->this.id = pw_map_insert_new(&impl->map, b);
|
||||
spa_list_append(&impl->blocks, &b->link);
|
||||
pw_log_debug("%p: block:%p id:%d type:%u size:%zu", pool,
|
||||
&b->this, b->this.id, type, size);
|
||||
pw_log_debug("%p: block:%p id:%d type:%u flags:%08x size:%zu", pool,
|
||||
&b->this, b->this.id, type, flags, size);
|
||||
|
||||
if (!SPA_FLAG_IS_SET(flags, PW_MEMBLOCK_FLAG_DONT_NOTIFY))
|
||||
pw_mempool_emit_added(impl, &b->this);
|
||||
|
|
@ -665,7 +676,7 @@ struct pw_memblock * pw_mempool_import(struct pw_mempool *pool,
|
|||
spa_list_append(&impl->blocks, &b->link);
|
||||
|
||||
pw_log_debug("%p: block:%p id:%u flags:%08x type:%u fd:%d",
|
||||
pool, b, b->this.id, flags, type, fd);
|
||||
pool, &b->this, b->this.id, flags, type, fd);
|
||||
|
||||
if (!SPA_FLAG_IS_SET(flags, PW_MEMBLOCK_FLAG_DONT_NOTIFY))
|
||||
pw_mempool_emit_added(impl, &b->this);
|
||||
|
|
@ -701,15 +712,15 @@ struct pw_memblock * pw_mempool_import_block(struct pw_mempool *pool,
|
|||
struct pw_memblock *block;
|
||||
struct memblock *b;
|
||||
|
||||
pw_log_debug("%p: import block:%p type:%d fd:%d", pool,
|
||||
mem, mem->type, mem->fd);
|
||||
|
||||
block = pw_mempool_import(pool,
|
||||
mem->flags | PW_MEMBLOCK_FLAG_DONT_CLOSE,
|
||||
mem->type, mem->fd);
|
||||
if (!block)
|
||||
return NULL;
|
||||
|
||||
pw_log_debug("%p: import block:%p flags:%08x type:%d fd:%d as %p", pool,
|
||||
mem, mem->flags, mem->type, mem->fd, block);
|
||||
|
||||
b = SPA_CONTAINER_OF(block, struct memblock, this);
|
||||
if (!b->owner) {
|
||||
struct memblock *bmem = SPA_CONTAINER_OF(mem, struct memblock, this);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ enum pw_memblock_flags {
|
|||
PW_MEMBLOCK_FLAG_MAP = (1 << 3), /**< mmap the fd */
|
||||
PW_MEMBLOCK_FLAG_DONT_CLOSE = (1 << 4), /**< don't close fd */
|
||||
PW_MEMBLOCK_FLAG_DONT_NOTIFY = (1 << 5), /**< don't notify events */
|
||||
PW_MEMBLOCK_FLAG_MAPPABLE = (1 << 6), /**< the fd can be mmapped */
|
||||
|
||||
PW_MEMBLOCK_FLAG_READWRITE = PW_MEMBLOCK_FLAG_READABLE | PW_MEMBLOCK_FLAG_WRITABLE,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@ PW_LOG_TOPIC_EXTERN(log_stream);
|
|||
|
||||
static bool mlock_warned = false;
|
||||
|
||||
static uint32_t mappable_dataTypes = (1<<SPA_DATA_MemFd);
|
||||
|
||||
struct buffer {
|
||||
struct pw_buffer this;
|
||||
uint32_t id;
|
||||
|
|
@ -222,7 +220,7 @@ static void fix_datatype(struct spa_pod *param)
|
|||
pw_log_debug("dataType: %u", dataType);
|
||||
if (dataType & (1u << SPA_DATA_MemPtr)) {
|
||||
SPA_POD_VALUE(struct spa_pod_int, &vals[0]) =
|
||||
dataType | mappable_dataTypes;
|
||||
dataType | (1<<SPA_DATA_MemFd);
|
||||
pw_log_debug("Change dataType: %u -> %u", dataType,
|
||||
SPA_POD_VALUE(struct spa_pod_int, &vals[0]));
|
||||
}
|
||||
|
|
@ -865,8 +863,7 @@ static void clear_buffers(struct pw_stream *stream)
|
|||
if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_MAPPED)) {
|
||||
for (j = 0; j < b->this.buffer->n_datas; j++) {
|
||||
struct spa_data *d = &b->this.buffer->datas[j];
|
||||
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE) ||
|
||||
(mappable_dataTypes & (1<<d->type)) > 0) {
|
||||
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE)) {
|
||||
pw_log_debug("%p: clear buffer %d mem",
|
||||
stream, b->id);
|
||||
unmap_data(impl, d);
|
||||
|
|
@ -1000,8 +997,7 @@ static int impl_port_use_buffers(void *object,
|
|||
if (SPA_FLAG_IS_SET(impl_flags, PW_STREAM_FLAG_MAP_BUFFERS)) {
|
||||
for (j = 0; j < buffers[i]->n_datas; j++) {
|
||||
struct spa_data *d = &buffers[i]->datas[j];
|
||||
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE) ||
|
||||
(mappable_dataTypes & (1<<d->type)) > 0) {
|
||||
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE)) {
|
||||
if ((res = map_data(impl, d, prot)) < 0)
|
||||
return res;
|
||||
SPA_FLAG_SET(b->flags, BUFFER_FLAG_MAPPED);
|
||||
|
|
@ -1011,15 +1007,16 @@ static int impl_port_use_buffers(void *object,
|
|||
return -EINVAL;
|
||||
}
|
||||
buf_size += d->maxsize;
|
||||
pw_log_debug("%p: data:%d type:%d flags:%08x size:%d", stream, j,
|
||||
d->type, d->flags, d->maxsize);
|
||||
}
|
||||
|
||||
if (size > 0 && buf_size != size) {
|
||||
pw_log_error("%p: invalid buffer size %d", stream, buf_size);
|
||||
return -EINVAL;
|
||||
} else
|
||||
size = buf_size;
|
||||
}
|
||||
pw_log_debug("%p: got buffer id:%d datas:%d, mapped size %d", stream, i,
|
||||
pw_log_debug("%p: got buffer id:%d datas:%d mapped size %d", stream, i,
|
||||
buffers[i]->n_datas, size);
|
||||
}
|
||||
impl->n_buffers = n_buffers;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue