mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	remote: improve mapped memory tracking
This commit is contained in:
		
							parent
							
								
									008df86c8f
								
							
						
					
					
						commit
						c9fb320987
					
				
					 1 changed files with 38 additions and 32 deletions
				
			
		| 
						 | 
					@ -48,19 +48,23 @@ struct remote {
 | 
				
			||||||
	struct spa_hook core_listener;
 | 
						struct spa_hook core_listener;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct mapping {
 | 
				
			||||||
 | 
						void *ptr;
 | 
				
			||||||
 | 
						struct pw_map_range map;
 | 
				
			||||||
 | 
						int prot;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct mem {
 | 
					struct mem {
 | 
				
			||||||
	uint32_t id;
 | 
						uint32_t id;
 | 
				
			||||||
	int fd;
 | 
						int fd;
 | 
				
			||||||
	uint32_t flags;
 | 
						uint32_t flags;
 | 
				
			||||||
	uint32_t ref;
 | 
						uint32_t ref;
 | 
				
			||||||
	struct pw_map_range map;
 | 
						struct mapping map;
 | 
				
			||||||
	void *ptr;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct buffer_mem {
 | 
					struct buffer_mem {
 | 
				
			||||||
	void *ptr;
 | 
					 | 
				
			||||||
	struct pw_map_range map;
 | 
					 | 
				
			||||||
	uint32_t mem_id;
 | 
						uint32_t mem_id;
 | 
				
			||||||
 | 
						struct mapping map;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct buffer {
 | 
					struct buffer {
 | 
				
			||||||
| 
						 | 
					@ -539,25 +543,29 @@ static struct mem *find_mem_ptr(struct node_data *data, void *ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct mem *m;
 | 
						struct mem *m;
 | 
				
			||||||
	pw_array_for_each(m, &data->mems) {
 | 
						pw_array_for_each(m, &data->mems) {
 | 
				
			||||||
		if (m->ptr == ptr)
 | 
							if (m->map.ptr == ptr)
 | 
				
			||||||
			return m;
 | 
								return m;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *mem_map(struct node_data *data, struct pw_map_range *range,
 | 
					static void *mem_map(struct node_data *data, struct mapping *map,
 | 
				
			||||||
		int fd, int prot, uint32_t offset, uint32_t size)
 | 
							int fd, int prot, uint32_t offset, uint32_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct mapping m;
 | 
				
			||||||
	void *ptr;
 | 
						void *ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_map_range_init(range, offset, size, data->core->sc_pagesize);
 | 
						pw_map_range_init(&m.map, offset, size, data->core->sc_pagesize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ptr = mmap(NULL, range->size, prot, MAP_SHARED, fd, range->offset);
 | 
						if (map->ptr == NULL || map->map.offset != m.map.offset || map->map.size != m.map.size) {
 | 
				
			||||||
	if (ptr == MAP_FAILED) {
 | 
							map->ptr = mmap(map->ptr, m.map.size, prot, MAP_SHARED, fd, m.map.offset);
 | 
				
			||||||
 | 
							if (map->ptr == MAP_FAILED) {
 | 
				
			||||||
			pw_log_error("remote %p: Failed to mmap memory %d: %m", data, size);
 | 
								pw_log_error("remote %p: Failed to mmap memory %d: %m", data, size);
 | 
				
			||||||
			return NULL;
 | 
								return NULL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	ptr = SPA_MEMBER(ptr, range->start, void);
 | 
							map->map = m.map;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ptr = SPA_MEMBER(map->ptr, map->map.start, void);
 | 
				
			||||||
	pw_log_debug("remote %p: fd %d mapped %d %d %p", data, fd, offset, size, ptr);
 | 
						pw_log_debug("remote %p: fd %d mapped %d %d %p", data, fd, offset, size, ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ptr;
 | 
						return ptr;
 | 
				
			||||||
| 
						 | 
					@ -592,7 +600,7 @@ static void clear_mem(struct node_data *data, struct mem *m)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (!has_ref) {
 | 
							if (!has_ref) {
 | 
				
			||||||
			m->ptr = mem_unmap(data, m->ptr, &m->map);
 | 
								m->map.ptr = mem_unmap(data, m->map.ptr, &m->map.map);
 | 
				
			||||||
			close(fd);
 | 
								close(fd);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -730,8 +738,8 @@ static void client_node_add_mem(void *object,
 | 
				
			||||||
	m->fd = memfd;
 | 
						m->fd = memfd;
 | 
				
			||||||
	m->flags = flags;
 | 
						m->flags = flags;
 | 
				
			||||||
	m->ref = 0;
 | 
						m->ref = 0;
 | 
				
			||||||
	m->map = PW_MAP_RANGE_INIT;
 | 
						m->map.map = PW_MAP_RANGE_INIT;
 | 
				
			||||||
	m->ptr = NULL;
 | 
						m->map.ptr = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void client_node_transport(void *object, uint32_t node_id,
 | 
					static void client_node_transport(void *object, uint32_t node_id,
 | 
				
			||||||
| 
						 | 
					@ -1006,15 +1014,15 @@ client_node_port_use_buffers(void *object,
 | 
				
			||||||
		bid = pw_array_add(&mix->buffers, sizeof(struct buffer));
 | 
							bid = pw_array_add(&mix->buffers, sizeof(struct buffer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bmem.mem_id = m->id;
 | 
							bmem.mem_id = m->id;
 | 
				
			||||||
		bmem.ptr = mem_map(data, &bmem.map, m->fd, prot,
 | 
							bmem.map.ptr = mem_map(data, &bmem.map, m->fd, prot,
 | 
				
			||||||
				buffers[i].offset, buffers[i].size);
 | 
									buffers[i].offset, buffers[i].size);
 | 
				
			||||||
		if (bmem.ptr == NULL) {
 | 
							if (bmem.map.ptr == NULL) {
 | 
				
			||||||
			res = -errno;
 | 
								res = -errno;
 | 
				
			||||||
			goto cleanup;
 | 
								goto cleanup;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (mlock(bmem.ptr, bmem.map.size) < 0)
 | 
							if (mlock(bmem.map.ptr, bmem.map.map.size) < 0)
 | 
				
			||||||
			pw_log_warn("Failed to mlock memory %u %u: %m",
 | 
								pw_log_warn("Failed to mlock memory %u %u: %m",
 | 
				
			||||||
					bmem.map.offset, bmem.map.size);
 | 
										bmem.map.map.offset, bmem.map.map.size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		size = sizeof(struct spa_buffer);
 | 
							size = sizeof(struct spa_buffer);
 | 
				
			||||||
		size += sizeof(struct buffer_mem);
 | 
							size += sizeof(struct buffer_mem);
 | 
				
			||||||
| 
						 | 
					@ -1048,13 +1056,13 @@ client_node_port_use_buffers(void *object,
 | 
				
			||||||
			pw_log_warn("unexpected id %u found, expected %u", bid->id, len);
 | 
								pw_log_warn("unexpected id %u found, expected %u", bid->id, len);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		pw_log_debug("add buffer %d %d %u %u", m->id,
 | 
							pw_log_debug("add buffer %d %d %u %u", m->id,
 | 
				
			||||||
				bid->id, bmem.map.offset, bmem.map.size);
 | 
									bid->id, bmem.map.map.offset, bmem.map.map.size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		offset = 0;
 | 
							offset = 0;
 | 
				
			||||||
		for (j = 0; j < b->n_metas; j++) {
 | 
							for (j = 0; j < b->n_metas; j++) {
 | 
				
			||||||
			struct spa_meta *m = &b->metas[j];
 | 
								struct spa_meta *m = &b->metas[j];
 | 
				
			||||||
			memcpy(m, &buffers[i].buffer->metas[j], sizeof(struct spa_meta));
 | 
								memcpy(m, &buffers[i].buffer->metas[j], sizeof(struct spa_meta));
 | 
				
			||||||
			m->data = SPA_MEMBER(bmem.ptr, offset, void);
 | 
								m->data = SPA_MEMBER(bmem.map.ptr, offset, void);
 | 
				
			||||||
			offset += m->size;
 | 
								offset += m->size;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1063,7 +1071,7 @@ client_node_port_use_buffers(void *object,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			memcpy(d, &buffers[i].buffer->datas[j], sizeof(struct spa_data));
 | 
								memcpy(d, &buffers[i].buffer->datas[j], sizeof(struct spa_data));
 | 
				
			||||||
			d->chunk =
 | 
								d->chunk =
 | 
				
			||||||
			    SPA_MEMBER(bmem.ptr, offset + sizeof(struct spa_chunk) * j,
 | 
								    SPA_MEMBER(bmem.map.ptr, offset + sizeof(struct spa_chunk) * j,
 | 
				
			||||||
				       struct spa_chunk);
 | 
									       struct spa_chunk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (d->type == t->data.MemFd || d->type == t->data.DmaBuf) {
 | 
								if (d->type == t->data.MemFd || d->type == t->data.DmaBuf) {
 | 
				
			||||||
| 
						 | 
					@ -1080,15 +1088,15 @@ client_node_port_use_buffers(void *object,
 | 
				
			||||||
				d->fd = bm->fd;
 | 
									d->fd = bm->fd;
 | 
				
			||||||
				bm->ref++;
 | 
									bm->ref++;
 | 
				
			||||||
				bm2.mem_id = bm->id;
 | 
									bm2.mem_id = bm->id;
 | 
				
			||||||
				bm2.ptr = NULL;
 | 
									bm2.map.ptr = NULL;
 | 
				
			||||||
				d->data = bm2.ptr;
 | 
									d->data = bm2.map.ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				bid->mem[bid->n_mem++] = bm2;
 | 
									bid->mem[bid->n_mem++] = bm2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				pw_log_debug(" data %d %u -> fd %d", j, bm->id, bm->fd);
 | 
									pw_log_debug(" data %d %u -> fd %d", j, bm->id, bm->fd);
 | 
				
			||||||
			} else if (d->type == t->data.MemPtr) {
 | 
								} else if (d->type == t->data.MemPtr) {
 | 
				
			||||||
				int offs = SPA_PTR_TO_INT(d->data);
 | 
									int offs = SPA_PTR_TO_INT(d->data);
 | 
				
			||||||
				d->data = SPA_MEMBER(bmem.ptr, offs, void);
 | 
									d->data = SPA_MEMBER(bmem.map.ptr, offs, void);
 | 
				
			||||||
				d->fd = -1;
 | 
									d->fd = -1;
 | 
				
			||||||
				pw_log_debug(" data %d %u -> mem %p", j, bid->id, d->data);
 | 
									pw_log_debug(" data %d %u -> mem %p", j, bid->id, d->data);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
| 
						 | 
					@ -1160,14 +1168,12 @@ client_node_port_set_io(void *object,
 | 
				
			||||||
			pw_log_warn("unknown memory id %u", memid);
 | 
								pw_log_warn("unknown memory id %u", memid);
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (m->ptr == NULL) {
 | 
							ptr = mem_map(data, &m->map, m->fd,
 | 
				
			||||||
			m->ptr = mem_map(data, &m->map, m->fd,
 | 
					 | 
				
			||||||
			PROT_READ|PROT_WRITE, offset, size);
 | 
								PROT_READ|PROT_WRITE, offset, size);
 | 
				
			||||||
			if (m->ptr == NULL)
 | 
							if (ptr == NULL)
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		m->ref++;
 | 
							m->ref++;
 | 
				
			||||||
		ptr = m->ptr;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug("port %p: set io %s %p", mix->port,
 | 
						pw_log_debug("port %p: set io %s %p", mix->port,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue