1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** ThreadX Component */
16 /** */
17 /** ThreadX/GHS Event Log (EL) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define TX_SOURCE_CODE
23 #define TX_EL_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "tx_api.h"
29 #include "tx_el.h"
30 #include "string.h"
31
32
33 /* Define global variables used to manage the event pool. */
34
35 UCHAR *_tx_el_tni_start;
36 UCHAR **_tx_el_current_event;
37 UCHAR *_tx_el_event_area_start;
38 UCHAR *_tx_el_event_area_end;
39 UINT _tx_el_maximum_events;
40 ULONG _tx_el_total_events;
41 UINT _tx_el_event_filter;
42 ULONG _tx_el_time_base_upper;
43 ULONG _tx_el_time_base_lower;
44
45 extern char __ghsbegin_eventlog[];
46 extern char __ghsend_eventlog[];
47
48 extern TX_THREAD *_tx_thread_current_ptr;
49 UINT _tx_thread_interrupt_control(UINT new_posture);
50
51
52 /**************************************************************************/
53 /* */
54 /* FUNCTION RELEASE */
55 /* */
56 /* _tx_el_initialize PORTABLE C */
57 /* 6.1 */
58 /* AUTHOR */
59 /* */
60 /* William E. Lamie, Microsoft Corporation */
61 /* */
62 /* DESCRIPTION */
63 /* */
64 /* This function creates the Event Log (in the format dictated by the */
65 /* GHS Event Analyzer) and sets up various information for subsequent */
66 /* operation. The start and end of the Event Log is determined by the */
67 /* .eventlog section in the linker control file. */
68 /* */
69 /* INPUT */
70 /* */
71 /* None */
72 /* */
73 /* OUTPUT */
74 /* */
75 /* None */
76 /* */
77 /* CALLS */
78 /* */
79 /* None */
80 /* */
81 /* CALLED BY */
82 /* */
83 /* Application Code */
84 /* */
85 /* RELEASE HISTORY */
86 /* */
87 /* DATE NAME DESCRIPTION */
88 /* */
89 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
90 /* */
91 /**************************************************************************/
_tx_el_initialize(VOID)92 VOID _tx_el_initialize(VOID)
93 {
94
95 UCHAR *work_ptr;
96 UCHAR *read_ptr;
97 ULONG event_log_size;
98 UCHAR *end_ptr;
99 UINT i;
100
101
102 /* Clear total event counter. */
103 _tx_el_total_events = 0;
104
105 /* Clear event filter. */
106 _tx_el_event_filter = 0;
107
108 /* First, pickup the starting and ending address of the Event Log memory. */
109 work_ptr = (unsigned char *) __ghsbegin_eventlog;
110 end_ptr = (unsigned char *) __ghsend_eventlog;
111
112 /* Calculate the event log size. */
113 event_log_size = end_ptr - work_ptr;
114
115 /* Subtract off the number of bytes in the header and the TNI area. */
116 event_log_size = event_log_size - (TX_EL_HEADER_SIZE +
117 (TX_EL_TNI_ENTRY_SIZE * TX_EL_TNIS));
118
119 /* Make sure the event log is evenly divisible by the event size. */
120 event_log_size = (event_log_size/TX_EL_EVENT_SIZE) * TX_EL_EVENT_SIZE;
121
122 /* Build the Event Log header. */
123
124 /* Setup the Event Log Version ID. */
125 *((unsigned short *) work_ptr) = (unsigned short) TX_EL_VERSION_ID;
126 work_ptr = work_ptr + sizeof(unsigned short);
127
128 /* Setup the TNIS (number of thread names) field. */
129 *((unsigned short *) work_ptr) = (unsigned short) TX_EL_TNIS;
130 work_ptr = work_ptr + sizeof(unsigned short);
131
132 /* Setup the EVPS (event pool size) field. */
133 *((ULONG *) work_ptr) = event_log_size;
134 work_ptr = work_ptr + sizeof(ULONG);
135
136 /* Remember the maximum number of events. */
137 _tx_el_maximum_events = event_log_size/TX_EL_EVENT_SIZE;
138
139 /* Setup max_events field. */
140 *((ULONG *) work_ptr) = _tx_el_maximum_events;
141 work_ptr = work_ptr + sizeof(ULONG);
142
143 /* Setup the evploc (location of event pool). */
144 *((ULONG *) work_ptr) = (ULONG) (((ULONG) __ghsbegin_eventlog) + TX_EL_HEADER_SIZE +
145 (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
146 work_ptr = work_ptr + sizeof(ULONG);
147
148 /* Save the current event pointer. */
149 _tx_el_current_event = (UCHAR **) work_ptr;
150
151 /* Setup event_ptr (pointer to oldest event) field to the start
152 of the event pool. */
153 *_tx_el_current_event = (UCHAR *) (((ULONG) __ghsbegin_eventlog) + TX_EL_HEADER_SIZE +
154 (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
155 work_ptr = work_ptr + sizeof(ULONG);
156
157 /* Setup tbfreq (the number of ticks in a second) field. */
158 *((ULONG *) work_ptr) = TX_EL_TICKS_PER_SECOND;
159 work_ptr = work_ptr + sizeof(ULONG);
160
161 /* At this point we are pointing at the Thread Name Information (TNI) array. */
162
163 /* Remember the start of this for future updates. */
164 _tx_el_tni_start = work_ptr;
165
166 /* Clear the entire TNI array, this is the initial setting. */
167 end_ptr = work_ptr + (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE);
168 memset((void *)work_ptr, 0, (TX_EL_TNIS * TX_EL_TNI_ENTRY_SIZE));
169 work_ptr = end_ptr;
170
171 /* At this point, we are pointing at the actual Event Entry area. */
172
173 /* Remember the start of the actual event log area. */
174 _tx_el_event_area_start = work_ptr;
175
176 /* Clear the entire Event area. */
177 end_ptr = work_ptr + event_log_size;
178 memset((void *)work_ptr, 0, event_log_size);
179 work_ptr = end_ptr;
180
181 /* Save the end pointer for later use. */
182 _tx_el_event_area_end = work_ptr;
183
184 /* Setup an entry to resolve all activities from initialization and from
185 an idle system. */
186 work_ptr = _tx_el_tni_start;
187 read_ptr = (UCHAR *) "Initialization/System Idle";
188 i = 0;
189 while ((i < TX_EL_TNI_NAME_SIZE) && (*read_ptr))
190 {
191
192 /* Copy a character of thread's name into TNI area of log. */
193 *work_ptr++ = *read_ptr++;
194
195 /* Increment the character count. */
196 i++;
197 }
198
199 /* Determine if a NULL needs to be inserted. */
200 if (i < TX_EL_TNI_NAME_SIZE)
201 {
202
203 /* Yes, insert a NULL into the event log string. */
204 *work_ptr = (unsigned char) 0;
205 }
206
207 /* Setup the thread ID to NULL. */
208 *((ULONG *) (_tx_el_tni_start + TX_EL_TNI_THREAD_ID_OFFSET)) = (ULONG) TX_NULL;
209
210 /* Set the valid field to indicate the entry is complete. */
211 *((UCHAR *) (_tx_el_tni_start + TX_EL_TNI_VALID_OFFSET)) = (ULONG) TX_EL_VALID_ENTRY;
212
213 /* Clear the time base global variables. */
214 _tx_el_time_base_upper = 0;
215 _tx_el_time_base_lower = 0;
216 }
217
218
219 /**************************************************************************/
220 /* */
221 /* FUNCTION RELEASE */
222 /* */
223 /* _tx_el_thread_register PORTABLE C */
224 /* 6.1 */
225 /* AUTHOR */
226 /* */
227 /* William E. Lamie, Microsoft Corporation */
228 /* */
229 /* DESCRIPTION */
230 /* */
231 /* This function registers a thread in the event log for future */
232 /* display purposes. */
233 /* */
234 /* INPUT */
235 /* */
236 /* thread_ptr Pointer to thread control block */
237 /* */
238 /* OUTPUT */
239 /* */
240 /* TX_SUCCESS Thread was placed in TNI area */
241 /* TX_ERROR No more room in the TNI area */
242 /* */
243 /* CALLS */
244 /* */
245 /* None */
246 /* */
247 /* CALLED BY */
248 /* */
249 /* _tx_thread_create ThreadX thread create function */
250 /* */
251 /* RELEASE HISTORY */
252 /* */
253 /* DATE NAME DESCRIPTION */
254 /* */
255 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
256 /* */
257 /**************************************************************************/
_tx_el_thread_register(TX_THREAD * thread_ptr)258 UINT _tx_el_thread_register(TX_THREAD *thread_ptr)
259 {
260
261 UCHAR *entry_ptr;
262 UCHAR *work_ptr;
263 UCHAR *read_ptr;
264 UINT i;
265
266
267 /* First of all, search for a free slot in the TNI area. */
268 entry_ptr = _tx_el_tni_start;
269 i = 0;
270 while (i < TX_EL_TNIS)
271 {
272
273 /* Determine if this entry is available. */
274 if (*(entry_ptr + TX_EL_TNI_VALID_OFFSET) == TX_EL_INVALID_ENTRY)
275 break;
276
277 /* Otherwise, increment the associated pointers and indices. */
278 i++;
279 entry_ptr = entry_ptr + TX_EL_TNI_ENTRY_SIZE;
280 }
281
282 /* Check to see if there were no more valid entries. */
283 if (i >= TX_EL_TNIS)
284 return(TX_EL_NO_MORE_TNI_ROOM);
285
286 /* Otherwise, we have room in the TNI and a valid record. */
287
288 /* Setup the thread's name. */
289 work_ptr = entry_ptr;
290 read_ptr = (UCHAR *) thread_ptr -> tx_thread_name;
291 i = 0;
292 while ((i < TX_EL_TNI_NAME_SIZE) && (*read_ptr))
293 {
294
295 /* Copy a character of thread's name into TNI area of log. */
296 *work_ptr++ = *read_ptr++;
297
298 /* Increment the character count. */
299 i++;
300 }
301
302 /* Determine if a NULL needs to be inserted. */
303 if (i < TX_EL_TNI_NAME_SIZE)
304 {
305
306 /* Yes, insert a NULL into the event log string. */
307 *work_ptr = (unsigned char) 0;
308 }
309
310 /* Setup the thread ID. */
311 *((ULONG *) (entry_ptr + TX_EL_TNI_THREAD_ID_OFFSET)) = (ULONG) thread_ptr;
312
313 /* Setup the thread priority. */
314 *((ULONG *) (entry_ptr + TX_EL_TNI_THREAD_PRIORITY_OFF)) = (ULONG) thread_ptr -> tx_thread_priority;
315
316 /* Set the valid field to indicate the entry is complete. */
317 *((UCHAR *) (entry_ptr + TX_EL_TNI_VALID_OFFSET)) = (ULONG) TX_EL_VALID_ENTRY;
318
319 /* Thread name has been registered. */
320 return(TX_SUCCESS);
321 }
322
323
324 /**************************************************************************/
325 /* */
326 /* FUNCTION RELEASE */
327 /* */
328 /* _tx_el_thread_unregister PORTABLE C */
329 /* 6.1 */
330 /* AUTHOR */
331 /* */
332 /* William E. Lamie, Microsoft Corporation */
333 /* */
334 /* DESCRIPTION */
335 /* */
336 /* This function unregisters a thread in the event log for future */
337 /* display purposes. */
338 /* */
339 /* INPUT */
340 /* */
341 /* thread_ptr Pointer to thread control block */
342 /* */
343 /* OUTPUT */
344 /* */
345 /* TX_SUCCESS Thread was placed in TNI area */
346 /* TX_ERROR No more room in the TNI area */
347 /* */
348 /* CALLS */
349 /* */
350 /* None */
351 /* */
352 /* CALLED BY */
353 /* */
354 /* _tx_thread_create ThreadX thread create function */
355 /* */
356 /* RELEASE HISTORY */
357 /* */
358 /* DATE NAME DESCRIPTION */
359 /* */
360 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
361 /* */
362 /**************************************************************************/
_tx_el_thread_unregister(TX_THREAD * thread_ptr)363 UINT _tx_el_thread_unregister(TX_THREAD *thread_ptr)
364 {
365
366 UCHAR *entry_ptr;
367 UCHAR *work_ptr;
368 UCHAR *read_ptr;
369 UINT found;
370 UINT i, j;
371
372
373 /* First of all, search for a match in the TNI area. */
374 entry_ptr = _tx_el_tni_start;
375 i = 0;
376 while (i < TX_EL_TNIS)
377 {
378
379 /* Determine if this entry is a match. */
380 work_ptr = entry_ptr;
381 read_ptr = (UCHAR *) thread_ptr -> tx_thread_name;
382 found = TX_TRUE;
383 j = 0;
384 do
385 {
386
387 /* Determine if this character is the same. */
388 if (*work_ptr != *read_ptr)
389 {
390
391 /* Set found to false and fall out of the loop. */
392 found = TX_FALSE;
393 break;
394 }
395 else if (*work_ptr == 0)
396 {
397
398 /* Null terminated, just break the loop. */
399 break;
400 }
401 else
402 {
403
404 /* Copy a character of thread's name into TNI area of log. */
405 *work_ptr++ = *read_ptr++;
406 }
407
408 /* Increment the character count. */
409 j++;
410
411 } while(j < TX_EL_TNIS);
412
413
414 /* Was a match found? */
415 if (found)
416 {
417
418 /* Yes, mark the entry as available now. */
419 *(entry_ptr + TX_EL_TNI_VALID_OFFSET) = TX_EL_INVALID_ENTRY;
420
421 /* Get out of the loop! */
422 break;
423 }
424
425 /* Otherwise, increment the associated pointers and indices. */
426 i++;
427 entry_ptr = entry_ptr + TX_EL_TNI_ENTRY_SIZE;
428 }
429
430 /* Determine status to return. */
431 if (found)
432 return(TX_SUCCESS);
433 else
434 return(TX_EL_NAME_NOT_FOUND);
435 }
436
437
438 /**************************************************************************/
439 /* */
440 /* FUNCTION RELEASE */
441 /* */
442 /* _tx_el_user_event_insert PORTABLE C */
443 /* 6.1 */
444 /* AUTHOR */
445 /* */
446 /* William E. Lamie, Microsoft Corporation */
447 /* */
448 /* DESCRIPTION */
449 /* */
450 /* This function inserts a user event into the event log. */
451 /* If the event log is full, the oldest event is overwritten. */
452 /* */
453 /* INPUT */
454 /* */
455 /* sub_type Event subtype for kernel call */
456 /* info_1 First information field */
457 /* info_2 Second information field */
458 /* info_3 Third information field */
459 /* info_4 Fourth information field */
460 /* */
461 /* OUTPUT */
462 /* */
463 /* None */
464 /* */
465 /* CALLS */
466 /* */
467 /* None */
468 /* */
469 /* CALLED BY */
470 /* */
471 /* ThreadX services */
472 /* */
473 /* RELEASE HISTORY */
474 /* */
475 /* DATE NAME DESCRIPTION */
476 /* */
477 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
478 /* */
479 /**************************************************************************/
_tx_el_user_event_insert(UINT sub_type,ULONG info_1,ULONG info_2,ULONG info_3,ULONG info_4)480 VOID _tx_el_user_event_insert(UINT sub_type, ULONG info_1, ULONG info_2,
481 ULONG info_3, ULONG info_4)
482 {
483
484 TX_INTERRUPT_SAVE_AREA
485
486 UINT upper_tb;
487 UCHAR *entry_ptr;
488
489 /* Disable interrupts. */
490 TX_DISABLE
491
492 /* Increment total event counter. */
493 _tx_el_total_events++;
494
495 /* Setup working entry pointer first. */
496 entry_ptr = *_tx_el_current_event;
497
498 /* Store the event type. */
499 *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_USER_EVENT;
500
501 /* Store the event subtype. */
502 *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
503 (unsigned short) sub_type;
504
505 /* Get time stamp. */
506 do
507 {
508
509 /* Pickup the upper tb. */
510 upper_tb = (ULONG) read_tbu();
511
512 /* Store the upper time stamp. */
513 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
514 (ULONG) upper_tb;
515
516 /* Store the lower time stamp. */
517 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
518 (ULONG) read_tbl();
519 } while (upper_tb != (ULONG) read_tbu());
520
521 /* Store the current thread. */
522 *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
523 (ULONG) _tx_thread_current_ptr;
524
525 /* Store the first info field. */
526 *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
527 (ULONG) info_1;
528
529 /* Store the second info field. */
530 *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_2_OFFSET)) =
531 (ULONG) info_2;
532
533 /* Store the third info field. */
534 *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_3_OFFSET)) =
535 (ULONG) info_3;
536
537 /* Store the fourth info field. */
538 *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_4_OFFSET)) =
539 (ULONG) info_4;
540
541 /* Now move the current event log pointer. */
542 entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
543
544 /* Check for a wraparound condition. */
545 if (entry_ptr >= _tx_el_event_area_end)
546 {
547
548 /* Yes, we have wrapped around to the end of the event area.
549 Start back at the top! */
550 entry_ptr = _tx_el_event_area_start;
551 }
552
553 /* Write the entry pointer back into the header. */
554 *_tx_el_current_event = entry_ptr;
555
556 /* Restore interrupts. */
557 TX_RESTORE
558 }
559
560
561 /**************************************************************************/
562 /* */
563 /* FUNCTION RELEASE */
564 /* */
565 /* _tx_el_thread_running PORTABLE C */
566 /* 6.1 */
567 /* AUTHOR */
568 /* */
569 /* William E. Lamie, Microsoft Corporation */
570 /* */
571 /* DESCRIPTION */
572 /* */
573 /* This function inserts a thread change event into the event */
574 /* log, which indicates that a context switch is taking place. */
575 /* If the event log is full, the oldest event is overwritten. */
576 /* */
577 /* INPUT */
578 /* */
579 /* thread_ptr Pointer to thread being */
580 /* scheduled */
581 /* */
582 /* OUTPUT */
583 /* */
584 /* None */
585 /* */
586 /* CALLS */
587 /* */
588 /* None */
589 /* */
590 /* CALLED BY */
591 /* */
592 /* _tx_thread_schedule ThreadX scheduler */
593 /* */
594 /* RELEASE HISTORY */
595 /* */
596 /* DATE NAME DESCRIPTION */
597 /* */
598 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
599 /* */
600 /**************************************************************************/
_tx_el_thread_running(TX_THREAD * thread_ptr)601 VOID _tx_el_thread_running(TX_THREAD *thread_ptr)
602 {
603
604 UINT upper_tb;
605 UCHAR *entry_ptr;
606
607 TX_EL_NO_STATUS_EVENTS
608
609 /* Increment total event counter. */
610 _tx_el_total_events++;
611
612 /* Setup working entry pointer first. */
613 entry_ptr = *_tx_el_current_event;
614
615 /* Store the event type. */
616 *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_THREAD_CHANGE;
617
618 /* Store the event subtype. */
619 *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
620 (unsigned short) 0;
621
622 /* Get time stamp. */
623 do
624 {
625
626 /* Pickup the upper tb. */
627 upper_tb = (ULONG) read_tbu();
628
629 /* Store the upper time stamp. */
630 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
631 (ULONG) upper_tb;
632
633 /* Store the lower time stamp. */
634 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
635 (ULONG) read_tbl();
636 } while (upper_tb != (ULONG) read_tbu());
637
638 /* Store the current thread. */
639 *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
640 (ULONG) thread_ptr;
641
642 /* Now move the current event log pointer. */
643 entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
644
645 /* Check for a wraparound condition. */
646 if (entry_ptr >= _tx_el_event_area_end)
647 {
648
649 /* Yes, we have wrapped around to the end of the event area.
650 Start back at the top! */
651 entry_ptr = _tx_el_event_area_start;
652 }
653
654 /* Write the entry pointer back into the header. */
655 *_tx_el_current_event = entry_ptr;
656
657 TX_EL_END_FILTER
658 }
659
660
661 /**************************************************************************/
662 /* */
663 /* FUNCTION RELEASE */
664 /* */
665 /* _tx_el_thread_preempted PORTABLE C */
666 /* 6.1 */
667 /* AUTHOR */
668 /* */
669 /* William E. Lamie, Microsoft Corporation */
670 /* */
671 /* DESCRIPTION */
672 /* */
673 /* This function inserts a thread preempted event into the event */
674 /* log, which indicates that an interrupt occurred that made a higher */
675 /* priority thread ready for execution. In this case, the previously */
676 /* executing thread has an event entered to indicate it is no longer */
677 /* running. */
678 /* */
679 /* INPUT */
680 /* */
681 /* thread_ptr Pointer to thread being */
682 /* scheduled */
683 /* */
684 /* OUTPUT */
685 /* */
686 /* None */
687 /* */
688 /* CALLS */
689 /* */
690 /* None */
691 /* */
692 /* CALLED BY */
693 /* */
694 /* _tx_thread_context_restore ThreadX context restore */
695 /* */
696 /* RELEASE HISTORY */
697 /* */
698 /* DATE NAME DESCRIPTION */
699 /* */
700 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
701 /* */
702 /**************************************************************************/
_tx_el_thread_preempted(TX_THREAD * thread_ptr)703 VOID _tx_el_thread_preempted(TX_THREAD *thread_ptr)
704 {
705
706 UINT upper_tb;
707 UCHAR *entry_ptr;
708
709
710 TX_EL_NO_STATUS_EVENTS
711
712 /* Increment total event counter. */
713 _tx_el_total_events++;
714
715 /* Setup working entry pointer first. */
716 entry_ptr = *_tx_el_current_event;
717
718 /* Store the event type. */
719 *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_THREAD_STATUS_CHANGE;
720
721 /* Store the event subtype. */
722 *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
723 (unsigned short) TX_READY;
724
725 /* Get time stamp. */
726 do
727 {
728
729 /* Pickup the upper tb. */
730 upper_tb = (ULONG) read_tbu();
731
732 /* Store the upper time stamp. */
733 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
734 (ULONG) upper_tb;
735
736 /* Store the lower time stamp. */
737 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
738 (ULONG) read_tbl();
739 } while (upper_tb != (ULONG) read_tbu());
740
741 /* Store the current thread. */
742 *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
743 (ULONG) _tx_thread_current_ptr;
744
745 /* Now move the current event log pointer. */
746 entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
747
748 /* Check for a wraparound condition. */
749 if (entry_ptr >= _tx_el_event_area_end)
750 {
751
752 /* Yes, we have wrapped around to the end of the event area.
753 Start back at the top! */
754 entry_ptr = _tx_el_event_area_start;
755 }
756
757 /* Write the entry pointer back into the header. */
758 *_tx_el_current_event = entry_ptr;
759
760 TX_EL_END_FILTER
761 }
762
763
764 /**************************************************************************/
765 /* */
766 /* FUNCTION RELEASE */
767 /* */
768 /* _tx_el_interrupt PORTABLE C */
769 /* 6.1 */
770 /* AUTHOR */
771 /* */
772 /* William E. Lamie, Microsoft Corporation */
773 /* */
774 /* DESCRIPTION */
775 /* */
776 /* This function inserts an interrupt event into the log, which */
777 /* indicates the start of interrupt processing for the specific */
778 /* */
779 /* INPUT */
780 /* */
781 /* interrupt_number Interrupt number supplied by */
782 /* ISR */
783 /* */
784 /* OUTPUT */
785 /* */
786 /* None */
787 /* */
788 /* CALLS */
789 /* */
790 /* None */
791 /* */
792 /* CALLED BY */
793 /* */
794 /* ISR processing */
795 /* */
796 /* RELEASE HISTORY */
797 /* */
798 /* DATE NAME DESCRIPTION */
799 /* */
800 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
801 /* */
802 /**************************************************************************/
_tx_el_interrupt(UINT interrupt_number)803 VOID _tx_el_interrupt(UINT interrupt_number)
804 {
805
806 UINT upper_tb;
807 UCHAR *entry_ptr;
808
809
810 TX_EL_NO_INTERRUPT_EVENTS
811
812 /* Increment total event counter. */
813 _tx_el_total_events++;
814
815 /* Setup working entry pointer first. */
816 entry_ptr = *_tx_el_current_event;
817
818 /* Store the event type. */
819 *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_INTERRUPT;
820
821 /* Store the event subtype. */
822 *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
823 (unsigned short) TX_EL_INTERRUPT_SUB_TYPE;
824
825 /* Get time stamp. */
826 do
827 {
828
829 /* Pickup the upper tb. */
830 upper_tb = (ULONG) read_tbu();
831
832 /* Store the upper time stamp. */
833 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
834 (ULONG) upper_tb;
835
836 /* Store the lower time stamp. */
837 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
838 (ULONG) read_tbl();
839 } while (upper_tb != (ULONG) read_tbu());
840
841 /* Store the current thread. */
842 *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
843 (ULONG) _tx_thread_current_ptr;
844
845 /* Store the first info word. */
846 *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
847 (ULONG) interrupt_number;
848
849 /* Now move the current event log pointer. */
850 entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
851
852 /* Check for a wraparound condition. */
853 if (entry_ptr >= _tx_el_event_area_end)
854 {
855
856 /* Yes, we have wrapped around to the end of the event area.
857 Start back at the top! */
858 entry_ptr = _tx_el_event_area_start;
859 }
860
861 /* Write the entry pointer back into the header. */
862 *_tx_el_current_event = entry_ptr;
863
864 TX_EL_END_FILTER
865 }
866
867
868 /**************************************************************************/
869 /* */
870 /* FUNCTION RELEASE */
871 /* */
872 /* _tx_el_interrupt_end PORTABLE C */
873 /* 6.1 */
874 /* AUTHOR */
875 /* */
876 /* William E. Lamie, Microsoft Corporation */
877 /* */
878 /* DESCRIPTION */
879 /* */
880 /* This function inserts an interrupt end event into the log, which */
881 /* indicates the end of interrupt processing for the specific */
882 /* */
883 /* INPUT */
884 /* */
885 /* interrupt_number Interrupt number supplied by */
886 /* ISR */
887 /* */
888 /* OUTPUT */
889 /* */
890 /* None */
891 /* */
892 /* CALLS */
893 /* */
894 /* None */
895 /* */
896 /* CALLED BY */
897 /* */
898 /* ISR processing */
899 /* */
900 /* RELEASE HISTORY */
901 /* */
902 /* DATE NAME DESCRIPTION */
903 /* */
904 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
905 /* */
906 /**************************************************************************/
_tx_el_interrupt_end(UINT interrupt_number)907 VOID _tx_el_interrupt_end(UINT interrupt_number)
908 {
909
910 UINT upper_tb;
911 UCHAR *entry_ptr;
912
913
914 TX_EL_NO_INTERRUPT_EVENTS
915
916 /* Increment total event counter. */
917 _tx_el_total_events++;
918
919 /* Setup working entry pointer first. */
920 entry_ptr = *_tx_el_current_event;
921
922 /* Store the event type. */
923 *((unsigned short *) entry_ptr) = (unsigned short) TX_EL_INTERRUPT;
924
925 /* Store the event subtype. */
926 *((unsigned short *) (entry_ptr + TX_EL_EVENT_SUBTYPE_OFFSET)) =
927 (unsigned short) TX_EL_END_OF_INTERRUPT;
928
929 /* Get time stamp. */
930 do
931 {
932
933 /* Pickup the upper tb. */
934 upper_tb = (ULONG) read_tbu();
935
936 /* Store the upper time stamp. */
937 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_UPPER_OFFSET)) =
938 (ULONG) upper_tb;
939
940 /* Store the lower time stamp. */
941 *((ULONG *) (entry_ptr + TX_EL_EVENT_TIME_LOWER_OFFSET)) =
942 (ULONG) read_tbl();
943 } while (upper_tb != (ULONG) read_tbu());
944
945 /* Store the current thread. */
946 *((ULONG *) (entry_ptr + TX_EL_EVENT_THREAD_OFFSET)) =
947 (ULONG) _tx_thread_current_ptr;
948
949 /* Store the first info word. */
950 *((ULONG *) (entry_ptr + TX_EL_EVENT_INFO_1_OFFSET)) =
951 (ULONG) interrupt_number;
952
953 /* Now move the current event log pointer. */
954 entry_ptr = entry_ptr + TX_EL_EVENT_SIZE;
955
956 /* Check for a wraparound condition. */
957 if (entry_ptr >= _tx_el_event_area_end)
958 {
959
960 /* Yes, we have wrapped around to the end of the event area.
961 Start back at the top! */
962 entry_ptr = _tx_el_event_area_start;
963 }
964
965 /* Write the entry pointer back into the header. */
966 *_tx_el_current_event = entry_ptr;
967
968 TX_EL_END_FILTER
969 }
970
971
972 /**************************************************************************/
973 /* */
974 /* FUNCTION RELEASE */
975 /* */
976 /* _tx_el_interrupt_control PORTABLE C */
977 /* 6.1 */
978 /* AUTHOR */
979 /* */
980 /* William E. Lamie, Microsoft Corporation */
981 /* */
982 /* DESCRIPTION */
983 /* */
984 /* This function remaps the tx_interrupt_control service call so that */
985 /* it can be tracked in the event log. */
986 /* */
987 /* INPUT */
988 /* */
989 /* new_posture New interrupt posture */
990 /* */
991 /* OUTPUT */
992 /* */
993 /* old_posture Old interrupt posture */
994 /* */
995 /* CALLS */
996 /* */
997 /* _tx_thread_interrupt_control Interrupt control service */
998 /* */
999 /* CALLED BY */
1000 /* */
1001 /* ThreadX services */
1002 /* */
1003 /* RELEASE HISTORY */
1004 /* */
1005 /* DATE NAME DESCRIPTION */
1006 /* */
1007 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
1008 /* */
1009 /**************************************************************************/
_tx_el_interrupt_control(UINT new_posture)1010 UINT _tx_el_interrupt_control(UINT new_posture)
1011 {
1012
1013 TX_INTERRUPT_SAVE_AREA
1014 UINT old_posture;
1015
1016
1017 TX_EL_NO_INTERRUPT_EVENTS
1018
1019 TX_DISABLE
1020 TX_EL_KERNEL_CALL_EVENT_INSERT_INFO2(TX_EL_INTERRUPT_CONTROL, _tx_thread_current_ptr, new_posture)
1021 TX_RESTORE
1022
1023 TX_EL_END_FILTER
1024
1025 old_posture = _tx_thread_interrupt_control(new_posture);
1026 return(old_posture);
1027 }
1028
1029
1030 /**************************************************************************/
1031 /* */
1032 /* FUNCTION RELEASE */
1033 /* */
1034 /* _tx_el_event_log_on PORTABLE C */
1035 /* 6.1 */
1036 /* AUTHOR */
1037 /* */
1038 /* William E. Lamie, Microsoft Corporation */
1039 /* */
1040 /* DESCRIPTION */
1041 /* */
1042 /* This function disables all event filters. */
1043 /* */
1044 /* INPUT */
1045 /* */
1046 /* None */
1047 /* */
1048 /* OUTPUT */
1049 /* */
1050 /* None */
1051 /* */
1052 /* CALLS */
1053 /* */
1054 /* None */
1055 /* */
1056 /* CALLED BY */
1057 /* */
1058 /* Application code */
1059 /* */
1060 /* RELEASE HISTORY */
1061 /* */
1062 /* DATE NAME DESCRIPTION */
1063 /* */
1064 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
1065 /* */
1066 /**************************************************************************/
_tx_el_event_log_on(void)1067 VOID _tx_el_event_log_on(void)
1068 {
1069
1070 /* Disable all event filters. */
1071 _tx_el_event_filter = TX_EL_ENABLE_ALL_EVENTS;
1072 }
1073
1074
1075 /**************************************************************************/
1076 /* */
1077 /* FUNCTION RELEASE */
1078 /* */
1079 /* _tx_el_event_log_off PORTABLE C */
1080 /* 6.1 */
1081 /* AUTHOR */
1082 /* */
1083 /* William E. Lamie, Microsoft Corporation */
1084 /* */
1085 /* DESCRIPTION */
1086 /* */
1087 /* This function sets all event filters, thereby turning event */
1088 /* logging off. */
1089 /* */
1090 /* INPUT */
1091 /* */
1092 /* None */
1093 /* */
1094 /* OUTPUT */
1095 /* */
1096 /* None */
1097 /* */
1098 /* CALLS */
1099 /* */
1100 /* None */
1101 /* */
1102 /* CALLED BY */
1103 /* */
1104 /* Application code */
1105 /* */
1106 /* RELEASE HISTORY */
1107 /* */
1108 /* DATE NAME DESCRIPTION */
1109 /* */
1110 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
1111 /* */
1112 /**************************************************************************/
_tx_el_event_log_off(void)1113 VOID _tx_el_event_log_off(void)
1114 {
1115
1116 /* Set all event filters. */
1117 _tx_el_event_filter = TX_EL_FILTER_ALL_EVENTS;
1118 }
1119
1120
1121 /**************************************************************************/
1122 /* */
1123 /* FUNCTION RELEASE */
1124 /* */
1125 /* _tx_el_event_log_set PORTABLE C */
1126 /* 6.1 */
1127 /* AUTHOR */
1128 /* */
1129 /* William E. Lamie, Microsoft Corporation */
1130 /* */
1131 /* DESCRIPTION */
1132 /* */
1133 /* This function sets the events filters specified by the user. */
1134 /* */
1135 /* INPUT */
1136 /* */
1137 /* filter Events to filter */
1138 /* */
1139 /* OUTPUT */
1140 /* */
1141 /* None */
1142 /* */
1143 /* CALLS */
1144 /* */
1145 /* None */
1146 /* */
1147 /* CALLED BY */
1148 /* */
1149 /* Application code */
1150 /* */
1151 /* RELEASE HISTORY */
1152 /* */
1153 /* DATE NAME DESCRIPTION */
1154 /* */
1155 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
1156 /* */
1157 /**************************************************************************/
_tx_el_event_filter_set(UINT filter)1158 VOID _tx_el_event_filter_set(UINT filter)
1159 {
1160
1161 /* Apply the user event filter. */
1162 _tx_el_event_filter = filter;
1163 }
1164
1165