<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div class="BodyFragment"><font size="2"><span style="font-size:11pt">
<div class="PlainText">
<blockquote style="border-left: 3px solid rgb(200, 200, 200); border-top-color: rgb(200, 200, 200); border-right-color: rgb(200, 200, 200); border-bottom-color: rgb(200, 200, 200); padding-left: 1ex; margin-left: 0.8ex; color: rgb(102, 102, 102);">
On 05/11/2020 10:13 AM, Jose Fonseca wrote:<br>
> Hi,<br>
> <br>
> To give everybody a bit of background context, this email comes from <br>
> <a href="https://gitlab.freedesktop.org/mesa/mesa/-/issues/2911">https://gitlab.freedesktop.org/mesa/mesa/-/issues/2911</a> .<br>
> <br>
> The short story is that Gallium components (but not Mesa) used to have <br>
> their malloc/free calls intercepted, to satisfy certain needs: 1) memory <br>
> debugging on Windows, 2) memory accounting on embedded systems.  But <br>
> with the unification of Gallium into Mesa, the gallium vs non-gallium <br>
> division got blurred, leading to some mallocs being intercepted but not <br>
> the respective frees, and vice-versa.<br>
> <br>
> <br>
> I admit that trying to intercept mallocs/frees for some components and <br>
> not others is error prone.  We could get this going on again, it's <br>
> doable, but it's possible it would keep come causing troubles, for us or <br>
> others, over and over again.<br>
> <br>
> <br>
> The two needs mentioned above were mostly VMware's needs.  So I've <br>
> reevaluated, and I /think/ that with some trickery we satisfy those two <br>
> needs differently.  (Without wide spread source code changes.)<br>
> <br>
> <br>
> On the other hand, VMware is probably not the only one to have such <br>
> needs.  In fact Vulkan spec added memory callbacks precisely with the <br>
> same use cases as ours, as seen <br>
> <a href="https://www.khronos.org/registry/vulkan/specs/1.2/html/chap10.html#memory-host">
https://www.khronos.org/registry/vulkan/specs/1.2/html/chap10.html#memory-host</a> which
<br>
> states:<br>
> <br>
>     /Vulkan provides applications the opportunity to perform host memory<br>
>     allocations on behalf of the Vulkan implementation. If this feature<br>
>     is not used, the implementation will perform its own memory<br>
>     allocations. Since most memory allocations are off the critical<br>
>     path, this is not meant as a performance feature. *Rather, this can<br>
>     be useful for certain embedded systems, for debugging purposes (e.g.<br>
>     putting a guard page after all host allocations), or for memory<br>
>     allocation logging.*/<br>
> <br>
> <br>
> And I know there were people interested in having Mesa drivers on <br>
> embedded devices on the past (the old Tunsten Graphics having even been <br>
> multiple times hired to do so), and I'm pretty sure they exist again.<br>
> <br>
> <br>
> <br>
> Therefore, rather than shying away from memory allocation abstractions <br>
> now, I wonder if now it's not the time to actually double down on them <br>
> and ensure we do so comprehensively throughout the whole mesa, all drivers?<br>
> *<br>
> *<br>
> After all Mesa traditionally always had MALLOC*/CALLOC*/FREE wrappers <br>
> around malloc/free.  As so many other projects do.<br>
> <br>
> <br>
> <br>
> More concretely, I'd like to propose that we:<br>
> <br>
>   * ensure all components use MALLOC*/CALLOC*/FREE and never<br>
>     malloc/calloc/free directly (unless interfacing with a 3rd party<br>
>     which expects memory to be allocated/freed with malloc/free directly)<br>
>   * Perhaps consider renaming MALLOC -> _mesa_malloc etc while we're at it<br>
>   * introduce a mechanisms to quickly catch any mistaken use of<br>
>     malloc/calloc/free, regardless compiler/OS used:<br>
>       o #define malloc/free/calloc as malloc_do_not_use/free_do_not_use<br>
>         to trigger compilation errors, except on files which explicely<br>
>         opt out of this (source files which need to interface with 3rd<br>
>         party, or source files which implement the callbacks)<br>
>       o Add a cookie to MALLOC/CALLOC/FREE memory to ensure it's not<br>
>         inadvertently mixed with malloc/calloc/free<br>
> <br>
> The end goal is that we should be able to have a memory allocation <br>
> abstraction which can be used for all the needs above: memory debugging, <br>
> memory accounting, and satisfying Vulkan host memory callbacks.<br>
> <br>
> <br>
> Some might retort: why not just play some tricks with the linker, and <br>
> intercept all malloc/free calls, without actually having to modify any <br>
> source code?<br>
> <br>
> Yes, that's indeed technically feasible.  And is precisely the sort of <br>
> trick I was planing to resort to satisfy VMware needs without having to <br>
> further modify the source code.  But for these tricks to work, it is <br>
> absolutely /imperative/ that one statically links C++ library and STL.  <br>
> The problem being that if one doesn't then there's an imbalance: the <br>
> malloc/free/new/delete calls done in inline code on C++ headers will be <br>
> intercepted, where as malloc/free/new/delete calls done in code from the <br>
> shared object which is not inlined will not, causing havoc.  This is OK <br>
> for us VMware (we do it already for many other reasons, including <br>
> avoiding DLL hell.)  But I doubt it will be palatable for everybody <br>
> else, particularly Linux distros, to have everything statically linked.<br>
> <br>
> So effectively, if one really wants to implement Vulkan host memory <br>
> callbacks, the best way is to explicitly use malloc/free abstractions, <br>
> instead of the malloc/free directly.<br>
> <br>
> <br>
> So before we put more time on pursuing either the "all" or "nothing" <br>
> approaches, I'd like to get a feel for where people's preferences are.<br>
> <br>
> Jose<br>
> <br>
<br>
<br>
I was tinkering with this on Friday.  My initial idea is to use an <br>
opt-in approach for memory tracking/debugging.  That is, where we care <br>
about tracking/debugging we use explicit alternates to malloc/free/etc.<br>
<br>
malloc/free/MALLOC/CALLOC_STRUCT/etc are used in thousands of places in <br>
Mesa/gallium and touching all of them seems like a hard way to go - <br>
maybe not so much technical as people just not liking it for various <br>
reasons.<br>
<br>
I prototyped a u_trackmem.h header with u_trackmem_malloc(), functions, <br>
etc.  That header also does "#define malloc dont_call_malloc_here" to <br>
try to prevent use of malloc/free in the .c code.  u_trackmem.h would <br>
typically have to be the last #include in a .c file.<br>
<br>
I think redefining malloc/free in the .h file is better than the -D <br>
compiler option because as soon as we include a .h file which uses <br>
malloc/free we get a big mess.<br>
<br>
u_trackmem.h attached.<br>
<br>
<div>-Brian<br>
</div>
</blockquote>
<div><br>
</div>
<div>Yes, I was leaning towards "all" or "nothing" approaches, but on 2nd thought, I don't see anything wrong with this approach.  A partial solution is always easier to decide, as it doesn't require unanimity.  And the more modules use u_trackmem.h, the more
 we approach the complete coverage. </div>
<div><br>
</div>
<div>The only thing to watch out is that u_trackmem.h makes it difficult to do mallocs/free on header files, but that is virtually never the case on Mesa nowadays, so it should be good.  And even if we want to do it, it should be possible by splitting u_trackmem.h
 in two (where one header doesn't have the #define overrides.)</div>
<div><br>
</div>
<div>Jose</div>
<div><br>
</div>
<div><br>
</div>
</div>
</span></font></div>
</body>
</html>