1 #ifndef _LINUX_RING_BUFFER_FRONTEND_INTERNAL_H
2 #define _LINUX_RING_BUFFER_FRONTEND_INTERNAL_H
5 * linux/ringbuffer/frontend_internal.h
7 * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 * Ring Buffer Library Synchronization Header (internal helpers).
12 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
14 * See ring_buffer_frontend.c for more information on wait-free algorithms.
16 * Dual LGPL v2.1/GPL v2 license.
19 #include <urcu/compiler.h>
21 #include <ust/ringbuffer-config.h>
22 #include "backend_types.h"
23 #include "frontend_types.h"
26 /* Buffer offset macros */
28 /* buf_trunc mask selects only the buffer number. */
30 unsigned long buf_trunc(unsigned long offset
, struct channel
*chan
)
32 return offset
& ~(chan
->backend
.buf_size
- 1);
36 /* Select the buffer number value (counter). */
38 unsigned long buf_trunc_val(unsigned long offset
, struct channel
*chan
)
40 return buf_trunc(offset
, chan
) >> chan
->backend
.buf_size_order
;
43 /* buf_offset mask selects only the offset within the current buffer. */
45 unsigned long buf_offset(unsigned long offset
, struct channel
*chan
)
47 return offset
& (chan
->backend
.buf_size
- 1);
50 /* subbuf_offset mask selects the offset within the current subbuffer. */
52 unsigned long subbuf_offset(unsigned long offset
, struct channel
*chan
)
54 return offset
& (chan
->backend
.subbuf_size
- 1);
57 /* subbuf_trunc mask selects the subbuffer number. */
59 unsigned long subbuf_trunc(unsigned long offset
, struct channel
*chan
)
61 return offset
& ~(chan
->backend
.subbuf_size
- 1);
64 /* subbuf_align aligns the offset to the next subbuffer. */
66 unsigned long subbuf_align(unsigned long offset
, struct channel
*chan
)
68 return (offset
+ chan
->backend
.subbuf_size
)
69 & ~(chan
->backend
.subbuf_size
- 1);
72 /* subbuf_index returns the index of the current subbuffer within the buffer. */
74 unsigned long subbuf_index(unsigned long offset
, struct channel
*chan
)
76 return buf_offset(offset
, chan
) >> chan
->backend
.subbuf_size_order
;
80 * Last TSC comparison functions. Check if the current TSC overflows tsc_bits
81 * bits from the last TSC read. When overflows are detected, the full 64-bit
82 * timestamp counter should be written in the record header. Reads and writes
83 * last_tsc atomically.
86 #if (CAA_BITS_PER_LONG == 32)
88 void save_last_tsc(const struct lib_ring_buffer_config
*config
,
89 struct lib_ring_buffer
*buf
, u64 tsc
)
91 if (config
->tsc_bits
== 0 || config
->tsc_bits
== 64)
95 * Ensure the compiler performs this update in a single instruction.
97 v_set(config
, &buf
->last_tsc
, (unsigned long)(tsc
>> config
->tsc_bits
));
101 int last_tsc_overflow(const struct lib_ring_buffer_config
*config
,
102 struct lib_ring_buffer
*buf
, u64 tsc
)
104 unsigned long tsc_shifted
;
106 if (config
->tsc_bits
== 0 || config
->tsc_bits
== 64)
109 tsc_shifted
= (unsigned long)(tsc
>> config
->tsc_bits
);
110 if (unlikely(tsc_shifted
111 - (unsigned long)v_read(config
, &buf
->last_tsc
)))
118 void save_last_tsc(const struct lib_ring_buffer_config
*config
,
119 struct lib_ring_buffer
*buf
, u64 tsc
)
121 if (config
->tsc_bits
== 0 || config
->tsc_bits
== 64)
124 v_set(config
, &buf
->last_tsc
, (unsigned long)tsc
);
128 int last_tsc_overflow(const struct lib_ring_buffer_config
*config
,
129 struct lib_ring_buffer
*buf
, u64 tsc
)
131 if (config
->tsc_bits
== 0 || config
->tsc_bits
== 64)
134 if (unlikely((tsc
- v_read(config
, &buf
->last_tsc
))
135 >> config
->tsc_bits
))
143 int lib_ring_buffer_reserve_slow(struct lib_ring_buffer_ctx
*ctx
);
146 void lib_ring_buffer_switch_slow(struct lib_ring_buffer
*buf
,
147 enum switch_mode mode
,
148 struct shm_handle
*handle
);
150 /* Buffer write helpers */
153 void lib_ring_buffer_reserve_push_reader(struct lib_ring_buffer
*buf
,
154 struct channel
*chan
,
155 unsigned long offset
)
157 unsigned long consumed_old
, consumed_new
;
160 consumed_old
= uatomic_read(&buf
->consumed
);
162 * If buffer is in overwrite mode, push the reader consumed
163 * count if the write position has reached it and we are not
164 * at the first iteration (don't push the reader farther than
165 * the writer). This operation can be done concurrently by many
166 * writers in the same buffer, the writer being at the farthest
167 * write position sub-buffer index in the buffer being the one
168 * which will win this loop.
170 if (unlikely(subbuf_trunc(offset
, chan
)
171 - subbuf_trunc(consumed_old
, chan
)
172 >= chan
->backend
.buf_size
))
173 consumed_new
= subbuf_align(consumed_old
, chan
);
176 } while (unlikely(uatomic_cmpxchg(&buf
->consumed
, consumed_old
,
177 consumed_new
) != consumed_old
));
181 void lib_ring_buffer_vmcore_check_deliver(const struct lib_ring_buffer_config
*config
,
182 struct lib_ring_buffer
*buf
,
183 unsigned long commit_count
,
185 struct shm_handle
*handle
)
187 if (config
->oops
== RING_BUFFER_OOPS_CONSISTENCY
)
188 v_set(config
, &shmp(handle
, buf
->commit_hot
)[idx
].seq
, commit_count
);
192 int lib_ring_buffer_poll_deliver(const struct lib_ring_buffer_config
*config
,
193 struct lib_ring_buffer
*buf
,
194 struct channel
*chan
,
195 struct shm_handle
*handle
)
197 unsigned long consumed_old
, consumed_idx
, commit_count
, write_offset
;
199 consumed_old
= uatomic_read(&buf
->consumed
);
200 consumed_idx
= subbuf_index(consumed_old
, chan
);
201 commit_count
= v_read(config
, &shmp(handle
, buf
->commit_cold
)[consumed_idx
].cc_sb
);
203 * No memory barrier here, since we are only interested
204 * in a statistically correct polling result. The next poll will
205 * get the data is we are racing. The mb() that ensures correct
206 * memory order is in get_subbuf.
208 write_offset
= v_read(config
, &buf
->offset
);
211 * Check that the subbuffer we are trying to consume has been
212 * already fully committed.
215 if (((commit_count
- chan
->backend
.subbuf_size
)
216 & chan
->commit_count_mask
)
217 - (buf_trunc(consumed_old
, chan
)
218 >> chan
->backend
.num_subbuf_order
)
223 * Check that we are not about to read the same subbuffer in
224 * which the writer head is.
226 if (subbuf_trunc(write_offset
, chan
) - subbuf_trunc(consumed_old
, chan
)
235 int lib_ring_buffer_pending_data(const struct lib_ring_buffer_config
*config
,
236 struct lib_ring_buffer
*buf
,
237 struct channel
*chan
)
239 return !!subbuf_offset(v_read(config
, &buf
->offset
), chan
);
243 unsigned long lib_ring_buffer_get_data_size(const struct lib_ring_buffer_config
*config
,
244 struct lib_ring_buffer
*buf
,
246 struct shm_handle
*handle
)
248 return subbuffer_get_data_size(config
, &buf
->backend
, idx
, handle
);
252 * Check if all space reservation in a buffer have been committed. This helps
253 * knowing if an execution context is nested (for per-cpu buffers only).
254 * This is a very specific ftrace use-case, so we keep this as "internal" API.
257 int lib_ring_buffer_reserve_committed(const struct lib_ring_buffer_config
*config
,
258 struct lib_ring_buffer
*buf
,
259 struct channel
*chan
,
260 struct shm_handle
*handle
)
262 unsigned long offset
, idx
, commit_count
;
264 CHAN_WARN_ON(chan
, config
->alloc
!= RING_BUFFER_ALLOC_PER_CPU
);
265 CHAN_WARN_ON(chan
, config
->sync
!= RING_BUFFER_SYNC_PER_CPU
);
268 * Read offset and commit count in a loop so they are both read
269 * atomically wrt interrupts. By deal with interrupt concurrency by
270 * restarting both reads if the offset has been pushed. Note that given
271 * we only have to deal with interrupt concurrency here, an interrupt
272 * modifying the commit count will also modify "offset", so it is safe
273 * to only check for offset modifications.
276 offset
= v_read(config
, &buf
->offset
);
277 idx
= subbuf_index(offset
, chan
);
278 commit_count
= v_read(config
, &shmp(handle
, buf
->commit_hot
)[idx
].cc
);
279 } while (offset
!= v_read(config
, &buf
->offset
));
281 return ((buf_trunc(offset
, chan
) >> chan
->backend
.num_subbuf_order
)
282 - (commit_count
& chan
->commit_count_mask
) == 0);
286 void lib_ring_buffer_check_deliver(const struct lib_ring_buffer_config
*config
,
287 struct lib_ring_buffer
*buf
,
288 struct channel
*chan
,
289 unsigned long offset
,
290 unsigned long commit_count
,
292 struct shm_handle
*handle
)
294 unsigned long old_commit_count
= commit_count
295 - chan
->backend
.subbuf_size
;
298 /* Check if all commits have been done */
299 if (unlikely((buf_trunc(offset
, chan
) >> chan
->backend
.num_subbuf_order
)
300 - (old_commit_count
& chan
->commit_count_mask
) == 0)) {
302 * If we succeeded at updating cc_sb below, we are the subbuffer
303 * writer delivering the subbuffer. Deals with concurrent
304 * updates of the "cc" value without adding a add_return atomic
305 * operation to the fast path.
307 * We are doing the delivery in two steps:
308 * - First, we cmpxchg() cc_sb to the new value
309 * old_commit_count + 1. This ensures that we are the only
310 * subbuffer user successfully filling the subbuffer, but we
311 * do _not_ set the cc_sb value to "commit_count" yet.
312 * Therefore, other writers that would wrap around the ring
313 * buffer and try to start writing to our subbuffer would
314 * have to drop records, because it would appear as
316 * We therefore have exclusive access to the subbuffer control
317 * structures. This mutual exclusion with other writers is
318 * crucially important to perform record overruns count in
319 * flight recorder mode locklessly.
320 * - When we are ready to release the subbuffer (either for
321 * reading or for overrun by other writers), we simply set the
322 * cc_sb value to "commit_count" and perform delivery.
324 * The subbuffer size is least 2 bytes (minimum size: 1 page).
325 * This guarantees that old_commit_count + 1 != commit_count.
327 if (likely(v_cmpxchg(config
, &shmp(handle
, buf
->commit_cold
)[idx
].cc_sb
,
328 old_commit_count
, old_commit_count
+ 1)
329 == old_commit_count
)) {
331 * Start of exclusive subbuffer access. We are
332 * guaranteed to be the last writer in this subbuffer
333 * and any other writer trying to access this subbuffer
334 * in this state is required to drop records.
336 tsc
= config
->cb
.ring_buffer_clock_read(chan
);
338 subbuffer_get_records_count(config
,
341 &buf
->records_count
);
343 subbuffer_count_records_overrun(config
,
346 &buf
->records_overrun
);
347 config
->cb
.buffer_end(buf
, tsc
, idx
,
348 lib_ring_buffer_get_data_size(config
,
355 * Set noref flag and offset for this subbuffer id.
356 * Contains a memory barrier that ensures counter stores
357 * are ordered before set noref and offset.
359 lib_ring_buffer_set_noref_offset(config
, &buf
->backend
, idx
,
360 buf_trunc_val(offset
, chan
), handle
);
363 * Order set_noref and record counter updates before the
364 * end of subbuffer exclusive access. Orders with
365 * respect to writers coming into the subbuffer after
366 * wrap around, and also order wrt concurrent readers.
369 /* End of exclusive subbuffer access */
370 v_set(config
, &shmp(handle
, buf
->commit_cold
)[idx
].cc_sb
,
372 lib_ring_buffer_vmcore_check_deliver(config
, buf
,
373 commit_count
, idx
, handle
);
376 * RING_BUFFER_WAKEUP_BY_WRITER wakeup is not lock-free.
378 if (config
->wakeup
== RING_BUFFER_WAKEUP_BY_WRITER
379 && uatomic_read(&buf
->active_readers
)
380 && lib_ring_buffer_poll_deliver(config
, buf
, chan
, handle
)) {
381 int wakeup_fd
= shm_get_wakeup_fd(handle
, &buf
->self
._ref
);
383 if (wakeup_fd
>= 0) {
386 * Wake-up the other end by
387 * writing a null byte in the
388 * pipe (non-blocking).
391 ret
= write(wakeup_fd
, "", 1);
392 } while (ret
== -1L && errno
== EINTR
);
401 * lib_ring_buffer_write_commit_counter
403 * For flight recording. must be called after commit.
404 * This function increments the subbuffer's commit_seq counter each time the
405 * commit count reaches back the reserve offset (modulo subbuffer size). It is
406 * useful for crash dump.
409 void lib_ring_buffer_write_commit_counter(const struct lib_ring_buffer_config
*config
,
410 struct lib_ring_buffer
*buf
,
411 struct channel
*chan
,
413 unsigned long buf_offset
,
414 unsigned long commit_count
,
416 struct shm_handle
*handle
)
418 unsigned long offset
, commit_seq_old
;
420 if (config
->oops
!= RING_BUFFER_OOPS_CONSISTENCY
)
423 offset
= buf_offset
+ slot_size
;
426 * subbuf_offset includes commit_count_mask. We can simply
427 * compare the offsets within the subbuffer without caring about
428 * buffer full/empty mismatch because offset is never zero here
429 * (subbuffer header and record headers have non-zero length).
431 if (unlikely(subbuf_offset(offset
- commit_count
, chan
)))
434 commit_seq_old
= v_read(config
, &shmp(handle
, buf
->commit_hot
)[idx
].seq
);
435 while ((long) (commit_seq_old
- commit_count
) < 0)
436 commit_seq_old
= v_cmpxchg(config
, &shmp(handle
, buf
->commit_hot
)[idx
].seq
,
437 commit_seq_old
, commit_count
);
440 extern int lib_ring_buffer_create(struct lib_ring_buffer
*buf
,
441 struct channel_backend
*chanb
, int cpu
,
442 struct shm_handle
*handle
,
443 struct shm_object
*shmobj
);
444 extern void lib_ring_buffer_free(struct lib_ring_buffer
*buf
,
445 struct shm_handle
*handle
);
447 /* Keep track of trap nesting inside ring buffer code */
448 extern __thread
unsigned int lib_ring_buffer_nesting
;
450 #endif /* _LINUX_RING_BUFFER_FRONTEND_INTERNAL_H */