Commit 10dcb06d authored by John Ogness's avatar John Ogness Committed by Petr Mladek

printk: ringbuffer: change representation of states

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: default avatarJohn Ogness <john.ogness@linutronix.de>
Reviewed-by: default avatarPetr Mladek <pmladek@suse.com>
Signed-off-by: default avatarPetr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20200914123354.832-5-john.ogness@linutronix.de
parent cc5c7041
...@@ -295,9 +295,12 @@ document dump_record ...@@ -295,9 +295,12 @@ document dump_record
end end
define dmesg define dmesg
set var $desc_committed = 1UL << ((sizeof(long) * 8) - 1) # definitions from kernel/printk/printk_ringbuffer.h
set var $flags_mask = 3UL << ((sizeof(long) * 8) - 2) set var $desc_committed = 1
set var $id_mask = ~$flags_mask 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 $desc_count = 1U << prb->desc_ring.count_bits
set var $prev_flags = 0 set var $prev_flags = 0
...@@ -309,7 +312,8 @@ define dmesg ...@@ -309,7 +312,8 @@ define dmesg
set var $desc = &prb->desc_ring.descs[$id % $desc_count] set var $desc = &prb->desc_ring.descs[$id % $desc_count]
# skip non-committed record # 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 dump_record $desc $prev_flags
set var $prev_flags = $desc->info.flags set var $prev_flags = $desc->info.flags
end end
......
...@@ -348,14 +348,6 @@ static bool data_check_size(struct prb_data_ring *data_ring, unsigned int size) ...@@ -348,14 +348,6 @@ static bool data_check_size(struct prb_data_ring *data_ring, unsigned int size)
return true; 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. */ /* Query the state of a descriptor. */
static enum desc_state get_desc_state(unsigned long id, static enum desc_state get_desc_state(unsigned long id,
unsigned long state_val) unsigned long state_val)
...@@ -363,13 +355,7 @@ static enum desc_state get_desc_state(unsigned long id, ...@@ -363,13 +355,7 @@ static enum desc_state get_desc_state(unsigned long id,
if (id != DESC_ID(state_val)) if (id != DESC_ID(state_val))
return desc_miss; return desc_miss;
if (state_val & DESC_REUSE_MASK) return DESC_STATE(state_val);
return desc_reusable;
if (state_val & DESC_COMMITTED_MASK)
return desc_committed;
return desc_reserved;
} }
/* /*
...@@ -484,8 +470,8 @@ static enum desc_state desc_read(struct prb_desc_ring *desc_ring, ...@@ -484,8 +470,8 @@ static enum desc_state desc_read(struct prb_desc_ring *desc_ring,
static void desc_make_reusable(struct prb_desc_ring *desc_ring, static void desc_make_reusable(struct prb_desc_ring *desc_ring,
unsigned long id) unsigned long id)
{ {
unsigned long val_committed = id | DESC_COMMITTED_MASK; unsigned long val_committed = DESC_SV(id, desc_committed);
unsigned long val_reusable = val_committed | DESC_REUSE_MASK; unsigned long val_reusable = DESC_SV(id, desc_reusable);
struct prb_desc *desc = to_desc(desc_ring, id); struct prb_desc *desc = to_desc(desc_ring, id);
atomic_long_t *state_var = &desc->state_var; atomic_long_t *state_var = &desc->state_var;
...@@ -921,7 +907,7 @@ static bool desc_reserve(struct printk_ringbuffer *rb, unsigned long *id_out) ...@@ -921,7 +907,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) */ prev_state_val = atomic_long_read(&desc->state_var); /* LMM(desc_reserve:E) */
if (prev_state_val && 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); WARN_ON_ONCE(1);
return false; return false;
} }
...@@ -935,7 +921,7 @@ static bool desc_reserve(struct printk_ringbuffer *rb, unsigned long *id_out) ...@@ -935,7 +921,7 @@ static bool desc_reserve(struct printk_ringbuffer *rb, unsigned long *id_out)
* This pairs with desc_read:D. * This pairs with desc_read:D.
*/ */
if (!atomic_long_try_cmpxchg(&desc->state_var, &prev_state_val, 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); WARN_ON_ONCE(1);
return false; return false;
} }
...@@ -1254,7 +1240,7 @@ void prb_commit(struct prb_reserved_entry *e) ...@@ -1254,7 +1240,7 @@ void prb_commit(struct prb_reserved_entry *e)
{ {
struct prb_desc_ring *desc_ring = &e->rb->desc_ring; struct prb_desc_ring *desc_ring = &e->rb->desc_ring;
struct prb_desc *d = to_desc(desc_ring, e->id); 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) */ /* Now the writer has finished all writing: LMM(prb_commit:A) */
...@@ -1267,7 +1253,7 @@ void prb_commit(struct prb_reserved_entry *e) ...@@ -1267,7 +1253,7 @@ void prb_commit(struct prb_reserved_entry *e)
* this. This pairs with desc_read:B. * this. This pairs with desc_read:B.
*/ */
if (!atomic_long_try_cmpxchg(&d->state_var, &prev_state_val, 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); WARN_ON_ONCE(1);
} }
......
...@@ -112,16 +112,25 @@ struct prb_reserved_entry { ...@@ -112,16 +112,25 @@ struct prb_reserved_entry {
unsigned int text_space; unsigned int text_space;
}; };
#define _DATA_SIZE(sz_bits) (1UL << (sz_bits)) /* The possible responses of a descriptor state-query. */
#define _DESCS_COUNT(ct_bits) (1U << (ct_bits)) enum desc_state {
#define DESC_SV_BITS (sizeof(unsigned long) * 8) desc_miss = -1, /* ID mismatch (pseudo state) */
#define DESC_COMMITTED_MASK (1UL << (DESC_SV_BITS - 1)) desc_reserved = 0x0, /* reserved, in use by writer */
#define DESC_REUSE_MASK (1UL << (DESC_SV_BITS - 2)) desc_committed = 0x1, /* committed by writer */
#define DESC_FLAGS_MASK (DESC_COMMITTED_MASK | DESC_REUSE_MASK) desc_reusable = 0x3, /* free, not yet used by any writer */
#define DESC_ID_MASK (~DESC_FLAGS_MASK) };
#define DESC_ID(sv) ((sv) & DESC_ID_MASK)
#define FAILED_LPOS 0x1 #define _DATA_SIZE(sz_bits) (1UL << (sz_bits))
#define NO_LPOS 0x3 #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 \ #define FAILED_BLK_LPOS \
{ \ { \
...@@ -213,7 +222,7 @@ struct prb_reserved_entry { ...@@ -213,7 +222,7 @@ struct prb_reserved_entry {
*/ */
#define BLK0_LPOS(sz_bits) (-(_DATA_SIZE(sz_bits))) #define BLK0_LPOS(sz_bits) (-(_DATA_SIZE(sz_bits)))
#define DESC0_ID(ct_bits) DESC_ID(-(_DESCS_COUNT(ct_bits) + 1)) #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 * Define a ringbuffer with an external text data buffer. The same as
......
...@@ -78,10 +78,10 @@ class LxDmesg(gdb.Command): ...@@ -78,10 +78,10 @@ class LxDmesg(gdb.Command):
len_off = off + printk_info_type.get_type()['text_len'].bitpos // 8 len_off = off + printk_info_type.get_type()['text_len'].bitpos // 8
# definitions from kernel/printk/printk_ringbuffer.h # definitions from kernel/printk/printk_ringbuffer.h
desc_committed = 1
desc_sv_bits = utils.get_long_type().sizeof * 8 desc_sv_bits = utils.get_long_type().sizeof * 8
desc_committed_mask = 1 << (desc_sv_bits - 1) desc_flags_shift = desc_sv_bits - 2
desc_reuse_mask = 1 << (desc_sv_bits - 2) desc_flags_mask = 3 << desc_flags_shift
desc_flags_mask = desc_committed_mask | desc_reuse_mask
desc_id_mask = ~desc_flags_mask desc_id_mask = ~desc_flags_mask
# read in tail and head descriptor ids # read in tail and head descriptor ids
...@@ -96,8 +96,9 @@ class LxDmesg(gdb.Command): ...@@ -96,8 +96,9 @@ class LxDmesg(gdb.Command):
desc_off = desc_sz * ind desc_off = desc_sz * ind
# skip non-committed record # skip non-committed record
state = utils.read_u64(descs, desc_off + sv_off + counter_off) & desc_flags_mask state = 3 & (utils.read_u64(descs, desc_off + sv_off +
if state != desc_committed_mask: counter_off) >> desc_flags_shift)
if state != desc_committed:
if did == head_id: if did == head_id:
break break
did = (did + 1) & desc_id_mask did = (did + 1) & desc_id_mask
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment