3 static struct udebug_client_msg
*
4 send_and_wait(struct udebug
*ctx
, struct udebug_client_msg
*msg
, int *rfd
)
9 udebug_send_msg(ctx
, msg
, NULL
, -1);
15 msg
= __udebug_poll(ctx
, &fd
, true);
16 } while (msg
&& msg
->type
!= type
);
29 udebug_remote_get_handle(struct udebug
*ctx
)
31 struct udebug_client_msg
*msg
;
32 struct udebug_client_msg send_msg
= {
33 .type
= CL_MSG_GET_HANDLE
,
36 if (ctx
->poll_handle
>= 0 || !udebug_is_connected(ctx
))
39 msg
= send_and_wait(ctx
, &send_msg
, NULL
);
43 ctx
->poll_handle
= msg
->id
;
47 struct udebug_remote_buf
*udebug_remote_buf_get(struct udebug
*ctx
, uint32_t id
)
49 struct udebug_remote_buf
*rb
;
50 void *key
= (void *)(uintptr_t)id
;
52 return avl_find_element(&ctx
->remote_rings
, key
, rb
, node
);
55 int udebug_remote_buf_map(struct udebug
*ctx
, struct udebug_remote_buf
*rb
, uint32_t id
)
57 void *key
= (void *)(uintptr_t)id
;
58 struct udebug_client_msg
*msg
;
59 struct udebug_client_msg send_msg
= {
60 .type
= CL_MSG_RING_GET
,
65 if (rb
->buf
.data
|| !udebug_is_connected(ctx
))
68 msg
= send_and_wait(ctx
, &send_msg
, &fd
);
72 if (udebug_buf_open(&rb
->buf
, fd
, msg
->ring_size
, msg
->data_size
)) {
73 fprintf(stderr
, "failed to open fd %d, ring_size=%d, data_size=%d\n", fd
, msg
->ring_size
, msg
->data_size
);
80 avl_insert(&ctx
->remote_rings
, &rb
->node
);
85 void udebug_remote_buf_unmap(struct udebug
*ctx
, struct udebug_remote_buf
*rb
)
90 avl_delete(&ctx
->remote_rings
, &rb
->node
);
91 udebug_buf_free(&rb
->buf
);
97 int udebug_remote_buf_set_poll(struct udebug
*ctx
, struct udebug_remote_buf
*rb
, bool val
)
111 handle
= udebug_remote_get_handle(ctx
);
115 __atomic_fetch_or(&rb
->buf
.hdr
->notify
, 1UL << handle
, __ATOMIC_RELAXED
);
120 rbuf_advance_read_head(struct udebug_remote_buf
*rb
, uint32_t head
,
121 uint32_t *data_start
)
123 struct udebug_hdr
*hdr
= rb
->buf
.hdr
;
124 uint32_t min_head
= head
+ 1 - rb
->buf
.ring_size
;
125 uint32_t min_data
= u32_get(&hdr
->data_used
) - rb
->buf
.data_size
;
126 struct udebug_ptr
*last_ptr
= udebug_ring_ptr(hdr
, head
- 1);
128 if (!u32_get(&hdr
->head_hi
) && u32_sub(0, min_head
) > 0)
131 /* advance head to skip over any entries that are guaranteed
132 * to be overwritten now. final check will be performed after
135 if (u32_sub(rb
->head
, min_head
) < 0)
138 for (size_t i
= 0; i
< rb
->buf
.ring_size
; i
++) {
139 struct udebug_ptr
*ptr
= udebug_ring_ptr(hdr
, rb
->head
);
142 *data_start
= u32_get(&ptr
->start
);
143 __sync_synchronize();
146 if (ptr
->timestamp
> last_ptr
->timestamp
)
149 if (u32_sub(ptr
->start
, min_data
) > 0)
156 void udebug_remote_buf_set_start_time(struct udebug_remote_buf
*rb
, uint64_t ts
)
158 struct udebug_hdr
*hdr
= rb
->buf
.hdr
;
159 uint32_t head
= u32_get(&hdr
->head
);
160 uint32_t start
= rb
->head
, end
= head
;
166 rbuf_advance_read_head(rb
, head
, NULL
);
167 while ((diff
= u32_sub(end
, start
)) > 0) {
168 uint32_t cur
= start
+ diff
/ 2;
169 struct udebug_ptr
*ptr
;
171 ptr
= udebug_ring_ptr(hdr
, cur
);
172 if (ptr
->timestamp
> ts
)
181 void udebug_remote_buf_set_start_offset(struct udebug_remote_buf
*rb
, uint32_t idx
)
186 rb
->head
= rb
->buf
.hdr
->head
- idx
;
189 void udebug_remote_buf_set_flags(struct udebug_remote_buf
*rb
, uint64_t mask
, uint64_t set
)
191 struct udebug_hdr
*hdr
= rb
->buf
.hdr
;
197 __atomic_and_fetch(&hdr
->flags
[0], (uintptr_t)~mask
, __ATOMIC_RELAXED
);
199 __atomic_or_fetch(&hdr
->flags
[0], (uintptr_t)set
, __ATOMIC_RELAXED
);
201 if (sizeof(mask
) == sizeof(unsigned long))
206 __atomic_and_fetch(&hdr
->flags
[1], (uintptr_t)~mask
, __ATOMIC_RELAXED
);
208 __atomic_or_fetch(&hdr
->flags
[1], (uintptr_t)set
, __ATOMIC_RELAXED
);
211 struct udebug_snapshot
*
212 udebug_remote_buf_snapshot(struct udebug_remote_buf
*rb
)
214 struct udebug_hdr
*hdr
= rb
->buf
.hdr
;
215 struct udebug_ptr
*last_ptr
;
216 uint32_t data_start
, data_end
, data_used
;
217 struct udebug_snapshot
*s
= NULL
;
218 struct udebug_ptr
*ptr_buf
, *first_ptr
;
219 uint32_t data_size
, ptr_size
;
220 uint32_t head
, first_idx
;
221 uint32_t prev_read_head
= rb
->head
;
227 head
= u32_get(&hdr
->head
);
228 rbuf_advance_read_head(rb
, head
, &data_start
);
229 if (rb
->head
== head
)
232 first_idx
= rb
->head
;
233 first_ptr
= udebug_ring_ptr(hdr
, first_idx
);
234 last_ptr
= udebug_ring_ptr(hdr
, head
- 1);
235 data_end
= last_ptr
->start
+ last_ptr
->len
;
237 data_size
= data_end
- data_start
;
238 ptr_size
= head
- rb
->head
;
239 if (data_size
> rb
->buf
.data_size
|| ptr_size
> rb
->buf
.ring_size
) {
240 fprintf(stderr
, "Invalid data size: %x > %x, %x > %x\n", data_size
, (int)rb
->buf
.data_size
, ptr_size
, (int)rb
->buf
.ring_size
);
244 s
= calloc_a(sizeof(*s
),
245 &ptr_buf
, ptr_size
* sizeof(*ptr_buf
),
246 &data_buf
, data_size
);
248 s
->data
= memcpy(data_buf
, udebug_buf_ptr(&rb
->buf
, data_start
), data_size
);
249 s
->data_size
= data_size
;
250 s
->entries
= ptr_buf
;
251 s
->dropped
= rb
->head
- prev_read_head
;
253 if (first_ptr
> last_ptr
) {
254 struct udebug_ptr
*start_ptr
= udebug_ring_ptr(hdr
, 0);
255 struct udebug_ptr
*end_ptr
= udebug_ring_ptr(hdr
, rb
->buf
.ring_size
- 1) + 1;
256 uint32_t size
= end_ptr
- first_ptr
;
257 memcpy(s
->entries
, first_ptr
, size
* sizeof(*s
->entries
));
258 memcpy(s
->entries
+ size
, start_ptr
, (last_ptr
+ 1 - start_ptr
) * sizeof(*s
->entries
));
260 memcpy(s
->entries
, first_ptr
, (last_ptr
+ 1 - first_ptr
) * sizeof(*s
->entries
));
263 /* get a snapshot of the counter that indicates how much data has been
264 * clobbered by newly added entries */
265 __sync_synchronize();
266 data_used
= u32_get(&hdr
->data_used
) - rb
->buf
.data_size
;
268 s
->n_entries
= head
- first_idx
;
270 rbuf_advance_read_head(rb
, head
, NULL
);
271 if (s
->n_entries
< rb
->head
- first_idx
) {
277 s
->entries
+= rb
->head
- first_idx
;
278 s
->n_entries
-= rb
->head
- first_idx
;
279 while (s
->n_entries
> 0 &&
280 u32_sub(s
->entries
[0].start
, data_used
) < 0) {
286 for (size_t i
= 0; i
< s
->n_entries
; i
++)
287 s
->entries
[i
].start
-= data_start
;
289 s
->format
= hdr
->format
;
290 s
->sub_format
= hdr
->sub_format
;
291 s
->rbuf_idx
= (uint32_t)(uintptr_t)rb
->node
.key
;
298 bool udebug_snapshot_get_entry(struct udebug_snapshot
*s
, struct udebug_iter
*it
, unsigned int entry
)
300 struct udebug_ptr
*ptr
;
303 if (entry
>= s
->n_entries
)
306 ptr
= &s
->entries
[entry
];
307 if (ptr
->start
> s
->data_size
|| ptr
->len
> s
->data_size
||
308 ptr
->start
+ ptr
->len
> s
->data_size
)
312 it
->data
= s
->data
+ ptr
->start
;
314 it
->timestamp
= ptr
->timestamp
;
322 void udebug_iter_start(struct udebug_iter
*it
, struct udebug_snapshot
**s
, size_t n
)
324 memset(it
, 0, sizeof(*it
));
329 for (size_t i
= 0; i
< it
->n
; i
++)
330 it
->list
[i
]->iter_idx
= 0;
333 bool udebug_iter_next(struct udebug_iter
*it
)
336 struct udebug_snapshot
*s
;
340 for (size_t i
= 0; i
< it
->n
; i
++) {
341 struct udebug_ptr
*ptr
;
344 if (s
->iter_idx
>= s
->n_entries
)
347 ptr
= &s
->entries
[s
->iter_idx
];
348 if (cur
>= 0 && ptr
->timestamp
> cur_ts
)
352 cur_ts
= ptr
->timestamp
;
360 if (!udebug_snapshot_get_entry(s
, it
, s
->iter_idx
++))