From bebd991daf957d245d510afc019a212fb9140ac2 Mon Sep 17 00:00:00 2001 From: Minwoo Im Date: Tue, 24 Dec 2024 09:21:44 +0900 Subject: [PATCH] iommu: convert mutex to rwlock for @map->lock The mapping table managed for IOMMU page table is a skiplist protected by mutex with @map->lock. This has led performance impact with multiple threads looking up the page table at the same time, especially when manipulating PRP or SGL data structures per I/O. Application might optimize their own IOMMU-related paths like they prepare the bulk of memory buffers at the beginning time and map them to IOMMU at that time. After that, they can do I/Os based on pre-mapped memory buffers without inserting or deleting entries from page tables. To improve performance scalability, convert existing mutex @map->lock to read-write lock which leads to great performance on read(look-up)-most scenarios. Signed-off-by: Minwoo Im --- src/iommu/context.c | 2 +- src/iommu/context.h | 2 +- src/iommu/dma.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/iommu/context.c b/src/iommu/context.c index a77a48c..3796434 100644 --- a/src/iommu/context.c +++ b/src/iommu/context.c @@ -84,5 +84,5 @@ void iommu_ctx_init(struct iommu_ctx *ctx) pthread_mutex_init(&ctx->lock, NULL); skiplist_init(&ctx->map.list); - pthread_mutex_init(&ctx->map.lock, NULL); + pthread_rwlock_init(&ctx->map.lock, NULL); } diff --git a/src/iommu/context.h b/src/iommu/context.h index ef2cfee..57c9181 100644 --- a/src/iommu/context.h +++ b/src/iommu/context.h @@ -40,7 +40,7 @@ struct iova_mapping { }; struct iova_map { - pthread_mutex_t lock; + pthread_rwlock_t lock; struct skiplist list; }; diff --git a/src/iommu/dma.c b/src/iommu/dma.c index f836588..7ab4d47 100644 --- a/src/iommu/dma.c +++ b/src/iommu/dma.c @@ -41,7 +41,7 @@ static int iova_cmp(const void *vaddr, const struct skiplist_node *n) static int iova_map_add(struct iova_map *map, void *vaddr, size_t len, uint64_t iova, unsigned long flags) { - __autolock(&map->lock); + __autowrlock(&map->lock); struct skiplist_node *update[SKIPLIST_LEVELS] = {}; struct iova_mapping *m; @@ -70,7 +70,7 @@ static int iova_map_add(struct iova_map *map, void *vaddr, size_t len, uint64_t static void iova_map_remove(struct iova_map *map, void *vaddr) { - __autolock(&map->lock); + __autowrlock(&map->lock); struct skiplist_node *n, *update[SKIPLIST_LEVELS] = {}; @@ -83,7 +83,7 @@ static void iova_map_remove(struct iova_map *map, void *vaddr) static struct iova_mapping *iova_map_find(struct iova_map *map, void *vaddr) { - __autolock(&map->lock); + __autordlock(&map->lock); return container_of_or_null(skiplist_find(&map->list, vaddr, iova_cmp, NULL), struct iova_mapping, list); @@ -91,7 +91,7 @@ static struct iova_mapping *iova_map_find(struct iova_map *map, void *vaddr) static void iova_map_clear_with(struct iova_map *map, skiplist_iter_fn fn, void *opaque) { - __autolock(&map->lock); + __autowrlock(&map->lock); skiplist_clear_with(&map->list, fn, opaque); }