File indexing completed on 2025-05-11 08:24:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 #ifdef HAVE_CONFIG_H
0041 #include "config.h"
0042 #endif
0043
0044 #include <stdlib.h>
0045 #include <string.h>
0046
0047 #include <rtems/captureimpl.h>
0048 #include "capture_buffer.h"
0049
0050
0051
0052
0053
0054
0055
0056
0057 #if defined (RTEMS_CAPTURE_ENGINE_ALLOW_RELATED_EVENTS)
0058 #define RTEMS_CAPTURE_RECORD_EVENTS (RTEMS_CAPTURE_CREATED_BY_EVENT | \
0059 RTEMS_CAPTURE_CREATED_EVENT | \
0060 RTEMS_CAPTURE_STARTED_BY_EVENT | \
0061 RTEMS_CAPTURE_STARTED_EVENT | \
0062 RTEMS_CAPTURE_RESTARTED_BY_EVENT | \
0063 RTEMS_CAPTURE_RESTARTED_EVENT | \
0064 RTEMS_CAPTURE_DELETED_BY_EVENT | \
0065 RTEMS_CAPTURE_DELETED_EVENT | \
0066 RTEMS_CAPTURE_BEGIN_EVENT | \
0067 RTEMS_CAPTURE_EXITTED_EVENT | \
0068 RTEMS_CAPTURE_TERMINATED_EVENT | \
0069 RTEMS_CAPTURE_AUTOGEN_ENTRY_EVENT | \
0070 RTEMS_CAPTURE_AUTOGEN_EXIT_EVENT)
0071 #else
0072 #define RTEMS_CAPTURE_RECORD_EVENTS (0)
0073 #endif
0074
0075 typedef struct {
0076 rtems_capture_buffer records;
0077 uint32_t count;
0078 rtems_id reader;
0079 rtems_interrupt_lock lock;
0080 uint32_t flags;
0081 } rtems_capture_per_cpu_data;
0082
0083 typedef struct {
0084 uint32_t flags;
0085 rtems_capture_control* controls;
0086 int extension_index;
0087 rtems_capture_timestamp timestamp;
0088 rtems_task_priority ceiling;
0089 rtems_task_priority floor;
0090 rtems_interrupt_lock lock;
0091 } rtems_capture_global_data;
0092
0093 static rtems_capture_per_cpu_data *capture_per_cpu = NULL;
0094
0095 static rtems_capture_global_data capture_global = {
0096 .lock = RTEMS_INTERRUPT_LOCK_INITIALIZER( "Capture" )
0097 };
0098
0099
0100
0101
0102 #define capture_per_cpu_get( _cpu ) \
0103 ( &capture_per_cpu[ _cpu ] )
0104
0105 #define capture_records_on_cpu( _cpu ) capture_per_cpu[ _cpu ].records
0106 #define capture_count_on_cpu( _cpu ) capture_per_cpu[ _cpu ].count
0107 #define capture_flags_on_cpu( _cpu ) capture_per_cpu[ _cpu ].flags
0108 #define capture_reader_on_cpu( _cpu ) capture_per_cpu[ _cpu ].reader
0109 #define capture_lock_on_cpu( _cpu ) capture_per_cpu[ _cpu ].lock
0110
0111 #define capture_flags_global capture_global.flags
0112 #define capture_controls capture_global.controls
0113 #define capture_extension_index capture_global.extension_index
0114 #define capture_timestamp capture_global.timestamp
0115 #define capture_ceiling capture_global.ceiling
0116 #define capture_floor capture_global.floor
0117 #define capture_lock_global capture_global.lock
0118
0119
0120
0121
0122 static const char * const capture_event_text[] =
0123 {
0124 "CREATED_BY",
0125 "CREATED",
0126 "STARTED_BY",
0127 "STARTED",
0128 "RESTARTED_BY",
0129 "RESTARTED",
0130 "DELETED_BY",
0131 "DELETED",
0132 "TERMINATED",
0133 "BEGIN",
0134 "EXITTED",
0135 "SWITCHED_OUT",
0136 "SWITCHED_IN",
0137 "TIMESTAMP"
0138 };
0139
0140 void rtems_capture_set_extension_index(int index)
0141 {
0142 capture_extension_index = index;
0143 }
0144
0145 int rtems_capture_get_extension_index(void)
0146 {
0147 return capture_extension_index;
0148 }
0149
0150 uint32_t rtems_capture_get_flags(void)
0151 {
0152 return capture_flags_global;
0153 }
0154
0155 void rtems_capture_set_flags(uint32_t mask)
0156 {
0157 capture_flags_global |= mask;
0158 }
0159
0160
0161
0162
0163
0164 void
0165 rtems_capture_get_time (rtems_capture_time* time)
0166 {
0167 if (capture_timestamp)
0168 capture_timestamp (time);
0169 else
0170 {
0171 *time = rtems_clock_get_uptime_nanoseconds ();
0172 }
0173 }
0174
0175
0176
0177
0178
0179
0180 static inline bool
0181 rtems_capture_match_names (rtems_name lhs, rtems_name rhs)
0182 {
0183 return lhs == rhs;
0184 }
0185
0186
0187
0188
0189
0190
0191 static inline bool
0192 rtems_capture_match_ids (rtems_id lhs, rtems_id rhs)
0193 {
0194 return lhs == rhs;
0195 }
0196
0197
0198
0199
0200 static inline bool
0201 rtems_capture_match_name_id (rtems_name lhs_name,
0202 rtems_id lhs_id,
0203 rtems_name rhs_name,
0204 rtems_id rhs_id)
0205 {
0206 bool match_name;
0207
0208 match_name = ((rtems_capture_task_api(lhs_id) != OBJECTS_POSIX_API) &&
0209 (rtems_capture_task_api(rhs_id) != OBJECTS_POSIX_API));
0210
0211
0212
0213
0214 if ((lhs_name == 0) && (lhs_id == rhs_id))
0215 return true;
0216 else if (match_name && ((lhs_id == 0) || (lhs_id == rhs_id)))
0217 {
0218 if (rtems_capture_match_names (lhs_name, rhs_name))
0219 return true;
0220 }
0221 return false;
0222 }
0223
0224
0225
0226
0227
0228
0229 static inline void
0230 rtems_capture_dup_name (rtems_name* dst, rtems_name src)
0231 {
0232 *dst = src;
0233 }
0234
0235
0236
0237
0238
0239
0240 static inline bool
0241 rtems_capture_by_in_to (uint32_t events,
0242 rtems_tcb* by,
0243 rtems_capture_control* to)
0244 {
0245 uint32_t valid_mask = RTEMS_CAPTURE_CONTROL_FROM_MASK (0);
0246 uint32_t valid_remainder = 0xffffffff;
0247 int i;
0248
0249 for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
0250 {
0251
0252
0253
0254
0255 if ((valid_remainder & to->by_valid) == 0)
0256 break;
0257
0258
0259
0260
0261 if ((valid_mask & to->by_valid) &&
0262 (to->by[i].trigger & events))
0263 {
0264
0265
0266
0267
0268
0269 if (rtems_capture_match_name_id (to->by[i].name, to->by[i].id,
0270 rtems_capture_task_name( by ),
0271 by->Object.id))
0272 return 1;
0273 }
0274
0275 valid_mask >>= 1;
0276 valid_remainder >>= 1;
0277 }
0278
0279 return 0;
0280 }
0281
0282
0283
0284
0285 static inline rtems_capture_control*
0286 rtems_capture_find_control (rtems_name name, rtems_id id)
0287 {
0288 rtems_capture_control* control;
0289 for (control = capture_controls; control != NULL; control = control->next)
0290 if (rtems_capture_match_name_id (name, id, control->name, control->id))
0291 break;
0292 return control;
0293 }
0294
0295
0296
0297
0298
0299 static bool
0300 rtems_capture_initialize_control (rtems_tcb *tcb, void *arg)
0301 {
0302 if (tcb->Capture.control == NULL)
0303 {
0304 rtems_name name = rtems_build_name(0, 0, 0, 0);
0305 rtems_id id;
0306 rtems_capture_control* control;
0307
0308
0309
0310
0311
0312 id = tcb->Object.id;
0313 if (rtems_capture_task_api (id) != OBJECTS_POSIX_API)
0314 rtems_object_get_classic_name (id, &name);
0315 for (control = capture_controls; control != NULL; control = control->next)
0316 {
0317 if (rtems_capture_match_name_id (control->name, control->id,
0318 name, id))
0319 {
0320 tcb->Capture.control = control;
0321 break;
0322 }
0323 }
0324 }
0325
0326 return false;
0327 }
0328
0329 static rtems_capture_control*
0330 rtems_capture_create_control (rtems_name name, rtems_id id)
0331 {
0332 rtems_interrupt_lock_context lock_context;
0333 rtems_capture_control* control;
0334
0335 if ((name == 0) && (id == 0))
0336 return NULL;
0337
0338 control = rtems_capture_find_control (name, id);
0339
0340 if (control == NULL)
0341 {
0342 control = malloc (sizeof (*control));
0343
0344 if (!control)
0345 {
0346 capture_flags_global |= RTEMS_CAPTURE_NO_MEMORY;
0347 return NULL;
0348 }
0349
0350 control->name = name;
0351 control->id = id;
0352 control->flags = 0;
0353 control->to_triggers = 0;
0354 control->from_triggers = 0;
0355 control->by_valid = 0;
0356
0357 memset (control->by, 0, sizeof (control->by));
0358
0359 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0360
0361 control->next = capture_controls;
0362 capture_controls = control;
0363
0364 _Thread_Iterate (rtems_capture_initialize_control, NULL);
0365
0366 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0367 }
0368
0369 return control;
0370 }
0371
0372 void
0373 rtems_capture_record_lock (rtems_capture_record_lock_context* context)
0374 {
0375 rtems_capture_per_cpu_data* cpu;
0376 cpu = capture_per_cpu_get (rtems_scheduler_get_processor ());
0377 rtems_interrupt_lock_interrupt_disable (&context->lock_context);
0378 context->lock = &cpu->lock;
0379 rtems_interrupt_lock_acquire_isr (&cpu->lock, &context->lock_context);
0380 }
0381
0382 void
0383 rtems_capture_record_unlock (rtems_capture_record_lock_context* context)
0384 {
0385 rtems_interrupt_lock_release (context->lock, &context->lock_context);
0386 }
0387
0388 void*
0389 rtems_capture_record_open (rtems_tcb* tcb,
0390 uint32_t events,
0391 size_t size,
0392 rtems_capture_record_lock_context* context)
0393 {
0394 rtems_capture_per_cpu_data* cpu;
0395 uint8_t* ptr;
0396
0397 size += sizeof (rtems_capture_record);
0398
0399 cpu = capture_per_cpu_get (rtems_scheduler_get_processor ());
0400
0401 rtems_capture_record_lock (context);
0402
0403 ptr = rtems_capture_buffer_allocate (&cpu->records, size);
0404 if (ptr != NULL)
0405 {
0406 rtems_capture_record in;
0407 rtems_capture_time time;
0408
0409 ++cpu->count;
0410
0411 if ((events & RTEMS_CAPTURE_RECORD_EVENTS) == 0)
0412 tcb->Capture.flags |= RTEMS_CAPTURE_TRACED;
0413
0414
0415
0416
0417 in.size = size;
0418 in.task_id = tcb->Object.id;
0419 in.events = (events |
0420 rtems_capture_task_real_priority (tcb) |
0421 (rtems_capture_task_curr_priority (tcb) << 8));
0422
0423 rtems_capture_get_time (&time);
0424 in.time = time;
0425
0426 ptr = rtems_capture_record_append(ptr, &in, sizeof(in));
0427 }
0428 else
0429 cpu->flags |= RTEMS_CAPTURE_OVERFLOW;
0430
0431 return ptr;
0432 }
0433
0434 void
0435 rtems_capture_record_close (rtems_capture_record_lock_context* context)
0436 {
0437 rtems_capture_record_unlock (context);
0438 }
0439
0440 void
0441 rtems_capture_initialize_task( rtems_tcb* tcb )
0442 {
0443 rtems_capture_control* control;
0444 rtems_name name = rtems_build_name(0, 0, 0, 0);
0445 rtems_id id = rtems_capture_task_id (tcb);
0446 rtems_interrupt_lock_context lock_context;
0447
0448
0449
0450
0451
0452 if (rtems_capture_task_api (id) != OBJECTS_POSIX_API)
0453 rtems_object_get_classic_name (id, &name);
0454
0455 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0456
0457 if (tcb->Capture.control == NULL) {
0458 for (control = capture_controls; control != NULL; control = control->next)
0459 if (rtems_capture_match_name_id (control->name, control->id,
0460 name, id))
0461 tcb->Capture.control = control;
0462 }
0463
0464 tcb->Capture.flags |= RTEMS_CAPTURE_INIT_TASK;
0465
0466 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0467 }
0468
0469 void rtems_capture_record_task (rtems_tcb* tcb)
0470 {
0471 rtems_name name = rtems_build_name (0, 0, 0, 0);
0472 rtems_id id = rtems_capture_task_id (tcb);
0473 rtems_capture_task_record rec;
0474 void* ptr;
0475 rtems_interrupt_lock_context lock_context;
0476 rtems_capture_record_lock_context rec_context;
0477
0478 if (rtems_capture_task_api (id) != OBJECTS_POSIX_API)
0479 rtems_object_get_classic_name (id, &name);
0480
0481 rec.name = name;
0482 rec.stack_size = tcb->Start.Initial_stack.size;
0483 rec.start_priority = rtems_capture_task_start_priority (tcb);
0484
0485 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0486 tcb->Capture.flags |= RTEMS_CAPTURE_RECORD_TASK;
0487 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0488
0489
0490
0491
0492
0493 ptr = rtems_capture_record_open (tcb, 0, sizeof(rec), &rec_context);
0494 if (ptr != NULL)
0495 rtems_capture_record_append(ptr, &rec, sizeof (rec));
0496 rtems_capture_record_close (&rec_context);
0497 }
0498
0499
0500
0501
0502
0503 bool rtems_capture_filter (rtems_tcb* tcb, uint32_t events)
0504 {
0505 if (tcb &&
0506 ((capture_flags_global &
0507 (RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_ONLY_MONITOR)) ==
0508 RTEMS_CAPTURE_TRIGGERED))
0509 {
0510 rtems_capture_control* control;
0511
0512 control = tcb->Capture.control;
0513
0514
0515
0516
0517
0518
0519 if ((events & RTEMS_CAPTURE_RECORD_EVENTS) ||
0520 ((rtems_capture_task_real_priority (tcb) >= capture_ceiling) &&
0521 (rtems_capture_task_real_priority (tcb) <= capture_floor) &&
0522 ((capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH) ||
0523 (control && (control->flags & RTEMS_CAPTURE_WATCH)))))
0524 {
0525 return false;
0526 }
0527 }
0528
0529 return true;
0530 }
0531
0532
0533
0534
0535
0536 bool
0537 rtems_capture_trigger_fired (rtems_tcb* ft, rtems_tcb* tt, uint32_t events)
0538 {
0539
0540
0541
0542 if (!(capture_flags_global & RTEMS_CAPTURE_TRIGGERED))
0543 {
0544 rtems_capture_control* fc = NULL;
0545 rtems_capture_control* tc = NULL;
0546 uint32_t from_events = 0;
0547 uint32_t to_events = 0;
0548 uint32_t from_to_events = 0;
0549
0550 if (ft)
0551 {
0552 fc = ft->Capture.control;
0553 if (fc)
0554 from_events = fc->from_triggers & events;
0555 }
0556
0557 if (tt)
0558 {
0559 tc = tt->Capture.control;
0560 if (tc)
0561 {
0562 to_events = tc->to_triggers & events;
0563 if (ft && tc->by_valid)
0564 from_to_events = tc->by_triggers & events;
0565 }
0566 }
0567
0568
0569
0570
0571
0572
0573
0574
0575 if (from_events || to_events)
0576 {
0577 capture_flags_global |= RTEMS_CAPTURE_TRIGGERED;
0578 return true;
0579 }
0580
0581
0582
0583
0584 if (from_to_events)
0585 {
0586 if (rtems_capture_by_in_to (events, ft, tc))
0587 {
0588 capture_flags_global |= RTEMS_CAPTURE_TRIGGERED;
0589 return true;
0590 }
0591 }
0592
0593 return false;
0594 }
0595
0596 return true;
0597 }
0598
0599
0600
0601
0602
0603 rtems_status_code
0604 rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp RTEMS_UNUSED)
0605 {
0606 rtems_status_code sc = RTEMS_SUCCESSFUL;
0607 size_t count;
0608 uint32_t i;
0609 rtems_capture_buffer* buff;
0610
0611
0612
0613
0614
0615 if ((capture_flags_global & RTEMS_CAPTURE_INIT) == RTEMS_CAPTURE_INIT) {
0616 return RTEMS_RESOURCE_IN_USE;
0617 }
0618
0619 count = rtems_scheduler_get_processor_maximum();
0620 if (capture_per_cpu == NULL) {
0621 capture_per_cpu = calloc( count, sizeof( *capture_per_cpu ) );
0622 }
0623
0624 for (i=0; i<count; i++) {
0625 buff = &capture_records_on_cpu(i);
0626 rtems_capture_buffer_create( buff, size );
0627 if (buff->buffer == NULL) {
0628 sc = RTEMS_NO_MEMORY;
0629 break;
0630 }
0631
0632 rtems_interrupt_lock_initialize(
0633 &capture_lock_on_cpu( i ),
0634 "Capture Per-CPU"
0635 );
0636 }
0637
0638 capture_flags_global = 0;
0639 capture_ceiling = 0;
0640 capture_floor = 255;
0641 if (sc == RTEMS_SUCCESSFUL)
0642 sc = rtems_capture_user_extension_open();
0643
0644 if (sc != RTEMS_SUCCESSFUL)
0645 {
0646 for (i=0; i<count; i++)
0647 rtems_capture_buffer_destroy( &capture_records_on_cpu(i));
0648 } else {
0649 capture_flags_global |= RTEMS_CAPTURE_INIT;
0650 }
0651
0652 return sc;
0653 }
0654
0655
0656
0657
0658
0659 rtems_status_code
0660 rtems_capture_close (void)
0661 {
0662 rtems_interrupt_lock_context lock_context;
0663 rtems_capture_control* control;
0664 rtems_status_code sc;
0665 uint32_t cpu;
0666
0667 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0668
0669 if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT)
0670 {
0671 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0672 return RTEMS_SUCCESSFUL;
0673 }
0674
0675 if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
0676 {
0677 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0678 return RTEMS_UNSATISFIED;
0679 }
0680
0681 capture_flags_global &=
0682 ~(RTEMS_CAPTURE_ON | RTEMS_CAPTURE_ONLY_MONITOR | RTEMS_CAPTURE_INIT);
0683
0684 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0685
0686
0687
0688
0689
0690
0691 sc = rtems_capture_user_extension_close();
0692
0693 if (sc != RTEMS_SUCCESSFUL)
0694 return sc;
0695
0696 control = capture_controls;
0697
0698 while (control)
0699 {
0700 rtems_capture_control* delete = control;
0701 control = control->next;
0702 free (delete);
0703 }
0704
0705 capture_controls = NULL;
0706 for (cpu=0; cpu < rtems_scheduler_get_processor_maximum(); cpu++) {
0707 if (capture_records_on_cpu(cpu).buffer)
0708 rtems_capture_buffer_destroy( &capture_records_on_cpu(cpu) );
0709
0710 rtems_interrupt_lock_destroy( &capture_lock_on_cpu( cpu ) );
0711 }
0712
0713 free( capture_per_cpu );
0714 capture_per_cpu = NULL;
0715
0716 return RTEMS_SUCCESSFUL;
0717 }
0718
0719 rtems_status_code
0720 rtems_capture_set_control (bool enable)
0721 {
0722 rtems_interrupt_lock_context lock_context;
0723
0724 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0725
0726 if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT)
0727 {
0728 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0729 return RTEMS_UNSATISFIED;
0730 }
0731
0732 if (enable)
0733 capture_flags_global |= RTEMS_CAPTURE_ON;
0734 else
0735 capture_flags_global &= ~RTEMS_CAPTURE_ON;
0736
0737 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0738
0739 return RTEMS_SUCCESSFUL;
0740 }
0741
0742
0743
0744
0745
0746
0747 rtems_status_code
0748 rtems_capture_set_monitor (bool enable)
0749 {
0750 rtems_interrupt_lock_context lock_context;
0751
0752 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0753
0754 if ((capture_flags_global & RTEMS_CAPTURE_INIT) != RTEMS_CAPTURE_INIT)
0755 {
0756 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0757 return RTEMS_UNSATISFIED;
0758 }
0759
0760 if (enable)
0761 capture_flags_global |= RTEMS_CAPTURE_ONLY_MONITOR;
0762 else
0763 capture_flags_global &= ~RTEMS_CAPTURE_ONLY_MONITOR;
0764
0765 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0766
0767 return RTEMS_SUCCESSFUL;
0768 }
0769
0770
0771
0772
0773 static bool
0774 rtems_capture_flush_tcb (rtems_tcb *tcb, void *arg)
0775 {
0776 tcb->Capture.flags &= ~RTEMS_CAPTURE_TRACED;
0777 return false;
0778 }
0779
0780
0781
0782
0783
0784 rtems_status_code
0785 rtems_capture_flush (bool prime)
0786 {
0787 rtems_status_code sc = RTEMS_NOT_CONFIGURED;
0788 if (capture_per_cpu != NULL)
0789 {
0790 rtems_interrupt_lock_context lock_context_global;
0791 uint32_t cpu;
0792
0793 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context_global);
0794
0795 if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
0796 {
0797 rtems_interrupt_lock_release (&capture_lock_global, &lock_context_global);
0798 return RTEMS_UNSATISFIED;
0799 }
0800
0801 _Thread_Iterate (rtems_capture_flush_tcb, NULL);
0802
0803 if (prime)
0804 capture_flags_global &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
0805 else
0806 capture_flags_global &= ~RTEMS_CAPTURE_OVERFLOW;
0807
0808 for (cpu=0; cpu < rtems_scheduler_get_processor_maximum(); cpu++) {
0809 RTEMS_INTERRUPT_LOCK_REFERENCE( lock, &(capture_lock_on_cpu( cpu )) )
0810 rtems_interrupt_lock_context lock_context_per_cpu;
0811
0812 rtems_interrupt_lock_acquire (lock, &lock_context_per_cpu);
0813 capture_count_on_cpu(cpu) = 0;
0814 if (capture_records_on_cpu(cpu).buffer)
0815 rtems_capture_buffer_flush( &capture_records_on_cpu(cpu) );
0816 rtems_interrupt_lock_release (lock, &lock_context_per_cpu);
0817 }
0818
0819 rtems_interrupt_lock_release (&capture_lock_global, &lock_context_global);
0820
0821 sc = RTEMS_SUCCESSFUL;
0822 }
0823
0824 return sc;
0825 }
0826
0827
0828
0829
0830
0831
0832
0833 rtems_status_code
0834 rtems_capture_watch_add (rtems_name name, rtems_id id)
0835 {
0836 rtems_capture_control* control;
0837
0838 if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
0839 return RTEMS_UNSATISFIED;
0840
0841 if ((name == 0) && (id == 0))
0842 return RTEMS_UNSATISFIED;
0843
0844 control = rtems_capture_find_control (name, id);
0845
0846 if (control && !id)
0847 return RTEMS_TOO_MANY;
0848
0849 if (!control)
0850 control = rtems_capture_create_control (name, id);
0851
0852 if (!control)
0853 return RTEMS_NO_MEMORY;
0854
0855 return RTEMS_SUCCESSFUL;
0856 }
0857
0858
0859
0860
0861
0862
0863
0864 rtems_status_code
0865 rtems_capture_watch_del (rtems_name name, rtems_id id)
0866 {
0867 rtems_interrupt_lock_context lock_context;
0868 rtems_capture_control* control;
0869 rtems_capture_control** prev_control;
0870 bool found = false;
0871
0872 if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
0873 return RTEMS_UNSATISFIED;
0874
0875
0876
0877
0878
0879 for (prev_control = &capture_controls, control = capture_controls;
0880 control != NULL; )
0881 {
0882 if (rtems_capture_match_name_id (control->name, control->id, name, id))
0883 {
0884 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0885
0886 *prev_control = control->next;
0887
0888 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0889
0890 free (control);
0891
0892 control = *prev_control;
0893
0894 found = true;
0895 }
0896 else
0897 {
0898 prev_control = &control->next;
0899 control = control->next;
0900 }
0901 }
0902
0903 if (found)
0904 return RTEMS_SUCCESSFUL;
0905
0906 return RTEMS_INVALID_NAME;
0907 }
0908
0909
0910
0911
0912
0913 rtems_status_code
0914 rtems_capture_watch_ctrl (rtems_name name, rtems_id id, bool enable)
0915 {
0916 rtems_interrupt_lock_context lock_context;
0917 rtems_capture_control* control;
0918 bool found = false;
0919
0920 if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
0921 return RTEMS_UNSATISFIED;
0922
0923
0924
0925
0926
0927 for (control = capture_controls; control != NULL; control = control->next)
0928 {
0929 if (rtems_capture_match_name_id (control->name, control->id, name, id))
0930 {
0931 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0932
0933 if (enable)
0934 control->flags |= RTEMS_CAPTURE_WATCH;
0935 else
0936 control->flags &= ~RTEMS_CAPTURE_WATCH;
0937
0938 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0939
0940 found = true;
0941 }
0942 }
0943
0944 if (found)
0945 return RTEMS_SUCCESSFUL;
0946
0947 return RTEMS_INVALID_NAME;
0948 }
0949
0950
0951
0952
0953
0954
0955 rtems_status_code
0956 rtems_capture_watch_global (bool enable)
0957 {
0958 rtems_interrupt_lock_context lock_context;
0959
0960 rtems_interrupt_lock_acquire (&capture_lock_global, &lock_context);
0961
0962
0963
0964
0965
0966 if (enable)
0967 capture_flags_global |= RTEMS_CAPTURE_GLOBAL_WATCH;
0968 else
0969 capture_flags_global &= ~RTEMS_CAPTURE_GLOBAL_WATCH;
0970
0971 rtems_interrupt_lock_release (&capture_lock_global, &lock_context);
0972
0973 return RTEMS_SUCCESSFUL;
0974 }
0975
0976
0977
0978
0979 bool
0980 rtems_capture_watch_global_on (void)
0981 {
0982 return capture_flags_global & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0;
0983 }
0984
0985
0986
0987
0988
0989
0990
0991 rtems_status_code
0992 rtems_capture_watch_ceiling (rtems_task_priority ceiling)
0993 {
0994 capture_ceiling = ceiling;
0995 return RTEMS_SUCCESSFUL;
0996 }
0997
0998
0999
1000
1001 rtems_task_priority
1002 rtems_capture_watch_get_ceiling (void)
1003 {
1004 return capture_ceiling;
1005 }
1006
1007
1008
1009
1010
1011
1012
1013 rtems_status_code
1014 rtems_capture_watch_floor (rtems_task_priority floor)
1015 {
1016 capture_floor = floor;
1017 return RTEMS_SUCCESSFUL;
1018 }
1019
1020
1021
1022
1023 rtems_task_priority
1024 rtems_capture_watch_get_floor (void)
1025 {
1026 return capture_floor;
1027 }
1028
1029
1030
1031
1032 static uint32_t
1033 rtems_capture_map_trigger (rtems_capture_trigger trigger)
1034 {
1035
1036
1037
1038 switch (trigger)
1039 {
1040 case rtems_capture_switch:
1041 return RTEMS_CAPTURE_SWITCH;
1042 case rtems_capture_create:
1043 return RTEMS_CAPTURE_CREATE;
1044 case rtems_capture_start:
1045 return RTEMS_CAPTURE_START;
1046 case rtems_capture_restart:
1047 return RTEMS_CAPTURE_RESTART;
1048 case rtems_capture_delete:
1049 return RTEMS_CAPTURE_DELETE;
1050 case rtems_capture_begin:
1051 return RTEMS_CAPTURE_BEGIN;
1052 case rtems_capture_exitted:
1053 return RTEMS_CAPTURE_EXITTED;
1054 case rtems_capture_terminated:
1055 return RTEMS_CAPTURE_TERMINATED;
1056 default:
1057 break;
1058 }
1059 return 0;
1060 }
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 rtems_status_code
1074 rtems_capture_set_trigger (rtems_name from_name,
1075 rtems_id from_id,
1076 rtems_name to_name,
1077 rtems_id to_id,
1078 rtems_capture_trigger_mode mode,
1079 rtems_capture_trigger trigger)
1080 {
1081 rtems_capture_control* control;
1082 uint32_t flags;
1083
1084 flags = rtems_capture_map_trigger (trigger);
1085
1086
1087
1088
1089
1090
1091
1092 if (mode == rtems_capture_to_any)
1093 {
1094 control = rtems_capture_create_control (from_name, from_id);
1095 if (control == NULL)
1096 return RTEMS_NO_MEMORY;
1097 control->from_triggers |= flags & RTEMS_CAPTURE_FROM_TRIGS;
1098 }
1099 else
1100 {
1101 control = rtems_capture_create_control (to_name, to_id);
1102 if (control == NULL)
1103 return RTEMS_NO_MEMORY;
1104 if (mode == rtems_capture_from_any)
1105 control->to_triggers |= flags;
1106 else
1107 {
1108 bool done = false;
1109 int i;
1110
1111 control->by_triggers |= flags;
1112
1113 for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
1114 {
1115 if (rtems_capture_control_by_valid (control, i) &&
1116 ((control->by[i].name == from_name) ||
1117 (from_id && (control->by[i].id == from_id))))
1118 {
1119 control->by[i].trigger |= flags;
1120 done = true;
1121 break;
1122 }
1123 }
1124
1125 if (!done)
1126 {
1127 for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
1128 {
1129 if (!rtems_capture_control_by_valid (control, i))
1130 {
1131 control->by_valid |= RTEMS_CAPTURE_CONTROL_FROM_MASK (i);
1132 control->by[i].name = from_name;
1133 control->by[i].id = from_id;
1134 control->by[i].trigger = flags;
1135 done = true;
1136 break;
1137 }
1138 }
1139 }
1140
1141 if (!done)
1142 return RTEMS_TOO_MANY;
1143 }
1144 }
1145 return RTEMS_SUCCESSFUL;
1146 }
1147
1148
1149
1150
1151 rtems_status_code
1152 rtems_capture_clear_trigger (rtems_name from_name,
1153 rtems_id from_id,
1154 rtems_name to_name,
1155 rtems_id to_id,
1156 rtems_capture_trigger_mode mode,
1157 rtems_capture_trigger trigger)
1158 {
1159 rtems_capture_control* control;
1160 uint32_t flags;
1161
1162 flags = rtems_capture_map_trigger (trigger);
1163
1164 if (mode == rtems_capture_to_any)
1165 {
1166 control = rtems_capture_find_control (from_name, from_id);
1167 if (control == NULL)
1168 {
1169 if (from_id)
1170 return RTEMS_INVALID_ID;
1171 return RTEMS_INVALID_NAME;
1172 }
1173 control->from_triggers &= ~flags;
1174 }
1175 else
1176 {
1177 control = rtems_capture_find_control (to_name, to_id);
1178 if (control == NULL)
1179 {
1180 if (to_id)
1181 return RTEMS_INVALID_ID;
1182 return RTEMS_INVALID_NAME;
1183 }
1184 if (mode == rtems_capture_from_any)
1185 control->to_triggers &= ~flags;
1186 else
1187 {
1188 bool done = false;
1189 int i;
1190
1191 control->by_triggers &= ~flags;
1192
1193 for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
1194 {
1195 if (rtems_capture_control_by_valid (control, i) &&
1196 ((control->by[i].name == from_name) ||
1197 (control->by[i].id == from_id)))
1198 {
1199 control->by[i].trigger &= ~trigger;
1200 if (control->by[i].trigger == 0)
1201 control->by_valid &= ~RTEMS_CAPTURE_CONTROL_FROM_MASK (i);
1202 done = true;
1203 break;
1204 }
1205 }
1206
1207 if (!done)
1208 {
1209 if (from_id)
1210 return RTEMS_INVALID_ID;
1211 return RTEMS_INVALID_NAME;
1212 }
1213 }
1214 }
1215 return RTEMS_SUCCESSFUL;
1216 }
1217
1218 static inline uint32_t
1219 rtems_capture_count_records (const void* records, size_t size)
1220 {
1221 const uint8_t* ptr = records;
1222 uint32_t recs = 0;
1223 size_t bytes = 0;
1224
1225 while (bytes < size)
1226 {
1227 const rtems_capture_record* rec = (const rtems_capture_record*) ptr;
1228 recs++;
1229 ptr += rec->size;
1230 bytes += rec->size;
1231 }
1232
1233 return recs;
1234 }
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250 rtems_status_code
1251 rtems_capture_read (uint32_t cpu, size_t* read, const void** recs)
1252 {
1253 rtems_status_code sc = RTEMS_NOT_CONFIGURED;
1254 if (capture_per_cpu != NULL)
1255 {
1256 RTEMS_INTERRUPT_LOCK_REFERENCE (lock, &(capture_lock_on_cpu (cpu)))
1257 rtems_interrupt_lock_context lock_context;
1258 size_t recs_size = 0;
1259 rtems_capture_buffer* records;
1260 uint32_t* flags;
1261
1262 *read = 0;
1263 *recs = NULL;
1264
1265 records = &(capture_records_on_cpu (cpu));
1266 flags = &(capture_flags_on_cpu (cpu));
1267
1268 rtems_interrupt_lock_acquire (lock, &lock_context);
1269
1270
1271
1272
1273
1274 if (*flags & RTEMS_CAPTURE_READER_ACTIVE)
1275 {
1276 rtems_interrupt_lock_release (lock, &lock_context);
1277 return RTEMS_RESOURCE_IN_USE;
1278 }
1279
1280 if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 )
1281 {
1282 rtems_interrupt_lock_release (lock, &lock_context);
1283 return RTEMS_UNSATISFIED;
1284 }
1285
1286 *flags |= RTEMS_CAPTURE_READER_ACTIVE;
1287
1288 *recs = rtems_capture_buffer_peek( records, &recs_size );
1289
1290 *read = rtems_capture_count_records( *recs, recs_size );
1291
1292 rtems_interrupt_lock_release (lock, &lock_context);
1293
1294 sc = RTEMS_SUCCESSFUL;
1295 }
1296
1297 return sc;
1298 }
1299
1300
1301
1302
1303
1304 rtems_status_code
1305 rtems_capture_release (uint32_t cpu, uint32_t count)
1306 {
1307 rtems_status_code sc = RTEMS_NOT_CONFIGURED;
1308 if (capture_per_cpu != NULL)
1309 {
1310 rtems_interrupt_lock_context lock_context;
1311 uint8_t* ptr;
1312 rtems_capture_record* rec;
1313 uint32_t counted;
1314 size_t ptr_size = 0;
1315 size_t rel_size = 0;
1316 RTEMS_INTERRUPT_LOCK_REFERENCE( lock, &(capture_lock_on_cpu( cpu )) )
1317 rtems_capture_buffer* records = &(capture_records_on_cpu( cpu ));
1318 uint32_t* flags = &(capture_flags_on_cpu( cpu ));
1319 uint32_t* total = &(capture_count_on_cpu( cpu ));
1320
1321 sc = RTEMS_SUCCESSFUL;
1322
1323 rtems_interrupt_lock_acquire (lock, &lock_context);
1324
1325 if (count > *total) {
1326 count = *total;
1327 }
1328
1329 if ( (capture_flags_global & RTEMS_CAPTURE_ON) != 0 ) {
1330 rtems_interrupt_lock_release (lock, &lock_context);
1331 return RTEMS_UNSATISFIED;
1332 }
1333
1334 counted = count;
1335
1336 ptr = rtems_capture_buffer_peek( records, &ptr_size );
1337 _Assert(ptr_size >= (count * sizeof(*rec) ));
1338
1339 rel_size = 0;
1340 while (counted--) {
1341 rec = (rtems_capture_record*) ptr;
1342 rel_size += rec->size;
1343 _Assert( rel_size <= ptr_size );
1344 ptr += rec->size;
1345 }
1346
1347 if (rel_size > ptr_size ) {
1348 sc = RTEMS_INVALID_NUMBER;
1349 rel_size = ptr_size;
1350 }
1351
1352 *total -= count;
1353
1354 if (count) {
1355 rtems_capture_buffer_free( records, rel_size );
1356 }
1357
1358 *flags &= ~RTEMS_CAPTURE_READER_ACTIVE;
1359
1360 rtems_interrupt_lock_release (lock, &lock_context);
1361 }
1362
1363 return sc;
1364 }
1365
1366
1367
1368
1369
1370
1371 const char*
1372 rtems_capture_event_text (int event)
1373 {
1374 if ((event < RTEMS_CAPTURE_EVENT_START) || (event > RTEMS_CAPTURE_EVENT_END))
1375 return "invalid event id";
1376 return capture_event_text[event - RTEMS_CAPTURE_EVENT_START];
1377 }
1378
1379
1380
1381
1382
1383 rtems_capture_control*
1384 rtems_capture_get_control_list (void)
1385 {
1386 return capture_controls;
1387 }