1
0
mirror of https://github.com/TREX-CoE/qmckl.git synced 2025-05-01 04:44:49 +02:00
qmckl/qmckl_memory.html

651 lines
31 KiB
HTML

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2025-04-29 Tue 08:44 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Memory management</title>
<meta name="author" content="TREX CoE" />
<meta name="generator" content="Org Mode" />
<style>
#content { max-width: 60em; margin: auto; }
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #f2f2f2;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: auto;
}
pre.src:before {
display: none;
position: absolute;
top: -8px;
right: 12px;
padding: 3px;
color: #555;
background-color: #f2f2f299;
}
pre.src:hover:before { display: inline; margin-top: 14px;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-authinfo::before { content: 'Authinfo'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'Javascript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { }
</style>
<link rel="stylesheet" title="Standard" href="qmckl.css" type="text/css" />
<script src="org-info.js">
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&amp;dn=gpl-3.0.txt GPL-v3-or-Later
// @license-end
</script>
<script>
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&amp;dn=gpl-3.0.txt GPL-v3-or-Later
org_html_manager.set("TOC_DEPTH", "4");
org_html_manager.set("LINK_HOME", "index.html");
org_html_manager.set("LINK_UP", "");
org_html_manager.set("LOCAL_TOC", "1");
org_html_manager.set("VIEW_BUTTONS", "0");
org_html_manager.set("MOUSE_HINT", "underline");
org_html_manager.set("FIXED_TOC", "0");
org_html_manager.set("TOC", "1");
org_html_manager.set("VIEW", "info");
org_html_manager.setup(); // activate after the parameters are set
// @license-end
</script>
</head>
<body>
<div id="org-div-home-and-up">
<a accesskey="h" href=""> UP </a>
|
<a accesskey="H" href="index.html"> HOME </a>
</div><div id="content" class="content">
<h1 class="title">Memory management</h1>
<div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2>
<div id="text-table-of-contents" role="doc-toc">
<ul>
<li><a href="#org31a118b">1. Memory data structure for the context</a></li>
<li><a href="#orgc52927f">2. Passing info to allocation routines</a></li>
<li><a href="#org435db54">3. Allocation/deallocation functions</a></li>
<li><a href="#org501b238">4. Get the size of a memory block</a></li>
</ul>
</div>
</div>
<div id="outline-container-org31a118b" class="outline-2">
<h2 id="org31a118b"><span class="section-number-2">1.</span> Memory data structure for the context</h2>
<div class="outline-text-2" id="text-1">
<p>
Every time a new block of memory is allocated, the information
relative to the allocation is stored in a new <code>qmckl_memory_info_struct</code>.
A <code>qmckl_memory_info_struct</code> contains the pointer to the memory block,
its size in bytes, and extra implementation-specific information such as
alignment, pinning, if the memory should be allocated on CPU or GPU
<i>etc</i>.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a020f0;">typedef</span> <span style="color: #a020f0;">struct</span> <span style="color: #228b22;">qmckl_memory_info_struct</span> {
<span style="color: #228b22;">size_t</span> <span style="color: #a0522d;">size</span>;
<span style="color: #228b22;">void</span>* <span style="color: #a0522d;">pointer</span>;
} <span style="color: #228b22;">qmckl_memory_info_struct</span>;
<span style="color: #a020f0;">static</span> <span style="color: #a020f0;">const</span> <span style="color: #228b22;">qmckl_memory_info_struct</span> <span style="color: #a0522d;">qmckl_memory_info_struct_zero</span> =
{
.size = (<span style="color: #228b22;">size_t</span>) 0,
.pointer = <span style="color: #008b8b;">NULL</span>
};
</pre>
</div>
<p>
The <code>memory</code> element of the context is a data structure which
contains an array of <code>qmckl_memory_info_struct</code>, the size of the
array, and the number of allocated blocks.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #a020f0;">typedef</span> <span style="color: #a020f0;">struct</span> <span style="color: #228b22;">qmckl_memory_struct</span> {
<span style="color: #228b22;">size_t</span> <span style="color: #a0522d;">n_allocated</span>;
<span style="color: #228b22;">size_t</span> <span style="color: #a0522d;">array_size</span>;
<span style="color: #228b22;">qmckl_memory_info_struct</span>* <span style="color: #a0522d;">element</span>;
} <span style="color: #228b22;">qmckl_memory_struct</span>;
</pre>
</div>
</div>
</div>
<div id="outline-container-orgc52927f" class="outline-2">
<h2 id="orgc52927f"><span class="section-number-2">2.</span> Passing info to allocation routines</h2>
<div class="outline-text-2" id="text-2">
<p>
Passing information to the allocation routine should be done by
passing an instance of a <code>qmckl_memory_info_struct</code>.
</p>
</div>
</div>
<div id="outline-container-org435db54" class="outline-2">
<h2 id="org435db54"><span class="section-number-2">3.</span> Allocation/deallocation functions</h2>
<div class="outline-text-2" id="text-3">
<p>
Memory allocation inside the library should be done with
<code>qmckl_malloc</code>. It lets the library choose how the memory will be
allocated, and a pointer is returned to the user. The context is
passed to let the library store data related to the allocation
inside the context. In this particular implementation of the library,
we store a list of allocated pointers so that all the memory can be
properly freed when the library is de-initialized.
If the allocation failed, the <code>NULL</code> pointer is returned.
</p>
<p>
The allocated memory block is zeroed using <code>memset</code>.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #228b22;">void</span>* <span style="color: #0000ff;">qmckl_malloc</span>(<span style="color: #228b22;">qmckl_context</span> <span style="color: #a0522d;">context</span>,
<span style="color: #a020f0;">const</span> <span style="color: #228b22;">qmckl_memory_info_struct</span> <span style="color: #a0522d;">info</span>);
</pre>
</div>
<p>
Here's a step-by-step explanation of <code>qmckl_malloc</code>:
</p>
<ol class="org-ol">
<li>The function takes two parameters: a <code>qmckl_context</code> and a
<code>qmckl_memory_info_struct</code> containing the desired size of the memory
block to allocate.</li>
<li>The function checks if the provided <code>qmckl_context</code> is valid, using the
<code>qmckl_context_check</code> function.</li>
<li>The <code>qmckl_context_struct</code> pointer is retrieved from the provided
<code>qmckl_context</code>.</li>
<li>The function then allocates memory:
If the <code>HAVE_HPC</code> and <code>HAVE_POSIX_MEMALIGN</code> macros are defined, the memory
allocation is done using the <code>aligned_alloc</code> function with a 64-byte alignment,
rounding up the requested size to the nearest multiple of 64 bytes. Else, the
memory allocation is done using the standard <code>malloc</code> function.</li>
</ol>
<p>
5 If the allocation fails, the function returns <code>NULL</code>.
</p>
<ol class="org-ol">
<li>The allocated memory block is zeroed using <code>memset</code>.</li>
<li>The function acquires a lock on the <code>qmckl_context</code> using <code>qmckl_lock</code>.</li>
<li>Inside the locked section, the function checks if the
<code>qmckl_memory_struct</code> is full. If it is, it reallocates a larger array
by doubling its size and updating the <code>array_size</code> member of the
<code>qmckl_memory_struct</code>.</li>
<li>The function finds the first available <code>qmckl_memory_info_struct</code> slot
in the element array of the <code>qmckl_memory_struct</code>.</li>
</ol>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #228b22;">void</span>* <span style="color: #0000ff;">qmckl_malloc</span>(<span style="color: #228b22;">qmckl_context</span> <span style="color: #a0522d;">context</span>, <span style="color: #a020f0;">const</span> <span style="color: #228b22;">qmckl_memory_info_struct</span> <span style="color: #a0522d;">info</span>) {
assert (qmckl_context_check(context) != QMCKL_NULL_CONTEXT);
<span style="color: #228b22;">qmckl_context_struct</span>* <span style="color: #a020f0;">const</span> <span style="color: #a0522d;">ctx</span> = (<span style="color: #228b22;">qmckl_context_struct</span>*) context;
/* <span style="color: #b22222;">Allocate memory and zero it</span> */
<span style="color: #228b22;">void</span> * <span style="color: #a0522d;">pointer</span> = <span style="color: #008b8b;">NULL</span>;
<span style="color: #483d8b;">#if</span> <span style="color: #483d8b;">defined</span>(HAVE_HPC) &amp;&amp; <span style="color: #483d8b;">defined</span>(HAVE_POSIX_MEMALIGN)
<span style="color: #a020f0;">if</span> (posix_memalign(&amp;pointer, 64, info.size) != 0) pointer = <span style="color: #008b8b;">NULL</span>;
<span style="color: #483d8b;">#else</span>
pointer = malloc(info.size);
<span style="color: #483d8b;">#endif</span>
<span style="color: #a020f0;">if</span> (pointer == <span style="color: #008b8b;">NULL</span>) {
<span style="color: #a020f0;">return</span> <span style="color: #008b8b;">NULL</span>;
}
memset(pointer, 0, info.size);
qmckl_lock(context);
{
/* <span style="color: #b22222;">If qmckl_memory_struct is full, reallocate a larger one</span> */
<span style="color: #a020f0;">if</span> (ctx-&gt;memory.n_allocated == ctx-&gt;memory.array_size) {
<span style="color: #a020f0;">const</span> <span style="color: #228b22;">size_t</span> <span style="color: #a0522d;">old_size</span> = ctx-&gt;memory.array_size;
<span style="color: #228b22;">qmckl_memory_info_struct</span> * <span style="color: #a0522d;">new_array</span> = realloc(ctx-&gt;memory.element,
2L * old_size *
<span style="color: #a020f0;">sizeof</span>(qmckl_memory_info_struct));
<span style="color: #a020f0;">if</span> (new_array == <span style="color: #008b8b;">NULL</span>) {
qmckl_unlock(context);
free(pointer);
<span style="color: #a020f0;">return</span> <span style="color: #008b8b;">NULL</span>;
}
memset( &amp;(new_array[old_size]), 0, old_size * <span style="color: #a020f0;">sizeof</span>(qmckl_memory_info_struct) );
ctx-&gt;memory.element = new_array;
ctx-&gt;memory.array_size = 2L * old_size;
}
/* <span style="color: #b22222;">Find first NULL entry</span> */
<span style="color: #228b22;">size_t</span> <span style="color: #a0522d;">pos</span> = (<span style="color: #228b22;">size_t</span>) 0;
<span style="color: #a020f0;">while</span> ( pos &lt; ctx-&gt;memory.array_size &amp;&amp; ctx-&gt;memory.element[pos].size &gt; (<span style="color: #228b22;">size_t</span>) 0) {
pos += (<span style="color: #228b22;">size_t</span>) 1;
}
assert (ctx-&gt;memory.element[pos].size == (<span style="color: #228b22;">size_t</span>) 0);
/* <span style="color: #b22222;">Copy info at the new location</span> */
memcpy(&amp;(ctx-&gt;memory.element[pos]), &amp;info, <span style="color: #a020f0;">sizeof</span>(qmckl_memory_info_struct));
ctx-&gt;memory.element[pos].pointer = pointer;
ctx-&gt;memory.n_allocated += (<span style="color: #228b22;">size_t</span>) 1;
//<span style="color: #b22222;">printf("MALLOC: %5ld %p\n", ctx-&gt;memory.n_allocated, ctx-&gt;memory.element[pos].pointer);</span>
}
qmckl_unlock(context);
<span style="color: #a020f0;">return</span> pointer;
}
</pre>
</div>
<div class="org-src-container">
<pre class="src src-c">/* <span style="color: #b22222;">Create a context</span> */
<span style="color: #228b22;">qmckl_context</span> <span style="color: #a0522d;">context</span> = qmckl_context_create();
<span style="color: #228b22;">qmckl_memory_info_struct</span> <span style="color: #a0522d;">info</span> = qmckl_memory_info_struct_zero;
info.size = (<span style="color: #228b22;">size_t</span>) 3*<span style="color: #a020f0;">sizeof</span>(<span style="color: #228b22;">int</span>);
/* <span style="color: #b22222;">Allocate an array of ints</span> */
<span style="color: #228b22;">int</span> *<span style="color: #a0522d;">a</span> = (<span style="color: #228b22;">int</span>*) <span style="color: #0000ff;">qmckl_malloc</span>(context, info);
/* <span style="color: #b22222;">Check that array of ints is OK</span> */
<span style="color: #0000ff;">assert</span>(a != <span style="color: #008b8b;">NULL</span>);
<span style="color: #228b22;">a</span>[0] = 1; <span style="color: #0000ff;">assert</span>(<span style="color: #228b22;">a</span>[0] == 1);
<span style="color: #228b22;">a</span>[1] = 2; <span style="color: #0000ff;">assert</span>(<span style="color: #228b22;">a</span>[1] == 2);
<span style="color: #228b22;">a</span>[2] = 3; <span style="color: #0000ff;">assert</span>(<span style="color: #228b22;">a</span>[2] == 3);
/* <span style="color: #b22222;">Allocate another array of ints</span> */
<span style="color: #228b22;">int</span> *<span style="color: #a0522d;">b</span> = (<span style="color: #228b22;">int</span>*) <span style="color: #0000ff;">qmckl_malloc</span>(context, info);
/* <span style="color: #b22222;">Check that array of ints is OK</span> */
<span style="color: #0000ff;">assert</span>(b != <span style="color: #008b8b;">NULL</span>);
<span style="color: #228b22;">b</span>[0] = 1; <span style="color: #0000ff;">assert</span>(<span style="color: #228b22;">b</span>[0] == 1);
<span style="color: #228b22;">b</span>[1] = 2; <span style="color: #0000ff;">assert</span>(<span style="color: #228b22;">b</span>[1] == 2);
<span style="color: #228b22;">b</span>[2] = 3; <span style="color: #0000ff;">assert</span>(<span style="color: #228b22;">b</span>[2] == 3);
</pre>
</div>
<p>
When freeing the memory with <code>qmckl_free</code>, the context is passed, in
case some important information has been stored related to memory
allocation and needs to be updated.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #228b22;">qmckl_exit_code</span> <span style="color: #0000ff;">qmckl_free</span>(<span style="color: #228b22;">qmckl_context</span> <span style="color: #a0522d;">context</span>,
<span style="color: #228b22;">void</span> * <span style="color: #a020f0;">const</span> <span style="color: #a0522d;">ptr</span>);
</pre>
</div>
<p>
Here's a step-by-step explanation of the <code>qmckl_free</code> function:
</p>
<ol class="org-ol">
<li>The function takes two parameters: a <code>qmckl_context</code> and a pointer to
the memory block (<code>ptr</code>) that needs to be deallocated.</li>
<li>The function checks if the provided <code>qmckl_context</code> is valid, using the
<code>qmckl_context_check</code> function. If it is not valid, it returns an error
code <code>QMCKL_INVALID_CONTEXT</code> using the <code>qmckl_failwith</code> function.</li>
<li>The function checks if the provided pointer is <code>NULL</code>. If it is, it
returns an error code <code>QMCKL_INVALID_ARG_2</code> using the <code>qmckl_failwith</code>
function.</li>
<li>The <code>qmckl_context_struct</code> pointer is retrieved from the provided
<code>qmckl_context</code>.</li>
<li>The function acquires a lock on the <code>qmckl_context</code> using <code>qmckl_lock</code>.</li>
<li>Inside the locked section, the function searches for the pointer in
the element array of the <code>qmckl_memory_struct</code>.</li>
<li>If the pointer is not found in the array, it releases the lock and
returns an error code <code>QMCKL_INVALID_ARG_2</code> using the <code>qmckl_failwith</code>
function.</li>
<li>If the pointer is found, the memory block is deallocated using the
standard <code>free</code> function.</li>
<li>The <code>qmckl_memory_info_struct</code> at the found position is zeroed
using <code>memset</code>. This marks the slot as available for future
allocations.</li>
</ol>
<ol class="org-ol">
<li>The <code>n_allocated</code> member of the <code>qmckl_memory_struct</code> is decremented
by one, as the memory block has been deallocated.</li>
<li>The function releases the lock on the <code>qmckl_context</code> using <code>qmckl_unlock</code>.</li>
<li>Finally, the function returns <code>QMCKL_SUCCESS</code> to indicate
successful deallocation of the memory block.</li>
</ol>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #228b22;">qmckl_exit_code</span> <span style="color: #0000ff;">qmckl_free</span>(<span style="color: #228b22;">qmckl_context</span> <span style="color: #a0522d;">context</span>, <span style="color: #228b22;">void</span> * <span style="color: #a020f0;">const</span> <span style="color: #a0522d;">ptr</span>) {
<span style="color: #a020f0;">if</span> (qmckl_context_check(context) == QMCKL_NULL_CONTEXT) {
<span style="color: #a020f0;">return</span> qmckl_failwith(context,
QMCKL_INVALID_CONTEXT,
<span style="color: #8b2252;">"qmckl_free"</span>,
<span style="color: #008b8b;">NULL</span>);
}
<span style="color: #a020f0;">if</span> (ptr == <span style="color: #008b8b;">NULL</span>) {
<span style="color: #a020f0;">return</span> qmckl_failwith(context,
QMCKL_INVALID_ARG_2,
<span style="color: #8b2252;">"qmckl_free"</span>,
<span style="color: #8b2252;">"NULL pointer"</span>);
}
<span style="color: #228b22;">qmckl_context_struct</span>* <span style="color: #a020f0;">const</span> <span style="color: #a0522d;">ctx</span> = (<span style="color: #228b22;">qmckl_context_struct</span>*) context;
qmckl_lock(context);
{
/* <span style="color: #b22222;">Find pointer in array of saved pointers</span> */
<span style="color: #228b22;">size_t</span> <span style="color: #a0522d;">pos</span> = (<span style="color: #228b22;">size_t</span>) 0;
<span style="color: #a020f0;">while</span> ( pos &lt; ctx-&gt;memory.array_size &amp;&amp; ctx-&gt;memory.element[pos].pointer != ptr) {
pos += (<span style="color: #228b22;">size_t</span>) 1;
}
<span style="color: #a020f0;">if</span> (pos &gt;= ctx-&gt;memory.array_size) {
/* <span style="color: #b22222;">Not found</span> */
qmckl_unlock(context);
<span style="color: #a020f0;">return</span> qmckl_failwith(context,
QMCKL_INVALID_ARG_2,
<span style="color: #8b2252;">"qmckl_free"</span>,
<span style="color: #8b2252;">"Pointer not found in context"</span>);
}
/* <span style="color: #b22222;">Found</span> */
free(ptr);
ctx-&gt;memory.n_allocated -= (<span style="color: #228b22;">size_t</span>) 1;
//<span style="color: #b22222;">printf("FREE : %5ld %p\n", ctx-&gt;memory.n_allocated, ctx-&gt;memory.element[pos].pointer);</span>
ctx-&gt;memory.element[pos] = qmckl_memory_info_struct_zero;
}
qmckl_unlock(context);
<span style="color: #a020f0;">return</span> QMCKL_SUCCESS;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-org501b238" class="outline-2">
<h2 id="org501b238"><span class="section-number-2">4.</span> Get the size of a memory block</h2>
<div class="outline-text-2" id="text-4">
<p>
All the blocks allocated with <code>qmckl_malloc</code> keep track of how many
bytes were allocated. Using <code>qmckl_malloc_size</code> allows to get this information.
</p>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #228b22;">qmckl_exit_code</span>
<span style="color: #0000ff;">qmckl_get_malloc_info</span>(<span style="color: #228b22;">qmckl_context</span> <span style="color: #a0522d;">context</span>,
<span style="color: #a020f0;">const</span> <span style="color: #228b22;">void</span>* <span style="color: #a0522d;">pointer</span>,
<span style="color: #228b22;">qmckl_memory_info_struct</span>* <span style="color: #a0522d;">info</span>);
</pre>
</div>
<div class="org-src-container">
<pre class="src src-c"><span style="color: #228b22;">qmckl_exit_code</span>
<span style="color: #0000ff;">qmckl_get_malloc_info</span>(<span style="color: #228b22;">qmckl_context</span> <span style="color: #a0522d;">context</span>,
<span style="color: #a020f0;">const</span> <span style="color: #228b22;">void</span>* <span style="color: #a0522d;">ptr</span>,
<span style="color: #228b22;">qmckl_memory_info_struct</span>* <span style="color: #a0522d;">info</span>)
{
assert (qmckl_context_check(context) != QMCKL_NULL_CONTEXT);
<span style="color: #228b22;">qmckl_context_struct</span>* <span style="color: #a020f0;">const</span> <span style="color: #a0522d;">ctx</span> = (<span style="color: #228b22;">qmckl_context_struct</span>*) context;
<span style="color: #a020f0;">if</span> (ptr == <span style="color: #008b8b;">NULL</span>) {
<span style="color: #a020f0;">return</span> qmckl_failwith(context,
QMCKL_INVALID_ARG_2,
<span style="color: #8b2252;">"qmckl_get_malloc_info"</span>,
<span style="color: #8b2252;">"Null pointer"</span>);
}
<span style="color: #a020f0;">if</span> (info == <span style="color: #008b8b;">NULL</span>) {
<span style="color: #a020f0;">return</span> qmckl_failwith(context,
QMCKL_INVALID_ARG_3,
<span style="color: #8b2252;">"qmckl_get_malloc_info"</span>,
<span style="color: #8b2252;">"Null pointer"</span>);
}
qmckl_lock(context);
{
/* <span style="color: #b22222;">Find the pointer entry</span> */
<span style="color: #228b22;">size_t</span> <span style="color: #a0522d;">pos</span> = (<span style="color: #228b22;">size_t</span>) 0;
<span style="color: #a020f0;">while</span> ( pos &lt; ctx-&gt;memory.array_size &amp;&amp; ctx-&gt;memory.element[pos].pointer != ptr) {
pos += (<span style="color: #228b22;">size_t</span>) 1;
}
<span style="color: #a020f0;">if</span> (pos &gt;= ctx-&gt;memory.array_size) {
/* <span style="color: #b22222;">Not found</span> */
qmckl_unlock(context);
<span style="color: #a020f0;">return</span> qmckl_failwith(context,
QMCKL_INVALID_ARG_2,
<span style="color: #8b2252;">"qmckl_get_malloc_info"</span>,
<span style="color: #8b2252;">"Pointer not found in context"</span>);
}
/* <span style="color: #b22222;">Copy info</span> */
memcpy(info, &amp;(ctx-&gt;memory.element[pos]), <span style="color: #a020f0;">sizeof</span>(qmckl_memory_info_struct));
}
qmckl_unlock(context);
<span style="color: #a020f0;">return</span> QMCKL_SUCCESS;
}
</pre>
</div>
<div class="org-src-container">
<pre class="src src-c">/* <span style="color: #b22222;">Create a context</span> */
context = qmckl_context_create();
info = qmckl_memory_info_struct_zero;
info.size = (<span style="color: #228b22;">size_t</span>) 3*<span style="color: #a020f0;">sizeof</span>(<span style="color: #228b22;">int</span>);
/* <span style="color: #b22222;">Allocate an array of ints</span> */
a = (<span style="color: #228b22;">int</span>*) <span style="color: #0000ff;">qmckl_malloc</span>(context, info);
/* <span style="color: #b22222;">Check that the size of a is 3*sizeof(int)</span> */
info = qmckl_memory_info_struct_zero;
rc = qmckl_get_malloc_info(context, <span style="color: #008b8b;">NULL</span>, &amp;info);
<span style="color: #0000ff;">assert</span> (rc == QMCKL_INVALID_ARG_2);
rc = qmckl_get_malloc_info(context, &amp;rc, &amp;info);
<span style="color: #0000ff;">assert</span> (rc == QMCKL_INVALID_ARG_2);
rc = qmckl_get_malloc_info(context, a, &amp;info);
<span style="color: #0000ff;">assert</span> (rc == QMCKL_SUCCESS);
<span style="color: #0000ff;">assert</span> (info.size == 3*<span style="color: #a020f0;">sizeof</span>(<span style="color: #228b22;">int</span>));
rc = qmckl_context_destroy(context);
</pre>
</div>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: TREX CoE</p>
<p class="date">Created: 2025-04-29 Tue 08:44</p>
<p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>