<br><font size=2 face="sans-serif">Hi all,</font>
<br>
<br><font size=2 face="sans-serif">While ago looking for the a possible
implementation of _mcount() and profil() specific routines for RTEMS and
LEON2/3 I found this old thread</font>
<br>
<br><font size=2 face="sans-serif">http://www.rtems.com/ml/rtems-users/2003/february/msg00034.html</font>
<br>
<br><font size=2 face="sans-serif">Didn't find anything else on the topic
so I decided to implement _mcount() and profil() functionality over RTEMS
and LEON2/3 (file attached).</font>
<br>
<br><font size=2 face="sans-serif">It's not been integrated within RTEMS
distribution as I was not interested in profile RTEMS but application software
but the implementation is pretty portable as it uses __builtin_return_address()
to implement mcount. </font>
<br>
<br><font size=2 face="sans-serif">mcount() is just responsible for recording
in memory the call graph but there is another functionality that had to
be implemented and this is the one provided by the profil() routine under
UNIX-like systems.</font>
<br>
<br><font size=2 face="sans-serif">profil() routine keeps an histogram
of where the program counter happens to be every now and then. This routine
is not provided in the newlib for SPARC so I had to implement its functionality.
As I am working at application level this part was a bit more tricky as
I need to look at and store the PC every clock tick.</font>
<br><font size=2 face="sans-serif">To do that I register a new handler
for the clock (replace Clock_isr). This new handler just saves the PC and
calls Clock_isr(). But this is not enough as we have to store also the
PC in the histogram and some checks and histogram scale factors need to
be applied. The problem was that I have to do all this in the clock isr
avoiding any "save" instruction but if the handler performs to
many operations the compiler introduces "save" at the beginning
to allocate stack space for the function, the register window is moved
and so the PC is lost as it is stored in the local registers (%L1)</font>
<br>
<br><font size=2 face="sans-serif">I don't wanna get into details here
but in short the implementation replaces the Clock_isr() by a new one.
This saves the PC in a global variable and calls Clock_isr(). It is also
needed to wrap Clock_isr() -- using -Wl,--wrap linker options --  so
when it is called the previously saved PC can be properly stored into the
histogram.</font>
<br>
<br><font size=2 face="sans-serif">Bellow the new clock handler</font>
<br>
<br><font size=2 face="Courier New">static rtems_isr profile_clock_isr(rtems_vector_number
vector)</font>
<br><font size=2 face="Courier New">{</font>
<br><font size=2 face="Courier New">    SAVE_L1(pc);</font>
<br><font size=2 face="Courier New">    Clock_isr(vector);</font>
<br><font size=2 face="Courier New">    </font>
<br><font size=2 face="Courier New">}</font>
<br>
<br><font size=2 face="sans-serif">and the Clock_isr() wrapper routine</font>
<br>
<br>
<br><font size=2 face="Courier New">rtems_isr __wrap_Clock_isr()</font>
<br><font size=2 face="Courier New">{</font>
<br><font size=2 face="Courier New">    if( s_profil &&
s_profil_sz )</font>
<br><font size=2 face="Courier New">    {</font>
<br><font size=2 face="Courier New">        if( pc
)</font>
<br><font size=2 face="Courier New">        {</font>
<br><font size=2 face="Courier New">         
  pc -= (int)s_lowpc;</font>
<br><font size=2 face="Courier New">         
  pc = (pc >> HISTFRACTION_LOG2);</font>
<br><font size=2 face="Courier New">         
  if( pc < s_profil_sz )  s_profil[pc]++;</font>
<br><font size=2 face="Courier New">        }</font>
<br><font size=2 face="Courier New">    }</font>
<br><font size=2 face="Courier New">    pc = 0;</font>
<br>
<br><font size=2 face="Courier New">    __real_Clock_isr();</font>
<br><font size=2 face="Courier New">    </font>
<br><font size=2 face="Courier New">}</font>
<br>
<br>
<br><font size=2 face="sans-serif">I believe that introducing this code
into RTEMS source tree will ease all these as all can be handled directly
from the Clock_isr() routine. I am thinking about Clock_isr() acting as
a bottom handler to save the PC (%l1) register in a global variable and
then calling another function which would be the top handler to perform
the histogram.</font>
<br>
<br><font size=2 face="sans-serif">The dump of the profiling information
is made in the mcleanup() routine (serial line or UDP). The routine is
called at exit.</font>
<br>
<br><font size=2 face="sans-serif">Don't know if anybody tackled this before
but I did not find anything on the RTEMS list so here is the code</font>
<br>
<br>
<br>
<br><font size=2 face="sans-serif"><br>
//avs<br>
<br>
-----------------------------<br>
Aitor Viana Sánchez<br>
<br>
<br>
ESA - European Space Technology Centre (ESTEC)<br>
On-board Computer Engineer - TEC-EDS<br>
ESA/ESTEC P.O. Box 299 / 2200AG Noordwijk ZH, The Netherlands<br>
Tel (+31) 71 565 6727<br>
Email: aitor.viana.sanchez@esa.int</font>