Skip to content

Commit

Permalink
printk: ringbuffer: change representation of states
Browse files Browse the repository at this point in the history
Rather than deriving the state by evaluating bits within the flags
area of the state variable, assign the states explicit values and
set those values in the flags area. Introduce macros to make it
simple to read and write state values for the state variable.

Although the functionality is preserved, the binary representation
for the states is changed.

Signed-off-by: John Ogness <john.ogness@linutronix.de>
  • Loading branch information
jogness authored and intel-lab-lkp committed Sep 9, 2020
1 parent 55dfa0a commit c4cd70e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 41 deletions.
12 changes: 8 additions & 4 deletions Documentation/admin-guide/kdump/gdbmacros.txt
Expand Up @@ -295,9 +295,12 @@ document dump_record
end

define dmesg
set var $desc_committed = 1UL << ((sizeof(long) * 8) - 1)
set var $flags_mask = 3UL << ((sizeof(long) * 8) - 2)
set var $id_mask = ~$flags_mask
# definitions from kernel/printk/printk_ringbuffer.h
set var $desc_committed = 1
set var $desc_sv_bits = sizeof(long) * 8
set var $desc_flags_shift = $desc_sv_bits - 2
set var $desc_flags_mask = 3 << $desc_flags_shift
set var $id_mask = ~$desc_flags_mask

set var $desc_count = 1U << prb->desc_ring.count_bits
set var $prev_flags = 0
Expand All @@ -309,7 +312,8 @@ define dmesg
set var $desc = &prb->desc_ring.descs[$id % $desc_count]

# skip non-committed record
if (($desc->state_var.counter & $flags_mask) == $desc_committed)
set var $state = 3 & ($desc->state_var.counter >> $desc_flags_shift)
if ($state == $desc_committed)
dump_record $desc $prev_flags
set var $prev_flags = $desc->info.flags
end
Expand Down
28 changes: 7 additions & 21 deletions kernel/printk/printk_ringbuffer.c
Expand Up @@ -348,28 +348,14 @@ static bool data_check_size(struct prb_data_ring *data_ring, unsigned int size)
return true;
}

/* The possible responses of a descriptor state-query. */
enum desc_state {
desc_miss, /* ID mismatch */
desc_reserved, /* reserved, in use by writer */
desc_committed, /* committed, writer is done */
desc_reusable, /* free, not yet used by any writer */
};

/* Query the state of a descriptor. */
static enum desc_state get_desc_state(unsigned long id,
unsigned long state_val)
{
if (id != DESC_ID(state_val))
return desc_miss;

if (state_val & DESC_REUSE_MASK)
return desc_reusable;

if (state_val & DESC_COMMITTED_MASK)
return desc_committed;

return desc_reserved;
return DESC_STATE(state_val);
}

/*
Expand Down Expand Up @@ -467,8 +453,8 @@ static enum desc_state desc_read(struct prb_desc_ring *desc_ring,
static void desc_make_reusable(struct prb_desc_ring *desc_ring,
unsigned long id)
{
unsigned long val_committed = id | DESC_COMMITTED_MASK;
unsigned long val_reusable = val_committed | DESC_REUSE_MASK;
unsigned long val_committed = DESC_SV(id, desc_committed);
unsigned long val_reusable = DESC_SV(id, desc_reusable);
struct prb_desc *desc = to_desc(desc_ring, id);
atomic_long_t *state_var = &desc->state_var;

Expand Down Expand Up @@ -904,7 +890,7 @@ static bool desc_reserve(struct printk_ringbuffer *rb, unsigned long *id_out)
*/
prev_state_val = atomic_long_read(&desc->state_var); /* LMM(desc_reserve:E) */
if (prev_state_val &&
prev_state_val != (id_prev_wrap | DESC_COMMITTED_MASK | DESC_REUSE_MASK)) {
get_desc_state(id_prev_wrap, prev_state_val) != desc_reusable) {
WARN_ON_ONCE(1);
return false;
}
Expand All @@ -918,7 +904,7 @@ static bool desc_reserve(struct printk_ringbuffer *rb, unsigned long *id_out)
* This pairs with desc_read:D.
*/
if (!atomic_long_try_cmpxchg(&desc->state_var, &prev_state_val,
id | 0)) { /* LMM(desc_reserve:F) */
DESC_SV(id, desc_reserved))) { /* LMM(desc_reserve:F) */
WARN_ON_ONCE(1);
return false;
}
Expand Down Expand Up @@ -1237,7 +1223,7 @@ void prb_commit(struct prb_reserved_entry *e)
{
struct prb_desc_ring *desc_ring = &e->rb->desc_ring;
struct prb_desc *d = to_desc(desc_ring, e->id);
unsigned long prev_state_val = e->id | 0;
unsigned long prev_state_val = DESC_SV(e->id, desc_reserved);

/* Now the writer has finished all writing: LMM(prb_commit:A) */

Expand All @@ -1250,7 +1236,7 @@ void prb_commit(struct prb_reserved_entry *e)
* this. This pairs with desc_read:B.
*/
if (!atomic_long_try_cmpxchg(&d->state_var, &prev_state_val,
e->id | DESC_COMMITTED_MASK)) { /* LMM(prb_commit:B) */
DESC_SV(e->id, desc_committed))) { /* LMM(prb_commit:B) */
WARN_ON_ONCE(1);
}

