Back to index

glibc  2.9
Functions
mcount.c File Reference
#include <unistd.h>
#include <sys/param.h>
#include <sys/gmon.h>
#include <machine-gmon.h>
#include <atomic.h>

Go to the source code of this file.

Functions

 _MCOUNT_DECL (frompc, selfpc)

Function Documentation

_MCOUNT_DECL ( frompc  ,
selfpc   
)

Definition at line 59 of file mcount.c.

{
       register ARCINDEX *frompcindex;
       register struct tostruct *top, *prevtop;
       register struct gmonparam *p;
       register ARCINDEX toindex;
       int i;

       p = &_gmonparam;
       /*
        * check that we are profiling
        * and that we aren't recursively invoked.
        */
       if (catomic_compare_and_exchange_bool_acq (&p->state, GMON_PROF_BUSY,
                                             GMON_PROF_ON))
         return;

       /*
        * check that frompcindex is a reasonable pc value.
        * for example:      signal catchers get called from the stack,
        *            not from text space.  too bad.
        */
       frompc -= p->lowpc;
       if (frompc > p->textsize)
              goto done;

       /* The following test used to be
              if (p->log_hashfraction >= 0)
          But we can simplify this if we assume the profiling data
          is always initialized by the functions in gmon.c.  But
          then it is possible to avoid a runtime check and use the
          smae `if' as in gmon.c.  So keep these tests in sync.  */
       if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) {
         /* avoid integer divide if possible: */
           i = frompc >> p->log_hashfraction;
       } else {
           i = frompc / (p->hashfraction * sizeof(*p->froms));
       }
       frompcindex = &p->froms[i];
       toindex = *frompcindex;
       if (toindex == 0) {
              /*
               *     first time traversing this arc
               */
              toindex = ++p->tos[0].link;
              if (toindex >= p->tolimit)
                     /* halt further profiling */
                     goto overflow;

              *frompcindex = toindex;
              top = &p->tos[toindex];
              top->selfpc = selfpc;
              top->count = 1;
              top->link = 0;
              goto done;
       }
       top = &p->tos[toindex];
       if (top->selfpc == selfpc) {
              /*
               * arc at front of chain; usual case.
               */
              top->count++;
              goto done;
       }
       /*
        * have to go looking down chain for it.
        * top points to what we are looking at,
        * prevtop points to previous top.
        * we know it is not at the head of the chain.
        */
       for (; /* goto done */; ) {
              if (top->link == 0) {
                     /*
                      * top is end of the chain and none of the chain
                      * had top->selfpc == selfpc.
                      * so we allocate a new tostruct
                      * and link it to the head of the chain.
                      */
                     toindex = ++p->tos[0].link;
                     if (toindex >= p->tolimit)
                            goto overflow;

                     top = &p->tos[toindex];
                     top->selfpc = selfpc;
                     top->count = 1;
                     top->link = *frompcindex;
                     *frompcindex = toindex;
                     goto done;
              }
              /*
               * otherwise, check the next arc on the chain.
               */
              prevtop = top;
              top = &p->tos[top->link];
              if (top->selfpc == selfpc) {
                     /*
                      * there it is.
                      * increment its count
                      * move it to the head of the chain.
                      */
                     top->count++;
                     toindex = prevtop->link;
                     prevtop->link = top->link;
                     top->link = *frompcindex;
                     *frompcindex = toindex;
                     goto done;
              }

       }
done:
       p->state = GMON_PROF_ON;
       return;
overflow:
       p->state = GMON_PROF_ERROR;
       return;
}