From e8f66ef1977ff0bb8cbfedab80ec8ca3f27fdb30 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 27 Oct 2025 01:25:35 -0700 Subject: [PATCH] llvmpipe: refactor dmabuf and opaque fd handling This change: 1. add new helpers to handle dmabuf alloc/import/free 2. use FREE to match with alloc macro 3. simplify opaque fd code path Reviewed-by: Christian Gmeiner Part-of: --- src/gallium/drivers/llvmpipe/lp_texture.c | 238 ++++++++++++---------- 1 file changed, 125 insertions(+), 113 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index be44a89f486..1289ec39991 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -1383,64 +1383,104 @@ llvmpipe_free_memory(struct pipe_screen *pscreen, #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H) -static void* -llvmpipe_resource_alloc_udmabuf(struct llvmpipe_screen *screen, - struct llvmpipe_memory_allocation *alloc, - size_t size) +static void +llvmpipe_dmabuf_free(struct llvmpipe_memory_allocation *alloc) +{ + assert(alloc->cpu_addr != NULL && alloc->fd >= 0); + munmap(alloc->cpu_addr, alloc->size); + close(alloc->fd); + if (alloc->mem_fd >= 0) + close(alloc->mem_fd); +} + +static bool +llvmpipe_dmabuf_import(int fd, struct llvmpipe_memory_allocation *alloc) +{ + const off_t size = lseek(fd, 0, SEEK_END); + if (size < 0) + return false; + + lseek(fd, 0, SEEK_SET); + + void *cpu_addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (cpu_addr == MAP_FAILED) + return false; + + *alloc = (struct llvmpipe_memory_allocation){ + .fd = fd, + .offset = 0, + .cpu_addr = cpu_addr, + .size = size, + .type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF, + .mem_fd = -1, + }; + + return true; +} + +static bool +llvmpipe_dmabuf_alloc(struct llvmpipe_screen *screen, + size_t size, + struct llvmpipe_memory_allocation *alloc) { int mem_fd = -1; int dmabuf_fd = -1; - if (screen->udmabuf_fd != -1) { - uint64_t alignment; - if (!os_get_page_size(&alignment)) - alignment = 256; - size = align(size, alignment); + if (screen->udmabuf_fd < 0) + return false; - mem_fd = memfd_create("lp_dma_buf", MFD_ALLOW_SEALING); - if (mem_fd == -1) - goto fail; + uint64_t alignment; + if (!os_get_page_size(&alignment)) + alignment = 256; - int res = ftruncate(mem_fd, size); - if (res == -1) - goto fail; + size = align(size, alignment); - /* udmabuf create requires that the memfd have - * have the F_SEAL_SHRINK seal added and must not - * have the F_SEAL_WRITE seal added */ - if (fcntl(mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0) - goto fail; + mem_fd = memfd_create("lp_dma_buf", MFD_ALLOW_SEALING); + if (mem_fd < 0) + goto fail; - struct udmabuf_create create = { - .memfd = mem_fd, - .flags = UDMABUF_FLAGS_CLOEXEC, - .offset = 0, - .size = size - }; + if (ftruncate(mem_fd, size) < 0) + goto fail; - dmabuf_fd = ioctl(screen->udmabuf_fd, UDMABUF_CREATE, &create); - if (dmabuf_fd < 0) - goto fail; + /* udmabuf create requires that the memfd have have the F_SEAL_SHRINK seal + * added and must not have the F_SEAL_WRITE seal added + */ + if (fcntl(mem_fd, F_ADD_SEALS, F_SEAL_SHRINK) < 0) + goto fail; - struct pipe_memory_allocation *data = - mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, 0); - if (data == MAP_FAILED) - goto fail; + struct udmabuf_create create = { + .memfd = mem_fd, + .flags = UDMABUF_FLAGS_CLOEXEC, + .offset = 0, + .size = size + }; - alloc->mem_fd = mem_fd; - alloc->fd = dmabuf_fd; - alloc->size = size; - return data; - } + dmabuf_fd = ioctl(screen->udmabuf_fd, UDMABUF_CREATE, &create); + if (dmabuf_fd < 0) + goto fail; + + void *cpu_addr = + mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, mem_fd, 0); + if (cpu_addr == MAP_FAILED) + goto fail; + + *alloc = (struct llvmpipe_memory_allocation){ + .fd = dmabuf_fd, + .offset = 0, + .cpu_addr = cpu_addr, + .size = size, + .type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF, + .mem_fd = mem_fd, + }; + + return true; fail: if (dmabuf_fd >= 0) close(dmabuf_fd); - if (mem_fd != -1) + if (mem_fd >= 0) close(mem_fd); - /* If we don't have access to the udmabuf device - * or something else fails we return NULL */ - return NULL; + return false; } #endif @@ -1448,56 +1488,53 @@ fail: static struct pipe_memory_allocation * llvmpipe_allocate_memory_fd(struct pipe_screen *pscreen, uint64_t size, - int *fd, + int *out_fd, bool dmabuf) { struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation); if (!alloc) - goto fail; + return NULL; - alloc->mem_fd = -1; - alloc->fd = -1; + int fd = -1; #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H) if (dmabuf) { struct llvmpipe_screen *screen = llvmpipe_screen(pscreen); - alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF; - alloc->cpu_addr = llvmpipe_resource_alloc_udmabuf(screen, alloc, size); + if (!llvmpipe_dmabuf_alloc(screen, size, alloc)) + goto fail; - if (alloc->cpu_addr) { - *fd = os_dupfd_cloexec(alloc->fd); - if (*fd < 0) { - close(alloc->mem_fd); - close(alloc->fd); - FREE(alloc); - goto fail; - } + fd = os_dupfd_cloexec(alloc->fd); + if (fd < 0) { + llvmpipe_dmabuf_free(alloc); + goto fail; } } else #endif { - alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE; - uint64_t alignment; - if (!os_get_page_size(&alignment)) - alignment = 256; - alloc->cpu_addr = os_malloc_aligned_fd(size, alignment, fd, + uint64_t alignment = 256; + os_get_page_size(&alignment); + alloc->cpu_addr = os_malloc_aligned_fd(size, alignment, &fd, "llvmpipe memory fd", driver_id); + if (!alloc->cpu_addr) + goto fail; + + alloc->fd = -1; + alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE; } - if(alloc && !alloc->cpu_addr) { - free(alloc); - alloc = NULL; - } + *out_fd = fd; + return (struct pipe_memory_allocation*)alloc; fail: - return (struct pipe_memory_allocation*)alloc; + FREE(alloc); + return NULL; } static bool llvmpipe_import_memory_fd(struct pipe_screen *screen, int fd, - struct pipe_memory_allocation **ptr, - uint64_t *size, + struct pipe_memory_allocation **out_ptr, + uint64_t *out_size, bool dmabuf) { struct llvmpipe_memory_allocation *alloc = CALLOC_STRUCT(llvmpipe_memory_allocation); @@ -1508,52 +1545,31 @@ llvmpipe_import_memory_fd(struct pipe_screen *screen, alloc->fd = -1; #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H) if (dmabuf) { - off_t mmap_size = lseek(fd, 0, SEEK_END); - if (mmap_size < 0) { - free(alloc); - *ptr = NULL; - return false; + int dup_fd = os_dupfd_cloexec(fd); + if (dup_fd < 0) + goto fail; + + if (!llvmpipe_dmabuf_import(dup_fd, alloc)) { + close(dup_fd); + goto fail; } - - lseek(fd, 0, SEEK_SET); - void *cpu_addr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (cpu_addr == MAP_FAILED) { - free(alloc); - *ptr = NULL; - return false; - } - - alloc->type = LLVMPIPE_MEMORY_FD_TYPE_DMA_BUF; - alloc->cpu_addr = cpu_addr; - alloc->size = mmap_size; - alloc->fd = os_dupfd_cloexec(fd); - if (alloc->fd < 0) { - munmap(alloc->cpu_addr, alloc->size); - free(alloc); - *ptr = NULL; - return false; - } - - *ptr = (struct pipe_memory_allocation*)alloc; - *size = mmap_size; - - return true; } else #endif { - bool ret = os_import_memory_fd(fd, (void**)&alloc->cpu_addr, size, driver_id); - - if (!ret) { - free(alloc); - *ptr = NULL; - return false; - } else { - *ptr = (struct pipe_memory_allocation*)alloc; - } + if (!os_import_memory_fd(fd, &alloc->cpu_addr, &alloc->size, driver_id)) + goto fail; + alloc->fd = -1; alloc->type = LLVMPIPE_MEMORY_FD_TYPE_OPAQUE; - return ret; } + + *out_ptr = (struct pipe_memory_allocation*)alloc; + *out_size = alloc->size; + return true; + +fail: + FREE(alloc); + return false; } @@ -1567,15 +1583,11 @@ llvmpipe_free_memory_fd(struct pipe_screen *screen, } #if defined(HAVE_LIBDRM) && defined(HAVE_LINUX_UDMABUF_H) else { - munmap(alloc->cpu_addr, alloc->size); - if (alloc->fd >= 0) - close(alloc->fd); - if (alloc->mem_fd >= 0) - close(alloc->mem_fd); + llvmpipe_dmabuf_free(alloc); } #endif - free(alloc); + FREE(alloc); } #endif