summaryrefslogblamecommitdiffstats
path: root/cpukit/libmisc/capture/capture_user_extension.c
blob: 37372cbe1ecd88e37b22291ff2be86b117452067 (plain) (tree)
1
2
3
4
5
6
7
8






                                                                          
                          











                                                                          




















                                           

                                                   






































                                                           
                                         

                      


                               

                                               
 
                                          
           
 

                                         
 

                                                           


 































                                                                         

                                         
 



                                                               

                                           



                                                 
                                     













                                                              

                                        

    



                                                               

                                           
 
                 
                                       





                                                              





                                                    

                                          

    


                                                               

                                           
 

                                           





                                                                





                                                  

                                         
 

                                           
 

                                           





                                                              





                                                
                                        

    



                                                               

                                           









                                                            
                                          

    



                                                               

                                           


                                                              





                                                                    
                                             

    



                                                               

                                           


                                                                 





                                                      

                                         

                                             







                                                               

                                             
 

                                             






                                                                   






                                                                  
/*
  ------------------------------------------------------------------------

  Copyright Objective Design Systems Pty Ltd, 2002
  All rights reserved Objective Design Systems Pty Ltd, 2002
  Chris Johns (ccj@acm.org)

  COPYRIGHT (c) 1989-2014.
  On-Line Applications Research Corporation (OAR).

  The license and distribution terms for this file may be
  found in the file LICENSE in this distribution.

  This software with is provided ``as is'' and with NO WARRANTY.

  ------------------------------------------------------------------------

  RTEMS Performance Monitoring and Measurement Framework.

  This is the Capture Engine component.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>
#include <string.h>
#include <rtems/rtems/tasksimpl.h>

#include "captureimpl.h"

#include <rtems/score/statesimpl.h>
#include <rtems/score/todimpl.h>


/*
 * RTEMS Capture User Extension Data.
 */
static rtems_id                 capture_id;

static bool
rtems_capture_create_task (rtems_tcb* current_task,
                           rtems_tcb* new_task);

static void
rtems_capture_start_task (rtems_tcb* current_task,
                          rtems_tcb* started_task);

static void
rtems_capture_restart_task (rtems_tcb* current_task,
                            rtems_tcb* restarted_task);

static void
rtems_capture_delete_task (rtems_tcb* current_task,
                           rtems_tcb* deleted_task);

static void
rtems_capture_switch_task (rtems_tcb* current_task,
                           rtems_tcb* heir_task);

static void
rtems_capture_begin_task (rtems_tcb* begin_task);

static void
rtems_capture_exitted_task (rtems_tcb* exitted_task);

static void
rtems_capture_terminated_task (rtems_tcb* terminated_task);

static const rtems_extensions_table capture_extensions = {
  .thread_create    = rtems_capture_create_task,
  .thread_start     = rtems_capture_start_task,
  .thread_restart   = rtems_capture_restart_task,
  .thread_delete    = rtems_capture_delete_task,
  .thread_switch    = rtems_capture_switch_task,
  .thread_begin     = rtems_capture_begin_task,
  .thread_exitted   = rtems_capture_exitted_task,
  .fatal            = NULL,
  .thread_terminate = rtems_capture_terminated_task
};

static inline void rtems_capture_record (
  rtems_tcb*    tcb,
  uint32_t      events
)
{
  rtems_capture_record_t*  rec;
  void*                    ptr;
  size_t                   size = sizeof(*rec);

  if (rtems_capture_filter( tcb, events) )
    return;

  if (!rtems_capture_task_recorded (tcb))
    rtems_capture_record_task (tcb);

  rtems_capture_begin_add_record (tcb, events, size, &ptr);
  rtems_capture_end_add_record ( ptr );
}


rtems_status_code rtems_capture_user_extension_open(void)
{
  rtems_status_code sc;
  rtems_name        name;
  int               index;

  /*
   * Register the user extension handlers for the CAPture Engine.
   */
  name = rtems_build_name ('C', 'A', 'P', 'E');
  sc   = rtems_extension_create (name, &capture_extensions, &capture_id);
  if (sc != RTEMS_SUCCESSFUL)
    capture_id = 0;
  else {
    index = rtems_object_id_get_index (capture_id);
    rtems_capture_set_extension_index( index );
  }

  return sc;
}

rtems_status_code rtems_capture_user_extension_close(void)
{
  rtems_status_code sc;
  sc = rtems_extension_delete (capture_id);
  return sc;
}

/*
 * This function is called when a task is created.
 */
static bool
rtems_capture_create_task (rtems_tcb* ct,
                           rtems_tcb* nt)
{
  /*
   * The task pointers may not be known as the task may have
   * been created before the capture engine was open. Add them.
   */
  if (!rtems_capture_task_initialized (ct))
    rtems_capture_initialize_task (ct);

  /*
   * Create the new task's capture control block.
   */
  rtems_capture_initialize_task (nt);

  if (rtems_capture_trigger (ct, nt, RTEMS_CAPTURE_CREATE))
  {
    rtems_capture_record (ct, RTEMS_CAPTURE_CREATED_BY_EVENT);
    rtems_capture_record (nt, RTEMS_CAPTURE_CREATED_EVENT);
  }

  return 1 == 1;
}

