Parallella plat.: close_packet(): fix array indexing
[deliverable/barectf.git] / platforms / parallella / barectf-platform-parallella.c
CommitLineData
e5aa0be3
PP
1/*
2 * barectf Parallella platform
3 *
4 * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26#include <stdint.h>
27#include <stdio.h>
28#include <string.h>
29#include <e_lib.h>
30
31#include "barectf-platform-parallella-common.h"
32#include "barectf-platform-parallella.h"
33#include "barectf.h"
34
35static struct tracing_ctx {
36 struct barectf_default_ctx barectf_ctx;
37 volatile struct ringbuf *ringbuf;
38 uint64_t last_backend_check;
39 uint64_t clock_high;
40 e_memseg_t smem;
41
42 /*
43 * Use a producer index's shadow in local memory to avoid
44 * reading the old value of the producer index in shared memory
45 * after having incremented it.
46 *
47 * NEVER read or write the producer index or its shadow
48 * directly: always use get_prod_index() and incr_prod_index().
49 */
50 uint32_t producer_index_shadow;
51
52 unsigned int row, col;
53 uint8_t local_packet[PACKET_SZ];
54 uint8_t initialized;
55 uint8_t backend_wait_period;
56} g_tracing_ctx;
57
58struct barectf_default_ctx *tracing_get_barectf_ctx(void)
59{
60 return &g_tracing_ctx.barectf_ctx;
61}
62
63static inline void incr_prod_index(struct tracing_ctx *tracing_ctx)
64{
65 tracing_ctx->producer_index_shadow++;
66 tracing_ctx->ringbuf->producer_index =
67 tracing_ctx->producer_index_shadow;
68}
69
70static inline uint32_t get_prod_index(struct tracing_ctx *tracing_ctx)
71{
72 return tracing_ctx->producer_index_shadow;
73}
74
75static uint64_t get_clock(void* data)
76{
77 struct tracing_ctx *tracing_ctx = data;
78
d2b9efb5
PP
79 uint64_t low = (uint64_t)
80 ((uint32_t) (E_CTIMER_MAX - e_ctimer_get(E_CTIMER_1)));
e5aa0be3
PP
81
82 return tracing_ctx->clock_high | low;
83}
84
85static int is_backend_full(void *data)
86{
87 struct tracing_ctx *tracing_ctx = data;
88 int check_shared = 0;
508e0b45 89 int full;
e5aa0be3
PP
90
91 /* are we in a back-end checking waiting period? */
92 if (tracing_ctx->backend_wait_period) {
93 /* yes: check if we may check in shared memory now */
94 uint64_t cur_clock = get_clock(data);
95
96 if (cur_clock - tracing_ctx->last_backend_check >=
97 BACKEND_CHECK_TIMEOUT) {
98 /* check in shared memory */
99 check_shared = 1;
100 tracing_ctx->last_backend_check = cur_clock;
101 }
102 } else {
103 /* no: check in shared memory */
104 check_shared = 1;
105 }
106
107 if (check_shared) {
108 full = (get_prod_index(tracing_ctx) -
109 tracing_ctx->ringbuf->consumer_index) == RINGBUF_SZ;
110 tracing_ctx->backend_wait_period = full;
111
112 if (full) {
113 tracing_ctx->last_backend_check = get_clock(data);
114 }
115 } else {
116 /* no shared memory checking: always considered full */
117 full = 1;
118 }
119
120 return full;
121}
122
123static void open_packet(void *data)
124{
125 struct tracing_ctx *tracing_ctx = data;
126
127 barectf_default_open_packet(&tracing_ctx->barectf_ctx,
128 tracing_ctx->row, tracing_ctx->col);
129}
130
131static void close_packet(void *data)
132{
133 struct tracing_ctx *tracing_ctx = data;
134 void *dst;
135 unsigned int index;
136
137 /* close packet now */
138 barectf_default_close_packet(&tracing_ctx->barectf_ctx);
139
140 /*
141 * We know for sure that there is space in the back-end (ring
142 * buffer) for this packet, so "upload" it to shared memory now.
143 */
144 index = get_prod_index(tracing_ctx) & (RINGBUF_SZ - 1);
fa22632a 145 dst = (void *) &(tracing_ctx->ringbuf->packets[index][0]);
e5aa0be3
PP
146 memcpy(dst, tracing_ctx->local_packet, PACKET_SZ);
147
148 /* update producer index after copy */
149 incr_prod_index(tracing_ctx);
150}
151
152static struct barectf_platform_callbacks cbs = {
153 .default_clock_get_value = get_clock,
154 .is_backend_full = is_backend_full,
155 .open_packet = open_packet,
156 .close_packet = close_packet,
157};
158
159static void __attribute__((interrupt)) timer1_trace_isr()
160{
161 /* CTIMER1 reaches 0: reset to max value and start */
162 g_tracing_ctx.clock_high += (1ULL << 32);
163 e_ctimer_set(E_CTIMER_1, E_CTIMER_MAX);
164 e_ctimer_start(E_CTIMER_1, E_CTIMER_CLK);
165 return;
166}
167
168static void init_clock(void)
169{
170 /* stop and reset CTIMER1 */
171 e_ctimer_stop(E_CTIMER_1);
172 e_ctimer_set(E_CTIMER_1, E_CTIMER_MAX);
173 g_tracing_ctx.clock_high = 0;
174
175 /* enable CTIMER1 interrupt */
176 e_irq_global_mask(E_FALSE);
177 e_irq_attach(E_TIMER1_INT, timer1_trace_isr);
178 e_irq_mask(E_TIMER1_INT, E_FALSE);
179}
180
181static void stop_clock(void)
182{
183 e_ctimer_stop(E_CTIMER_1);
184 e_irq_mask(E_TIMER1_INT, E_TRUE);
185}
186
187void tracing_reset_clock(void)
188{
189 e_ctimer_set(E_CTIMER_1, E_CTIMER_MAX);
190 g_tracing_ctx.clock_high = 0;
191 g_tracing_ctx.backend_wait_period = 0;
192 g_tracing_ctx.last_backend_check = 0;
193 e_ctimer_start(E_CTIMER_1, E_CTIMER_CLK);
194}
195
196int tracing_init(void)
197{
198 e_coreid_t coreid;
199
200 if (g_tracing_ctx.initialized) {
201 /* already initialized */
202 return 0;
203 }
204
205 barectf_init(&g_tracing_ctx.barectf_ctx,
206 g_tracing_ctx.local_packet, PACKET_SZ, cbs, &g_tracing_ctx);
207
208 /* zero local packet */
209 memset(g_tracing_ctx.local_packet, 0, PACKET_SZ);
210
211 /* attach to shared memory */
212 if (e_shm_attach(&g_tracing_ctx.smem, SMEM_NAME) != E_OK) {
213 return -1;
214 }
215
216 /* get core's row and column */
217 coreid = e_get_coreid();
218 e_coords_from_coreid(coreid, &g_tracing_ctx.row, &g_tracing_ctx.col);
219
220 /* get core's ring buffer */
221 g_tracing_ctx.ringbuf =
222 get_ringbuf((void *) g_tracing_ctx.smem.ephy_base,
223 g_tracing_ctx.row, g_tracing_ctx.col);
224
225 /* initialize tracing clock */
226 init_clock();
227
228 /* start tracing clock */
229 tracing_reset_clock();
230
231 /* open first packet */
232 open_packet(&g_tracing_ctx);
233
79eab651
TB
234 /* acknowledge initialization */
235 g_tracing_ctx.initialized = 1;
236
e5aa0be3
PP
237 return 0;
238}
239
240void tracing_fini(void)
241{
242 if (!g_tracing_ctx.initialized) {
243 /* not initialized yet */
244 return;
245 }
246
247 /* close last packet if open and not empty */
248 if (barectf_packet_is_open(&g_tracing_ctx.barectf_ctx) &&
249 !barectf_packet_is_empty(&g_tracing_ctx.barectf_ctx)) {
250 close_packet(&g_tracing_ctx);
251 }
252
253 /* stop CTIMER1 */
254 stop_clock();
255}
This page took 0.045733 seconds and 4 git commands to generate.