Expand Down
31 changes: 20 additions & 11 deletions kernel/printk/printk_ringbuffer.h
Expand Up @@ -112,16 +112,25 @@ struct prb_reserved_entry {
unsigned int text_space;
};

#define _DATA_SIZE(sz_bits) (1UL << (sz_bits))
#define _DESCS_COUNT(ct_bits) (1U << (ct_bits))
#define DESC_SV_BITS (sizeof(unsigned long) * 8)
#define DESC_COMMITTED_MASK (1UL << (DESC_SV_BITS - 1))
#define DESC_REUSE_MASK (1UL << (DESC_SV_BITS - 2))
#define DESC_FLAGS_MASK (DESC_COMMITTED_MASK | DESC_REUSE_MASK)
#define DESC_ID_MASK (~DESC_FLAGS_MASK)
#define DESC_ID(sv) ((sv) & DESC_ID_MASK)
#define FAILED_LPOS 0x1
#define NO_LPOS 0x3
/* The possible responses of a descriptor state-query. */
enum desc_state {
desc_miss = -1, /* ID mismatch (pseudo state) */
desc_reserved = 0x0, /* reserved, in use by writer */
desc_committed = 0x1, /* committed by writer */
desc_reusable = 0x3, /* free, not yet used by any writer */
};

#define _DATA_SIZE(sz_bits) (1UL << (sz_bits))
#define _DESCS_COUNT(ct_bits) (1U << (ct_bits))
#define DESC_SV_BITS (sizeof(unsigned long) * 8)
#define DESC_FLAGS_SHIFT (DESC_SV_BITS - 2)
#define DESC_FLAGS_MASK (3UL << DESC_FLAGS_SHIFT)
#define DESC_STATE(sv) (3UL & (sv >> DESC_FLAGS_SHIFT))
#define DESC_SV(id, state) (((unsigned long)state << DESC_FLAGS_SHIFT) | id)
#define DESC_ID_MASK (~DESC_FLAGS_MASK)
#define DESC_ID(sv) ((sv) & DESC_ID_MASK)
#define FAILED_LPOS 0x1
#define NO_LPOS 0x3

#define FAILED_BLK_LPOS \
{ \
Expand Down Expand Up @@ -213,7 +222,7 @@ struct prb_reserved_entry {
*/
#define BLK0_LPOS(sz_bits) (-(_DATA_SIZE(sz_bits)))
#define DESC0_ID(ct_bits) DESC_ID(-(_DESCS_COUNT(ct_bits) + 1))
#define DESC0_SV(ct_bits) (DESC_COMMITTED_MASK | DESC_REUSE_MASK | DESC0_ID(ct_bits))
#define DESC0_SV(ct_bits) DESC_SV(DESC0_ID(ct_bits), desc_reusable)

/*
* Define a ringbuffer with an external text data buffer. The same as
Expand Down
11 changes: 6 additions & 5 deletions scripts/gdb/linux/dmesg.py
Expand Up @@ -78,10 +78,10 @@ def invoke(self, arg, from_tty):
len_off = off + printk_info_type.get_type()['text_len'].bitpos // 8

# definitions from kernel/printk/printk_ringbuffer.h
desc_committed = 1
desc_sv_bits = utils.get_long_type().sizeof * 8
desc_committed_mask = 1 << (desc_sv_bits - 1)
desc_reuse_mask = 1 << (desc_sv_bits - 2)
desc_flags_mask = desc_committed_mask | desc_reuse_mask
desc_flags_shift = desc_sv_bits - 2
desc_flags_mask = 3 << desc_flags_shift
desc_id_mask = ~desc_flags_mask

# read in tail and head descriptor ids
Expand All @@ -96,8 +96,9 @@ def invoke(self, arg, from_tty):
desc_off = desc_sz * ind

# skip non-committed record
state = utils.read_u64(descs, desc_off + sv_off + counter_off) & desc_flags_mask
if state != desc_committed_mask:
state = 3 & (utils.read_u64(descs, desc_off + sv_off +
counter_off) >> desc_flags_shift)
if state != desc_committed:
if did == head_id:
break
did = (did + 1) & desc_id_mask
Expand Down

0 comments on commit c4cd70e

Please sign in to comment.