1
0
mirror of https://github.com/TREX-CoE/qmckl.git synced 2024-06-01 02:45:43 +02:00
qmckl/qmckl_memory.html

749 lines
34 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>
<!-- 2024-05-08 Wed 11:57 -->
<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="generator" content="Org mode" />
<meta name="author" content="TREX CoE" />
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
.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 #ccc;
box-shadow: 3px 3px 3px #eee;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: visible;
padding-top: 1.2em;
}
pre.src:before {
display: none;
position: absolute;
background-color: white;
top: -10px;
right: 10px;
padding: 3px;
border: 1px solid black;
}
pre.src:hover:before { display: inline;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
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 { width: 90%; }
/*]]>*/-->
</style>
<link rel="stylesheet" title="Standard" href="qmckl.css" type="text/css" />
<script type="text/javascript" src="org-info.js">
/**
*
* @source: org-info.js
*
* @licstart The following is the entire license notice for the
* JavaScript code in org-info.js.
*
* Copyright (C) 2012-2020 Free Software Foundation, Inc.
*
*
* The JavaScript code in this tag is free software: you can
* redistribute it and/or modify it under the terms of the GNU
* General Public License (GNU GPL) as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version. The code is distributed WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
*
* As additional permission under GNU GPL version 3 section 7, you
* may distribute non-source (e.g., minimized or compacted) forms of
* that code without the copy of the GNU GPL normally required by
* section 4, provided you include this license notice and a URL
* through which recipients can access the Corresponding Source.
*
* @licend The above is the entire license notice
* for the JavaScript code in org-info.js.
*
*/
</script>
<script type="text/javascript">
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
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
/*]]>*///-->
</script>
<script type="text/javascript">
/*
@licstart The following is the entire license notice for the
JavaScript code in this tag.
Copyright (C) 2012-2020 Free Software Foundation, Inc.
The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version. The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.
@licend The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
function CodeHighlightOn(elem, id)
{
var target = document.getElementById(id);
if(null != target) {
elem.cacheClassElem = elem.className;
elem.cacheClassTarget = target.className;
target.className = "code-highlighted";
elem.className = "code-highlighted";
}
}
function CodeHighlightOff(elem, id)
{
var target = document.getElementById(id);
if(elem.cacheClassElem)
elem.className = elem.cacheClassElem;
if(elem.cacheClassTarget)
target.className = elem.cacheClassTarget;
}
/*]]>*///-->
</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">
<h1 class="title">Memory management</h1>
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#org612b560">1. Memory data structure for the context</a></li>
<li><a href="#org6ded438">2. Passing info to allocation routines</a></li>
<li><a href="#orga56e945">3. Allocation/deallocation functions</a></li>
<li><a href="#org2e3294f">4. Get the size of a memory block</a></li>
</ul>
</div>
</div>
<div id="outline-container-org612b560" class="outline-2">
<h2 id="org612b560"><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-org6ded438" class="outline-2">
<h2 id="org6ded438"><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-orga56e945" class="outline-2">
<h2 id="orga56e945"><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-org2e3294f" class="outline-2">
<h2 id="org2e3294f"><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: 2024-05-08 Wed 11:57</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>