Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:18

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief RTEMS Performance Monitoring and Measurement Framework.
0007  *
0008  * This is the Capture Engine component.
0009  */
0010 
0011 /*
0012  * Copyright 2002, 2016 Chris Johns <chrisj@rtems.org>. All rights reserved.
0013  *
0014  * COPYRIGHT (c) 1989-2014.
0015  * On-Line Applications Research Corporation (OAR).
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042 
0043 #include <stdlib.h>
0044 #include <string.h>
0045 
0046 #include <rtems/captureimpl.h>
0047 #include <rtems/score/statesimpl.h>
0048 #include <rtems/score/todimpl.h>
0049 #include <rtems/rtems/tasksimpl.h>
0050 
0051 /*
0052  * RTEMS Capture User Extension Data.
0053  */
0054 static rtems_id capture_id;
0055 
0056 static bool
0057 rtems_capture_create_task (rtems_tcb* current_task,
0058                            rtems_tcb* new_task);
0059 
0060 static void
0061 rtems_capture_start_task (rtems_tcb* current_task,
0062                           rtems_tcb* started_task);
0063 
0064 static void
0065 rtems_capture_restart_task (rtems_tcb* current_task,
0066                             rtems_tcb* restarted_task);
0067 
0068 static void
0069 rtems_capture_delete_task (rtems_tcb* current_task,
0070                            rtems_tcb* deleted_task);
0071 
0072 static void
0073 rtems_capture_switch_task (rtems_tcb* current_task,
0074                            rtems_tcb* heir_task);
0075 
0076 static void
0077 rtems_capture_begin_task (rtems_tcb* begin_task);
0078 
0079 static void
0080 rtems_capture_exitted_task (rtems_tcb* exitted_task);
0081 
0082 static void
0083 rtems_capture_terminated_task (rtems_tcb* terminated_task);
0084 
0085 static const rtems_extensions_table capture_extensions = {
0086   .thread_create    = rtems_capture_create_task,
0087   .thread_start     = rtems_capture_start_task,
0088   .thread_restart   = rtems_capture_restart_task,
0089   .thread_delete    = rtems_capture_delete_task,
0090   .thread_switch    = rtems_capture_switch_task,
0091   .thread_begin     = rtems_capture_begin_task,
0092   .thread_exitted   = rtems_capture_exitted_task,
0093   .fatal            = NULL,
0094   .thread_terminate = rtems_capture_terminated_task
0095 };
0096 
0097 static inline void capture_record (rtems_tcb* tcb, uint32_t events)
0098 {
0099   rtems_capture_record_lock_context rec_context;
0100 
0101   if (rtems_capture_filter (tcb, events))
0102     return;
0103 
0104   if (!rtems_capture_task_recorded (tcb))
0105     rtems_capture_record_task (tcb);
0106 
0107   rtems_capture_record_open (tcb, events, 0, &rec_context);
0108   rtems_capture_record_close (&rec_context);
0109 }
0110 
0111 
0112 rtems_status_code rtems_capture_user_extension_open(void)
0113 {
0114   rtems_status_code sc;
0115   rtems_name        name;
0116   int               index;
0117 
0118   /*
0119    * Register the user extension handlers for the CAPture Engine.
0120    */
0121   name = rtems_build_name ('C', 'A', 'P', 'E');
0122   sc   = rtems_extension_create (name, &capture_extensions, &capture_id);
0123   if (sc != RTEMS_SUCCESSFUL)
0124     capture_id = 0;
0125   else {
0126     index = rtems_object_id_get_index (capture_id);
0127     rtems_capture_set_extension_index (index);
0128   }
0129 
0130   return sc;
0131 }
0132 
0133 rtems_status_code rtems_capture_user_extension_close(void)
0134 {
0135   rtems_status_code sc;
0136   sc = rtems_extension_delete (capture_id);
0137   return sc;
0138 }
0139 
0140 /*
0141  * This function is called when a task is created.
0142  */
0143 static bool
0144 rtems_capture_create_task (rtems_tcb* ct,
0145                            rtems_tcb* nt)
0146 {
0147   /*
0148    * The task pointers may not be known as the task may have
0149    * been created before the capture engine was open. Add them.
0150    */
0151   if (!rtems_capture_task_initialized (ct))
0152     rtems_capture_initialize_task (ct);
0153 
0154   /*
0155    * Create the new task's capture control block.
0156    */
0157   rtems_capture_initialize_task (nt);
0158 
0159   if (rtems_capture_trigger_fired (ct, nt, RTEMS_CAPTURE_CREATE))
0160   {
0161     capture_record (ct, RTEMS_CAPTURE_CREATED_BY_EVENT);
0162     capture_record (nt, RTEMS_CAPTURE_CREATED_EVENT);
0163   }
0164 
0165   return 1 == 1;
0166 }
0167 
0168 /*
0169  * This function is called when a task is started.
0170  */
0171 static void
0172 rtems_capture_start_task (rtems_tcb* ct,
0173                           rtems_tcb* st)
0174 {
0175   /*
0176    * The task pointers may not be known as the task may have
0177    * been created before the capture engine was open. Add them.
0178    */
0179 
0180   if (!rtems_capture_task_initialized (ct))
0181     rtems_capture_initialize_task (ct);
0182 
0183   if (st != NULL)
0184     rtems_capture_initialize_task (st);
0185 
0186   if (rtems_capture_trigger_fired (ct, st, RTEMS_CAPTURE_START))
0187   {
0188     capture_record (ct, RTEMS_CAPTURE_STARTED_BY_EVENT);
0189     capture_record (st, RTEMS_CAPTURE_STARTED_EVENT);
0190   }
0191 }
0192 
0193 /*
0194  * This function is called when a task is restarted.
0195  */
0196 static void
0197 rtems_capture_restart_task (rtems_tcb* ct,
0198                             rtems_tcb* rt)
0199 {
0200   /*
0201    * The task pointers may not be known as the task may have
0202    * been created before the capture engine was open. Add them.
0203    */
0204   if (!rtems_capture_task_initialized (ct))
0205     rtems_capture_initialize_task (ct);
0206 
0207   if (!rtems_capture_task_initialized (rt))
0208     rtems_capture_initialize_task (rt);
0209 
0210   if (rtems_capture_trigger_fired (ct, rt, RTEMS_CAPTURE_RESTART))
0211   {
0212     capture_record (ct, RTEMS_CAPTURE_RESTARTED_BY_EVENT);
0213     capture_record (rt, RTEMS_CAPTURE_RESTARTED_EVENT);
0214   }
0215 }
0216 
0217 /*
0218  * This function is called when a task is deleted.
0219  */
0220 static void
0221 rtems_capture_delete_task (rtems_tcb* ct,
0222                            rtems_tcb* dt)
0223 {
0224   if (!rtems_capture_task_initialized (ct))
0225     rtems_capture_initialize_task (ct);
0226 
0227   if (!rtems_capture_task_initialized (dt))
0228     rtems_capture_initialize_task (dt);
0229 
0230   if (rtems_capture_trigger_fired (ct, dt, RTEMS_CAPTURE_DELETE))
0231   {
0232     capture_record (ct, RTEMS_CAPTURE_DELETED_BY_EVENT);
0233     capture_record (dt, RTEMS_CAPTURE_DELETED_EVENT);
0234   }
0235 }
0236 
0237 /*
0238  * This function is called when a task is begun.
0239  */
0240 static void
0241 rtems_capture_begin_task (rtems_tcb* bt)
0242 {
0243   /*
0244    * The task pointers may not be known as the task may have
0245    * been created before the capture engine was open. Add them.
0246    */
0247 
0248   if (!rtems_capture_task_initialized (bt))
0249     rtems_capture_initialize_task (bt);
0250 
0251   if (rtems_capture_trigger_fired (NULL, bt, RTEMS_CAPTURE_BEGIN))
0252     capture_record (bt, RTEMS_CAPTURE_BEGIN_EVENT);
0253 }
0254 
0255 /*
0256  * This function is called when a task is exitted. That is
0257  * returned rather than was deleted.
0258  */
0259 static void
0260 rtems_capture_exitted_task (rtems_tcb* et)
0261 {
0262   /*
0263    * The task pointers may not be known as the task may have
0264    * been created before the capture engine was open. Add them.
0265    */
0266 
0267   if (!rtems_capture_task_initialized (et))
0268     rtems_capture_initialize_task (et);
0269 
0270   if (rtems_capture_trigger_fired (NULL, et, RTEMS_CAPTURE_EXITTED))
0271     capture_record (et, RTEMS_CAPTURE_EXITTED_EVENT);
0272 }
0273 
0274 /*
0275  * This function is called when a termination request is identified.
0276  */
0277 static void
0278 rtems_capture_terminated_task (rtems_tcb* tt)
0279 {
0280   /*
0281    * The task pointers may not be known as the task may have
0282    * been created before the capture engine was open. Add them.
0283    */
0284 
0285   if (!rtems_capture_task_initialized (tt))
0286     rtems_capture_initialize_task (tt);
0287 
0288   if (rtems_capture_trigger_fired (NULL, tt, RTEMS_CAPTURE_TERMINATED))
0289     capture_record (tt, RTEMS_CAPTURE_TERMINATED_EVENT);
0290 }
0291 
0292 /*
0293  * This function is called when a context is switched.
0294  */
0295 static void
0296 rtems_capture_switch_task (rtems_tcb* ct,
0297                            rtems_tcb* ht)
0298 {
0299   uint32_t flags = rtems_capture_get_flags();
0300 
0301   /*
0302    * Only perform context switch trace processing if tracing is
0303    * enabled.
0304    */
0305   if (flags & RTEMS_CAPTURE_ON)
0306   {
0307     rtems_capture_time time;
0308     if (!rtems_capture_task_initialized (ct))
0309       rtems_capture_initialize_task (ct);
0310 
0311     if (!rtems_capture_task_initialized (ht))
0312       rtems_capture_initialize_task (ht);
0313 
0314     /*
0315      * Update the execution time. Assume the time will not overflow
0316      * for now. This may need to change.
0317      */
0318     rtems_capture_get_time (&time);
0319 
0320     if (rtems_capture_trigger_fired (ct, ht, RTEMS_CAPTURE_SWITCH))
0321     {
0322       capture_record (ct, RTEMS_CAPTURE_SWITCHED_OUT_EVENT);
0323       capture_record (ht, RTEMS_CAPTURE_SWITCHED_IN_EVENT);
0324     }
0325   }
0326 }