<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
        {mso-style-priority:99;
        mso-style-link:"Plain Text Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
span.PlainTextChar
        {mso-style-name:"Plain Text Char";
        mso-style-priority:99;
        mso-style-link:"Plain Text";
        font-family:"Calibri","sans-serif";}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoPlainText">After a bit of off-list back and forth on the credit / send / recv API, here’s my best shot:<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">First a definition:  The "size" of a send/recv context (aka queue for many providers) is the number of "MAX size" operations that can be posted and pending.  For IB, this is probably the number of WQEs/RQEs, for usnic it is the number
 of HW queue entries / iov_limit.  So, with no API changes, we get to at least where verbs is now:  easy accounting (just --x on post, ++x on completion), but providers like usnic pay a penalty in wasted queue space when iov_limit is large.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">This "size" should be as conservative as possible, including injected data, immediate data, atomic this and that, everything.  If size is N, an applicartion is guaranteed to be able to perform N sends/recvs/writes/reads with any legal
 parameters.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">I propose adding two calls:  fi_[rt]x_size_left() that return the number of "MAX size" operations that can be currently posted given what is currently posted and pending.  Note that parameters of MAX size are already reported via fi_info
 (iov_limit, inject_size, max_msg_size, etc.).  This eliminates the “divide queue depth by N” penalty paid by providers where send/recv operations consume variable amounts of hardware resources.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">So:<o:p></o:p></p>
<p class="MsoPlainText">- apps that just want EAGAIN work fine<o:p></o:p></p>
<p class="MsoPlainText">- apps that want to manage credits but care more about cycles than queue depth can just use --/++ on credits and be safe<o:p></o:p></p>
<p class="MsoPlainText">- apps that want to manage credits and care about maximizing queue depth can use:<o:p></o:p></p>
<p class="MsoPlainText">                if (fi_tx_size_left(ep) > 0) fi_send(); else queue_it();<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">The reason the 3rd bullet works is that app may call fi_tx_size_left() and get back, say, 5, then do 3 "small" sends, and fi_tx_size_left() might then return 4 - size_left() will always return a number >= the value the app would have
 from simply counting the number of operations done vs completions.  I cannot think of a provider whose internal accounting could not be represented this way.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">I'm hoping we can use this to answer both:<o:p></o:p></p>
<p class="MsoPlainText">- how do we define/specify/learn "size" of a tx/rx context?<o:p></o:p></p>
<p class="MsoPlainText">- how can the app manage send/recv credits cleanly and efficiently?<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">Prototypes are:<o:p></o:p></p>
<p class="MsoPlainText">size_t fi_rx_size_left(struct fid_ep *ep);<o:p></o:p></p>
<p class="MsoPlainText">size_t fi_tx_size_left(struct fid_ep *ep);<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">Sean correctly points out that one weakness here is a provider where a single “max sized send/recv” may consume *<b>all</b>* resources, such that fi_tx_size_left() returns 1 on an empty queue.  I think there are a couple of ways of handling
 that, “fall back to EAGAIN” being simplest.  Or, worst case, if there is a compelling use case for this, we add an extended version of size_left() that takes some additional arguments to specify the operation to be something smaller than max size, but that
 additional complexity is what stalled us earlier and what this approach is trying to avoid.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">Comments solicited…<o:p></o:p></p>
<p class="MsoPlainText">thanks!<o:p></o:p></p>
<p class="MsoPlainText">-reese<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>