Re: [Mesa-dev] [PATCH v4 1/2] gallium/winsys/kms: Fix possible leak in map/unmap.
Hi Lepton, Please avoid top-posting in mailing lists in the future. It's against the netiquette. On Wed, Mar 14, 2018 at 10:20 AM, Lepton Wuwrote: [Message moved to bottom] > On Tue, Mar 13, 2018 at 8:41 AM, Emil Velikov > wrote: >> On 13 March 2018 at 11:46, Tomasz Figa wrote: >>> On Thu, Mar 8, 2018 at 7:39 AM, Lepton Wu wrote: If user calls map twice for kms_sw_displaytarget, the first mapped buffer could get leaked. Instead of calling mmap every time, just reuse previous mapping. Since user could map same displaytarget with different flags, we have to keep two different pointers, one for rw mapping and one for ro mapping. Change-Id: I65308f0ff2640bd57b2577c6a3469540c9722859 Signed-off-by: Lepton Wu --- .../winsys/sw/kms-dri/kms_dri_sw_winsys.c | 21 --- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c index 22e1c936ac5..7fc40488c2e 100644 --- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c @@ -70,6 +70,7 @@ struct kms_sw_displaytarget uint32_t handle; void *mapped; + void *ro_mapped; int ref_count; struct list_head link; @@ -198,16 +199,19 @@ kms_sw_displaytarget_map(struct sw_winsys *ws, return NULL; prot = (flags == PIPE_TRANSFER_READ) ? PROT_READ : (PROT_READ | PROT_WRITE); - kms_sw_dt->mapped = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, -kms_sw->fd, map_req.offset); - - if (kms_sw_dt->mapped == MAP_FAILED) - return NULL; + void **ptr = (flags == PIPE_TRANSFER_READ) ? _sw_dt->ro_mapped : _sw_dt->mapped; + if (!*ptr) { + void *tmp = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, + kms_sw->fd, map_req.offset); + if (tmp == MAP_FAILED) + return NULL; + *ptr = tmp; + } DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p\n", - kms_sw_dt->handle, kms_sw_dt->size, kms_sw_dt->mapped); + kms_sw_dt->handle, kms_sw_dt->size, *ptr); - return kms_sw_dt->mapped; + return *ptr; } static struct kms_sw_displaytarget * @@ -278,9 +282,12 @@ kms_sw_displaytarget_unmap(struct sw_winsys *ws, struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", kms_sw_dt->handle, kms_sw_dt->mapped); + DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", kms_sw_dt->handle, kms_sw_dt->ro_mapped); munmap(kms_sw_dt->mapped, kms_sw_dt->size); kms_sw_dt->mapped = NULL; + munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size); + kms_sw_dt->ro_mapped = NULL; } >>> >>> If user calls map twice, wouldn't they also call unmap twice? >>> Moreover, wouldn't the pointer be expected to be still valid between >>> first and second unmap? >>> >>> The answer obviously depends on how the API is designed, but i feels >>> really weird being asymmetrical like that. Typically the mapping would >>> be refcounted and maps would have to be balanced with unmaps to free >>> the mapping. >>> >> Valid points. >> >> If you guys prefer we could land 2/2 (multiplane support), since it >> has no dependency of the mapping work. >> And polish out ro/rw mappings (even the leaks) at later stage, as time >> permits? >> >> -Emil > > I am fine to add ref count for map pointer but then the code looks a > little complex: > We already have ref count for display target, and it seems most other > drivers don't have a > ref count for map pointer. (I checked dri_sw_displaytarget_map / > gdi_sw_displaytarget_map/hgl_winsys_displaytarget_map > /xlib_displaytarget_map) > > If you really want a reference count for map pointer, I will add one. > But I am just feeling that introduce some unnecessary complex. > Just want to get confirmation before I begin to write code. Looking at users, I found at least one that it's quite realistic to have two separate maps created and expected to work, because of semantics of pipe->transfer_map() API: https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/softpipe/sp_texture.c#n355 You can see that every time it creates a new, independent pipe_transfer object, which should be expected to be valid until pipe->transfer_unmap() on this particular object is not called. Also, looking at the implementations you mentioned: 1) dri_sw The real buffer is not being mapped. There is a staging buffer allocated with malloc() at display target creation time and data are read-back to it
Re: [Mesa-dev] [PATCH v4 1/2] gallium/winsys/kms: Fix possible leak in map/unmap.
I am fine to add ref count for map pointer but then the code looks a little complex: We already have ref count for display target, and it seems most other drivers don't have a ref count for map pointer. (I checked dri_sw_displaytarget_map / gdi_sw_displaytarget_map/hgl_winsys_displaytarget_map /xlib_displaytarget_map) If you really want a reference count for map pointer, I will add one. But I am just feeling that introduce some unnecessary complex. Just want to get confirmation before I begin to write code. Thanks! On Tue, Mar 13, 2018 at 8:41 AM, Emil Velikovwrote: > On 13 March 2018 at 11:46, Tomasz Figa wrote: >> On Thu, Mar 8, 2018 at 7:39 AM, Lepton Wu wrote: >>> If user calls map twice for kms_sw_displaytarget, the first mapped >>> buffer could get leaked. Instead of calling mmap every time, just >>> reuse previous mapping. Since user could map same displaytarget with >>> different flags, we have to keep two different pointers, one for rw >>> mapping and one for ro mapping. >>> >>> Change-Id: I65308f0ff2640bd57b2577c6a3469540c9722859 >>> Signed-off-by: Lepton Wu >>> --- >>> .../winsys/sw/kms-dri/kms_dri_sw_winsys.c | 21 --- >>> 1 file changed, 14 insertions(+), 7 deletions(-) >>> >>> diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c >>> b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c >>> index 22e1c936ac5..7fc40488c2e 100644 >>> --- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c >>> +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c >>> @@ -70,6 +70,7 @@ struct kms_sw_displaytarget >>> >>> uint32_t handle; >>> void *mapped; >>> + void *ro_mapped; >>> >>> int ref_count; >>> struct list_head link; >>> @@ -198,16 +199,19 @@ kms_sw_displaytarget_map(struct sw_winsys *ws, >>>return NULL; >>> >>> prot = (flags == PIPE_TRANSFER_READ) ? PROT_READ : (PROT_READ | >>> PROT_WRITE); >>> - kms_sw_dt->mapped = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, >>> -kms_sw->fd, map_req.offset); >>> - >>> - if (kms_sw_dt->mapped == MAP_FAILED) >>> - return NULL; >>> + void **ptr = (flags == PIPE_TRANSFER_READ) ? _sw_dt->ro_mapped : >>> _sw_dt->mapped; >>> + if (!*ptr) { >>> + void *tmp = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, >>> + kms_sw->fd, map_req.offset); >>> + if (tmp == MAP_FAILED) >>> + return NULL; >>> + *ptr = tmp; >>> + } >>> >>> DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p\n", >>> - kms_sw_dt->handle, kms_sw_dt->size, kms_sw_dt->mapped); >>> + kms_sw_dt->handle, kms_sw_dt->size, *ptr); >>> >>> - return kms_sw_dt->mapped; >>> + return *ptr; >>> } >>> >>> static struct kms_sw_displaytarget * >>> @@ -278,9 +282,12 @@ kms_sw_displaytarget_unmap(struct sw_winsys *ws, >>> struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); >>> >>> DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", >>> kms_sw_dt->handle, kms_sw_dt->mapped); >>> + DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", >>> kms_sw_dt->handle, kms_sw_dt->ro_mapped); >>> >>> munmap(kms_sw_dt->mapped, kms_sw_dt->size); >>> kms_sw_dt->mapped = NULL; >>> + munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size); >>> + kms_sw_dt->ro_mapped = NULL; >>> } >> >> If user calls map twice, wouldn't they also call unmap twice? >> Moreover, wouldn't the pointer be expected to be still valid between >> first and second unmap? >> >> The answer obviously depends on how the API is designed, but i feels >> really weird being asymmetrical like that. Typically the mapping would >> be refcounted and maps would have to be balanced with unmaps to free >> the mapping. >> > Valid points. > > If you guys prefer we could land 2/2 (multiplane support), since it > has no dependency of the mapping work. > And polish out ro/rw mappings (even the leaks) at later stage, as time > permits? > > -Emil ___ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Re: [Mesa-dev] [PATCH v4 1/2] gallium/winsys/kms: Fix possible leak in map/unmap.
On 13 March 2018 at 11:46, Tomasz Figawrote: > On Thu, Mar 8, 2018 at 7:39 AM, Lepton Wu wrote: >> If user calls map twice for kms_sw_displaytarget, the first mapped >> buffer could get leaked. Instead of calling mmap every time, just >> reuse previous mapping. Since user could map same displaytarget with >> different flags, we have to keep two different pointers, one for rw >> mapping and one for ro mapping. >> >> Change-Id: I65308f0ff2640bd57b2577c6a3469540c9722859 >> Signed-off-by: Lepton Wu >> --- >> .../winsys/sw/kms-dri/kms_dri_sw_winsys.c | 21 --- >> 1 file changed, 14 insertions(+), 7 deletions(-) >> >> diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c >> b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c >> index 22e1c936ac5..7fc40488c2e 100644 >> --- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c >> +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c >> @@ -70,6 +70,7 @@ struct kms_sw_displaytarget >> >> uint32_t handle; >> void *mapped; >> + void *ro_mapped; >> >> int ref_count; >> struct list_head link; >> @@ -198,16 +199,19 @@ kms_sw_displaytarget_map(struct sw_winsys *ws, >>return NULL; >> >> prot = (flags == PIPE_TRANSFER_READ) ? PROT_READ : (PROT_READ | >> PROT_WRITE); >> - kms_sw_dt->mapped = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, >> -kms_sw->fd, map_req.offset); >> - >> - if (kms_sw_dt->mapped == MAP_FAILED) >> - return NULL; >> + void **ptr = (flags == PIPE_TRANSFER_READ) ? _sw_dt->ro_mapped : >> _sw_dt->mapped; >> + if (!*ptr) { >> + void *tmp = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, >> + kms_sw->fd, map_req.offset); >> + if (tmp == MAP_FAILED) >> + return NULL; >> + *ptr = tmp; >> + } >> >> DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p\n", >> - kms_sw_dt->handle, kms_sw_dt->size, kms_sw_dt->mapped); >> + kms_sw_dt->handle, kms_sw_dt->size, *ptr); >> >> - return kms_sw_dt->mapped; >> + return *ptr; >> } >> >> static struct kms_sw_displaytarget * >> @@ -278,9 +282,12 @@ kms_sw_displaytarget_unmap(struct sw_winsys *ws, >> struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); >> >> DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", >> kms_sw_dt->handle, kms_sw_dt->mapped); >> + DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", >> kms_sw_dt->handle, kms_sw_dt->ro_mapped); >> >> munmap(kms_sw_dt->mapped, kms_sw_dt->size); >> kms_sw_dt->mapped = NULL; >> + munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size); >> + kms_sw_dt->ro_mapped = NULL; >> } > > If user calls map twice, wouldn't they also call unmap twice? > Moreover, wouldn't the pointer be expected to be still valid between > first and second unmap? > > The answer obviously depends on how the API is designed, but i feels > really weird being asymmetrical like that. Typically the mapping would > be refcounted and maps would have to be balanced with unmaps to free > the mapping. > Valid points. If you guys prefer we could land 2/2 (multiplane support), since it has no dependency of the mapping work. And polish out ro/rw mappings (even the leaks) at later stage, as time permits? -Emil ___ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Re: [Mesa-dev] [PATCH v4 1/2] gallium/winsys/kms: Fix possible leak in map/unmap.
On Thu, Mar 8, 2018 at 7:39 AM, Lepton Wuwrote: > If user calls map twice for kms_sw_displaytarget, the first mapped > buffer could get leaked. Instead of calling mmap every time, just > reuse previous mapping. Since user could map same displaytarget with > different flags, we have to keep two different pointers, one for rw > mapping and one for ro mapping. > > Change-Id: I65308f0ff2640bd57b2577c6a3469540c9722859 > Signed-off-by: Lepton Wu > --- > .../winsys/sw/kms-dri/kms_dri_sw_winsys.c | 21 --- > 1 file changed, 14 insertions(+), 7 deletions(-) > > diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c > b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c > index 22e1c936ac5..7fc40488c2e 100644 > --- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c > +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c > @@ -70,6 +70,7 @@ struct kms_sw_displaytarget > > uint32_t handle; > void *mapped; > + void *ro_mapped; > > int ref_count; > struct list_head link; > @@ -198,16 +199,19 @@ kms_sw_displaytarget_map(struct sw_winsys *ws, >return NULL; > > prot = (flags == PIPE_TRANSFER_READ) ? PROT_READ : (PROT_READ | > PROT_WRITE); > - kms_sw_dt->mapped = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, > -kms_sw->fd, map_req.offset); > - > - if (kms_sw_dt->mapped == MAP_FAILED) > - return NULL; > + void **ptr = (flags == PIPE_TRANSFER_READ) ? _sw_dt->ro_mapped : > _sw_dt->mapped; > + if (!*ptr) { > + void *tmp = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, > + kms_sw->fd, map_req.offset); > + if (tmp == MAP_FAILED) > + return NULL; > + *ptr = tmp; > + } > > DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p\n", > - kms_sw_dt->handle, kms_sw_dt->size, kms_sw_dt->mapped); > + kms_sw_dt->handle, kms_sw_dt->size, *ptr); > > - return kms_sw_dt->mapped; > + return *ptr; > } > > static struct kms_sw_displaytarget * > @@ -278,9 +282,12 @@ kms_sw_displaytarget_unmap(struct sw_winsys *ws, > struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); > > DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", > kms_sw_dt->handle, kms_sw_dt->mapped); > + DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", > kms_sw_dt->handle, kms_sw_dt->ro_mapped); > > munmap(kms_sw_dt->mapped, kms_sw_dt->size); > kms_sw_dt->mapped = NULL; > + munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size); > + kms_sw_dt->ro_mapped = NULL; > } If user calls map twice, wouldn't they also call unmap twice? Moreover, wouldn't the pointer be expected to be still valid between first and second unmap? The answer obviously depends on how the API is designed, but i feels really weird being asymmetrical like that. Typically the mapping would be refcounted and maps would have to be balanced with unmaps to free the mapping. Best regards, Tomasz ___ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Re: [Mesa-dev] [PATCH v4 1/2] gallium/winsys/kms: Fix possible leak in map/unmap.
On Tue, Mar 13, 2018 at 3:10 AM, Emil Velikovwrote: > On 12 March 2018 at 17:45, Lepton Wu wrote: >> Ping. Any more comments or missing stuff to get this commited into master? >> > As things have changed a bit (the original map/unmap behaviour is > preserved) I was hoping that Tomasz will give it another look. > If he prefers, I could add some revision summary and keep him as reviewer of > v1? Thanks Emil. I'll take a look. Sorry for being late to the party. Best regards, Tomasz ___ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Re: [Mesa-dev] [PATCH v4 1/2] gallium/winsys/kms: Fix possible leak in map/unmap.
On 12 March 2018 at 17:45, Lepton Wuwrote: > Ping. Any more comments or missing stuff to get this commited into master? > As things have changed a bit (the original map/unmap behaviour is preserved) I was hoping that Tomasz will give it another look. If he prefers, I could add some revision summary and keep him as reviewer of v1? Thanks Emil ___ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev
Re: [Mesa-dev] [PATCH v4 1/2] gallium/winsys/kms: Fix possible leak in map/unmap.
Ping. Any more comments or missing stuff to get this commited into master? Thanks. On Wed, Mar 7, 2018 at 2:39 PM, Lepton Wuwrote: > If user calls map twice for kms_sw_displaytarget, the first mapped > buffer could get leaked. Instead of calling mmap every time, just > reuse previous mapping. Since user could map same displaytarget with > different flags, we have to keep two different pointers, one for rw > mapping and one for ro mapping. > > Change-Id: I65308f0ff2640bd57b2577c6a3469540c9722859 > Signed-off-by: Lepton Wu > --- > .../winsys/sw/kms-dri/kms_dri_sw_winsys.c | 21 --- > 1 file changed, 14 insertions(+), 7 deletions(-) > > diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c > b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c > index 22e1c936ac5..7fc40488c2e 100644 > --- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c > +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c > @@ -70,6 +70,7 @@ struct kms_sw_displaytarget > > uint32_t handle; > void *mapped; > + void *ro_mapped; > > int ref_count; > struct list_head link; > @@ -198,16 +199,19 @@ kms_sw_displaytarget_map(struct sw_winsys *ws, >return NULL; > > prot = (flags == PIPE_TRANSFER_READ) ? PROT_READ : (PROT_READ | > PROT_WRITE); > - kms_sw_dt->mapped = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, > -kms_sw->fd, map_req.offset); > - > - if (kms_sw_dt->mapped == MAP_FAILED) > - return NULL; > + void **ptr = (flags == PIPE_TRANSFER_READ) ? _sw_dt->ro_mapped : > _sw_dt->mapped; > + if (!*ptr) { > + void *tmp = mmap(0, kms_sw_dt->size, prot, MAP_SHARED, > + kms_sw->fd, map_req.offset); > + if (tmp == MAP_FAILED) > + return NULL; > + *ptr = tmp; > + } > > DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p\n", > - kms_sw_dt->handle, kms_sw_dt->size, kms_sw_dt->mapped); > + kms_sw_dt->handle, kms_sw_dt->size, *ptr); > > - return kms_sw_dt->mapped; > + return *ptr; > } > > static struct kms_sw_displaytarget * > @@ -278,9 +282,12 @@ kms_sw_displaytarget_unmap(struct sw_winsys *ws, > struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt); > > DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", > kms_sw_dt->handle, kms_sw_dt->mapped); > + DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", > kms_sw_dt->handle, kms_sw_dt->ro_mapped); > > munmap(kms_sw_dt->mapped, kms_sw_dt->size); > kms_sw_dt->mapped = NULL; > + munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size); > + kms_sw_dt->ro_mapped = NULL; > } > > static struct sw_displaytarget * > -- > 2.16.2.395.g2e18187dfd-goog > ___ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev