-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathcpu_idle.c
123 lines (106 loc) · 2.68 KB
/
cpu_idle.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* LTTng to GTKwave trace conversion
*
* Authors:
* Ivan Djelic <[email protected]>
* Matthieu Castet <[email protected]>
*
* Copyright (C) 2013 Parrot S.A.
*/
#include "lttng2lxt.h"
#define IDLE_CPU_IDLE PROCESS_KERNEL
#define IDLE_CPU_RUNNING PROCESS_IDLE
#define IDLE_CPU_PREEMPT PROCESS_PREEMPTED
enum {
IDLE_IDLE,
IDLE_RUNNING,
};
static int idle_cpu_state[MAX_CPU];
static int idle_cpu_preempt[MAX_CPU];
static struct ltt_trace idle_cpu[MAX_CPU];
void init_cpu(int cpu)
{
init_trace(&idle_cpu[cpu], TG_PROCESS, 0.0+0.001*cpu, TRACE_SYM_F_BITS,
"cpu idle/%d", cpu);
}
static double emit_cpu_idle_state(double clock, int cpu, union ltt_value val)
{
static double run_start;
static double total_run;
double ret;
if (val.state) {
emit_trace(&idle_cpu[cpu], val);
/* if running account the time */
if (strcmp(val.state, IDLE_CPU_RUNNING) == 0) {
/* if already started, do nothing */
if (!run_start)
run_start = clock;
} else { /* if stopping, record the idle time */
/* if already stopped,, do nothing */
if (run_start > 0) {
total_run += clock - run_start;
run_start = 0;
}
}
ret = total_run;
} else { /* give the total idle time and reset counter */
/* idle is running */
if (run_start > 0) {
total_run += clock - run_start;
run_start = clock;
}
ret = total_run;
/* reset counter */
total_run = 0;
}
return ret;
}
void set_cpu_idle(double clock, int cpu)
{
idle_cpu_state[cpu] = IDLE_IDLE;
(void)emit_cpu_idle_state(clock, cpu, (union ltt_value)IDLE_CPU_IDLE);
}
void set_cpu_running(double clock, int cpu)
{
if (idle_cpu_state[cpu] == IDLE_RUNNING)
return;
idle_cpu_state[cpu] = IDLE_RUNNING;
(void)emit_cpu_idle_state(clock, cpu,
(union ltt_value)IDLE_CPU_RUNNING);
}
void cpu_preempt(double clock, int cpu)
{
struct task *task;
idle_cpu_preempt[cpu]++;
if (idle_cpu_preempt[cpu] == 1) {
if (idle_cpu_state[cpu] == IDLE_IDLE)
(void)emit_cpu_idle_state(clock, cpu,
(union ltt_value)IDLE_CPU_PREEMPT);
task = get_current_task(cpu);
if (task)
emit_trace(task->state_trace,
(union ltt_value)PROCESS_PREEMPTED);
}
}
void cpu_unpreempt(double clock, int cpu)
{
union ltt_value value;
struct task *task;
if (idle_cpu_preempt[cpu] <= 0)
return;
idle_cpu_preempt[cpu]--;
if (idle_cpu_preempt[cpu] == 0) {
task = get_current_task(cpu);
if (task)
emit_trace(task->state_trace,
(union ltt_value)task->mode);
else
INFO("cpu unpreempt : no more task for cpu %d at %lf\n", cpu, clock);
if (idle_cpu_state[cpu] == IDLE_RUNNING) {
value.state = IDLE_CPU_RUNNING;
} else {
value.state = IDLE_CPU_IDLE;
}
(void)emit_cpu_idle_state(clock, cpu, value);
}
}