trace-systemview  3.1.0
trace-systemview
LLMJVM_MONITOR_sysview.c
Go to the documentation of this file.
1 /*
2  * C
3  *
4  * Copyright 2017-2023 MicroEJ Corp. All rights reserved.
5  * Use of this source code is governed by a BSD-style license that can be found with this software.
6  */
7 
16 /* Includes ------------------------------------------------------------------*/
17 
18 #include <LLMJVM_MONITOR_impl.h>
19 #include <MJVM_MONITOR.h>
20 #include <LLTRACE.h>
21 #include <SEGGER_SYSVIEW.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include "LLMJVM_MONITOR_sysview.h"
26 
27 
28 /* Defines -------------------------------------------------------------------*/
29 
30 // UID for the GC thread (0 is not used by any thread)
31 #define THREAD_GC_UID (0xFF)
32 
33 #define THREAD_GC_NAME "GC"
34 
35 // Max Thread priority + 1
36 #define THREAD_GC_PRIORITY (11)
37 
38 
39 #define apiID_ALLOCATE (0u)
40 #define apiID_EXCEPTION (1u)
41 
42 
43 
44 /* Private functions ---------------------------------------------------------*/
45 
49 static void LLMJVM_MONITOR_SYSTEMVIEW_send_thread_info(int32_t thread_id) {
50  MJVM_MONITOR_thread_info_t thread_info;
51  SEGGER_SYSVIEW_TASKINFO sysview_thread_info;
52  char thread_name[MICROEJ_TRACE_MAX_THREAD_NAME_LENGTH];
53  int32_t result;
54 
55  result = MJVM_MONITOR_get_thread_info(thread_id, &thread_info, thread_name, sizeof(thread_name));
56  if(result == MJVM_MONITOR_OK){
57  memset(&sysview_thread_info, 0, sizeof(sysview_thread_info));
58  sysview_thread_info.TaskID = (U32)thread_id;
59  sysview_thread_info.sName = thread_name;
60  sysview_thread_info.Prio = thread_info.priority;
61  sysview_thread_info.StackBase = (U32)0;
62  if(thread_info.max_stack_usage == -1){
63  thread_info.max_stack_usage = 0;
64  }
65  sysview_thread_info.StackSize = thread_info.max_stack_usage;
66  sysview_thread_info.IsMicroEJThread = 1;
67  SEGGER_SYSVIEW_SendTaskInfo(&sysview_thread_info);
68  }
69 }
70 
71 static void LLMJVM_MONITOR_SYSTEMVIEW_send_gc_thread_info() {
72  // Declare the GC as a task
73  SEGGER_SYSVIEW_TASKINFO taskInfo;
74  memset(&taskInfo, 0, sizeof(taskInfo));
75  taskInfo.TaskID = (U32)THREAD_GC_UID;
76  taskInfo.sName = THREAD_GC_NAME;
77  taskInfo.Prio = THREAD_GC_PRIORITY;
78  taskInfo.StackBase = (U32)0;
79  taskInfo.StackSize = 0;
80  taskInfo.IsMicroEJThread = 1;
81  SEGGER_SYSVIEW_SendTaskInfo(&taskInfo);
82 }
83 
84 void LLMJVM_MONITOR_SYSTEMVIEW_send_task_list(void) {
85  int32_t java_threads_ids[MICROEJ_TRACE_MAX_NB_THREADS];
86  int32_t nb_java_threads = MJVM_MONITOR_get_threads_ids(java_threads_ids, MICROEJ_TRACE_MAX_NB_THREADS);
87 
88  // Declare all the threads
89  while(--nb_java_threads >= 0){
90  LLMJVM_MONITOR_SYSTEMVIEW_send_thread_info(java_threads_ids[nb_java_threads]);
91  }
92 
93  LLMJVM_MONITOR_SYSTEMVIEW_send_gc_thread_info();
94 }
95 
96 /* Globals -------------------------------------------------------------------*/
97 
98 /* Public functions ----------------------------------------------------------*/
99 
100 void LLMJVM_MONITOR_IMPL_initialize(bool auto_start) {
101  if(auto_start == true){
102  LLTRACE_start();
103  }
104  SEGGER_SYSVIEW_OnTaskCreate(THREAD_GC_UID);
105  LLMJVM_MONITOR_SYSTEMVIEW_send_gc_thread_info();
106 }
107 
108 void LLMJVM_MONITOR_IMPL_on_shutdown(void) {
109  // Nothing to do
110 }
111 
112 void LLMJVM_MONITOR_IMPL_on_thread_create(int32_t thread_id) {
113  SEGGER_SYSVIEW_OnTaskCreate(thread_id);
114  LLMJVM_MONITOR_SYSTEMVIEW_send_thread_info(thread_id);
115 }
116 
117 void LLMJVM_MONITOR_IMPL_on_thread_modified(int32_t thread_id) {
118  LLMJVM_MONITOR_SYSTEMVIEW_send_thread_info(thread_id);
119 }
120 
121 void LLMJVM_MONITOR_IMPL_on_thread_state_changed(int32_t thread_id, MJVM_MONITOR_state_t new_state) {
122  switch(new_state){
123  case MJVM_MONITOR_STATE_READY:{
124  SEGGER_SYSVIEW_OnTaskStartReady(thread_id);
125  break;
126  }
127  case MJVM_MONITOR_STATE_RUNNING:{
128  SEGGER_SYSVIEW_setCurrentMicroEJTask(thread_id);
129  SEGGER_SYSVIEW_OnTaskStartExec(thread_id);
130  break;
131  }
132  case MJVM_MONITOR_STATE_WAITING:
133  case MJVM_MONITOR_STATE_MONITOR_QUEUED:{
134  SEGGER_SYSVIEW_OnTaskStopReady(thread_id, new_state);
135  break;
136  }
137  case MJVM_MONITOR_STATE_TERMINATED:{
138  LLMJVM_MONITOR_SYSTEMVIEW_send_thread_info(thread_id);
139  SEGGER_SYSVIEW_OnTaskStopExec();
140  break;
141  }
142  }
143 }
144 
145 void LLMJVM_MONITOR_IMPL_on_idle(void) {
146  // MicroEJ IDLE event is only sent when used without any RTOS.
147  // Otherwise it is the only responsibility of the RTOS to send this event.
148  if(!MICROEJ_TRACE_OVER_RTOS){
149  SEGGER_SYSVIEW_OnIdle();
150  }
151 }
152 
153 void LLMJVM_MONITOR_IMPL_on_gc_start(int32_t current_thread_id) {
154  SEGGER_SYSVIEW_OnTaskStartExec(THREAD_GC_UID);
155 }
156 
157 void LLMJVM_MONITOR_IMPL_on_gc_stop(int32_t current_thread_id) {
158  SEGGER_SYSVIEW_OnTaskStartExec(current_thread_id);
159 }
160 
161 void LLMJVM_MONITOR_IMPL_on_allocate(void* type, int32_t size, void* method, void* instruction_address, int32_t total_memory, int32_t free_memory, bool immortal) {
162  if(MICROEJ_TRACE_ENABLE_ALLOCATIONS){
163  SEGGER_SYSVIEW_RecordU32x3(MICROEJ_TRACE_API_ID_OFFSET + apiID_ALLOCATE, size, free_memory, total_memory-free_memory);
164  }
165 }
166 
167 void LLMJVM_MONITOR_IMPL_on_exception(void* exception_type, void* throw_method, void* throw_instruction_address, void* catch_method, void* catch_instruction_address, const char* message) {
168  if(MICROEJ_TRACE_ENABLE_EXCEPTIONS){
169  SEGGER_SYSVIEW_RecordU32x5(MICROEJ_TRACE_API_ID_OFFSET + apiID_EXCEPTION, (U32)exception_type, (U32)throw_method, (U32)throw_instruction_address, (U32)catch_method, (U32)catch_instruction_address);
170  }
171 }
MicroEJ Trace library low level API.
MicroEJ Trace library low level API.