/*
 * This function is called when a task is started.
 */
static void
rtems_capture_start_task (rtems_tcb* ct,
                          rtems_tcb* st)
{
  /*
   * The task pointers may not be known as the task may have
   * been created before the capture engine was open. Add them.
   */

  if (!rtems_capture_task_initialized (ct))
    rtems_capture_initialize_task (ct);

  if (st != NULL)
    rtems_capture_initialize_task (st);

  if (rtems_capture_trigger (ct, st, RTEMS_CAPTURE_START))
  {
    rtems_capture_record (ct, RTEMS_CAPTURE_STARTED_BY_EVENT);
    rtems_capture_record (st, RTEMS_CAPTURE_STARTED_EVENT);
  }
}

/*
 * This function is called when a task is restarted.
 */
static void
rtems_capture_restart_task (rtems_tcb* ct,
                            rtems_tcb* rt)
{
  /*
   * The task pointers may not be known as the task may have
   * been created before the capture engine was open. Add them.
   */
  if (!rtems_capture_task_initialized (ct))
    rtems_capture_initialize_task (ct);

  if (!rtems_capture_task_initialized (rt))
    rtems_capture_initialize_task (rt);

  if (rtems_capture_trigger (ct, rt, RTEMS_CAPTURE_RESTART))
  {
    rtems_capture_record (ct, RTEMS_CAPTURE_RESTARTED_BY_EVENT);
    rtems_capture_record (rt, RTEMS_CAPTURE_RESTARTED_EVENT);
  }
}

/*
 * This function is called when a task is deleted.
 */
static void
rtems_capture_delete_task (rtems_tcb* ct,
                           rtems_tcb* dt)
{
  if (!rtems_capture_task_initialized (ct))
    rtems_capture_initialize_task (ct);

  if (!rtems_capture_task_initialized (dt))
    rtems_capture_initialize_task (dt);

  if (rtems_capture_trigger (ct, dt, RTEMS_CAPTURE_DELETE))
  {
    rtems_capture_record (ct, RTEMS_CAPTURE_DELETED_BY_EVENT);
    rtems_capture_record (dt, RTEMS_CAPTURE_DELETED_EVENT);
  }
}

/*
 * This function is called when a task is begun.
 */
static void
rtems_capture_begin_task (rtems_tcb* bt)
{
  /*
   * The task pointers may not be known as the task may have
   * been created before the capture engine was open. Add them.
   */

  if (!rtems_capture_task_initialized (bt))
    rtems_capture_initialize_task (bt);

  if (rtems_capture_trigger (NULL, bt, RTEMS_CAPTURE_BEGIN))
    rtems_capture_record (bt, RTEMS_CAPTURE_BEGIN_EVENT);
}

/*
 * This function is called when a task is exitted. That is
 * returned rather than was deleted.
 */
static void
rtems_capture_exitted_task (rtems_tcb* et)
{
  /*
   * The task pointers may not be known as the task may have
   * been created before the capture engine was open. Add them.
   */

  if (!rtems_capture_task_initialized (et))
    rtems_capture_initialize_task (et);

  if (rtems_capture_trigger (NULL, et, RTEMS_CAPTURE_EXITTED))
    rtems_capture_record (et, RTEMS_CAPTURE_EXITTED_EVENT);
}

/*
 * This function is called when a termination request is identified.
 */
static void
rtems_capture_terminated_task (rtems_tcb* tt)
{
  /*
   * The task pointers may not be known as the task may have
   * been created before the capture engine was open. Add them.
   */

  if (!rtems_capture_task_initialized (tt))
    rtems_capture_initialize_task (tt);

  if (rtems_capture_trigger (NULL, tt, RTEMS_CAPTURE_TERMINATED))
    rtems_capture_record (tt, RTEMS_CAPTURE_TERMINATED_EVENT);
}

/*
 * This function is called when a context is switched.
 */
static void
rtems_capture_switch_task (rtems_tcb* ct,
                           rtems_tcb* ht)
{
  uint32_t flags = rtems_capture_get_flags();

  /*
   * Only perform context switch trace processing if tracing is
   * enabled.
   */
  if (flags & RTEMS_CAPTURE_ON)
  {
    rtems_capture_time_t time;
    if (!rtems_capture_task_initialized (ct))
      rtems_capture_initialize_task (ct);

    if (!rtems_capture_task_initialized (ht))
      rtems_capture_initialize_task (ht);

    /*
     * Update the execution time. Assume the time will not overflow
     * for now. This may need to change.
     */
    rtems_capture_get_time (&time);

    if (rtems_capture_trigger (ct, ht, RTEMS_CAPTURE_SWITCH))
    {
      rtems_capture_record (ct, RTEMS_CAPTURE_SWITCHED_OUT_EVENT);
      rtems_capture_record (ht, RTEMS_CAPTURE_SWITCHED_IN_EVENT);
    }
  }
}