15
15
16
16
#include <linux/rbtree.h>
17
17
#include <linux/list.h>
18
+ #include <linux/log2.h>
18
19
#include <errno.h>
19
20
#include "thread.h"
20
21
#include "event.h"
@@ -75,6 +76,16 @@ struct thread_stack {
75
76
unsigned int arr_sz ;
76
77
};
77
78
79
+ /*
80
+ * Assume pid == tid == 0 identifies the idle task as defined by
81
+ * perf_session__register_idle_thread(). The idle task is really 1 task per cpu,
82
+ * and therefore requires a stack for each cpu.
83
+ */
84
+ static inline bool thread_stack__per_cpu (struct thread * thread )
85
+ {
86
+ return !(thread -> tid || thread -> pid_ );
87
+ }
88
+
78
89
static int thread_stack__grow (struct thread_stack * ts )
79
90
{
80
91
struct thread_stack_entry * new_stack ;
@@ -111,13 +122,16 @@ static int thread_stack__init(struct thread_stack *ts, struct thread *thread,
111
122
return 0 ;
112
123
}
113
124
114
- static struct thread_stack * thread_stack__new (struct thread * thread ,
125
+ static struct thread_stack * thread_stack__new (struct thread * thread , int cpu ,
115
126
struct call_return_processor * crp )
116
127
{
117
128
struct thread_stack * ts = thread -> ts , * new_ts ;
118
129
unsigned int old_sz = ts ? ts -> arr_sz : 0 ;
119
130
unsigned int new_sz = 1 ;
120
131
132
+ if (thread_stack__per_cpu (thread ) && cpu > 0 )
133
+ new_sz = roundup_pow_of_two (cpu + 1 );
134
+
121
135
if (!ts || new_sz > old_sz ) {
122
136
new_ts = calloc (new_sz , sizeof (* ts ));
123
137
if (!new_ts )
@@ -130,16 +144,45 @@ static struct thread_stack *thread_stack__new(struct thread *thread,
130
144
ts = new_ts ;
131
145
}
132
146
147
+ if (thread_stack__per_cpu (thread ) && cpu > 0 &&
148
+ (unsigned int )cpu < ts -> arr_sz )
149
+ ts += cpu ;
150
+
133
151
if (!ts -> stack &&
134
152
thread_stack__init (ts , thread , crp ))
135
153
return NULL ;
136
154
137
155
return ts ;
138
156
}
139
157
140
- static inline struct thread_stack * thread__stack (struct thread * thread )
158
+ static struct thread_stack * thread__cpu_stack (struct thread * thread , int cpu )
141
159
{
142
- return thread ? thread -> ts : NULL ;
160
+ struct thread_stack * ts = thread -> ts ;
161
+
162
+ if (cpu < 0 )
163
+ cpu = 0 ;
164
+
165
+ if (!ts || (unsigned int )cpu >= ts -> arr_sz )
166
+ return NULL ;
167
+
168
+ ts += cpu ;
169
+
170
+ if (!ts -> stack )
171
+ return NULL ;
172
+
173
+ return ts ;
174
+ }
175
+
176
+ static inline struct thread_stack * thread__stack (struct thread * thread ,
177
+ int cpu )
178
+ {
179
+ if (!thread )
180
+ return NULL ;
181
+
182
+ if (thread_stack__per_cpu (thread ))
183
+ return thread__cpu_stack (thread , cpu );
184
+
185
+ return thread -> ts ;
143
186
}
144
187
145
188
static int thread_stack__push (struct thread_stack * ts , u64 ret_addr ,
@@ -270,16 +313,16 @@ int thread_stack__flush(struct thread *thread)
270
313
return err ;
271
314
}
272
315
273
- int thread_stack__event (struct thread * thread , u32 flags , u64 from_ip ,
316
+ int thread_stack__event (struct thread * thread , int cpu , u32 flags , u64 from_ip ,
274
317
u64 to_ip , u16 insn_len , u64 trace_nr )
275
318
{
276
- struct thread_stack * ts = thread__stack (thread );
319
+ struct thread_stack * ts = thread__stack (thread , cpu );
277
320
278
321
if (!thread )
279
322
return - EINVAL ;
280
323
281
324
if (!ts ) {
282
- ts = thread_stack__new (thread , NULL );
325
+ ts = thread_stack__new (thread , cpu , NULL );
283
326
if (!ts ) {
284
327
pr_warning ("Out of memory: no thread stack\n" );
285
328
return - ENOMEM ;
@@ -329,9 +372,9 @@ int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
329
372
return 0 ;
330
373
}
331
374
332
- void thread_stack__set_trace_nr (struct thread * thread , u64 trace_nr )
375
+ void thread_stack__set_trace_nr (struct thread * thread , int cpu , u64 trace_nr )
333
376
{
334
- struct thread_stack * ts = thread__stack (thread );
377
+ struct thread_stack * ts = thread__stack (thread , cpu );
335
378
336
379
if (!ts )
337
380
return ;
@@ -375,10 +418,11 @@ static inline u64 callchain_context(u64 ip, u64 kernel_start)
375
418
return ip < kernel_start ? PERF_CONTEXT_USER : PERF_CONTEXT_KERNEL ;
376
419
}
377
420
378
- void thread_stack__sample (struct thread * thread , struct ip_callchain * chain ,
421
+ void thread_stack__sample (struct thread * thread , int cpu ,
422
+ struct ip_callchain * chain ,
379
423
size_t sz , u64 ip , u64 kernel_start )
380
424
{
381
- struct thread_stack * ts = thread__stack (thread );
425
+ struct thread_stack * ts = thread__stack (thread , cpu );
382
426
u64 context = callchain_context (ip , kernel_start );
383
427
u64 last_context ;
384
428
size_t i , j ;
@@ -651,7 +695,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
651
695
struct addr_location * to_al , u64 ref ,
652
696
struct call_return_processor * crp )
653
697
{
654
- struct thread_stack * ts = thread__stack (thread );
698
+ struct thread_stack * ts = thread__stack (thread , sample -> cpu );
655
699
int err = 0 ;
656
700
657
701
if (ts && !ts -> crp ) {
@@ -661,7 +705,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
661
705
}
662
706
663
707
if (!ts ) {
664
- ts = thread_stack__new (thread , crp );
708
+ ts = thread_stack__new (thread , sample -> cpu , crp );
665
709
if (!ts )
666
710
return - ENOMEM ;
667
711
ts -> comm = comm ;
@@ -726,9 +770,9 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
726
770
return err ;
727
771
}
728
772
729
- size_t thread_stack__depth (struct thread * thread )
773
+ size_t thread_stack__depth (struct thread * thread , int cpu )
730
774
{
731
- struct thread_stack * ts = thread__stack (thread );
775
+ struct thread_stack * ts = thread__stack (thread , cpu );
732
776
733
777
if (!ts )
734
778
return 0 ;
0 commit comments