NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/56002: lockstat shows huge times on aarch64



>Number:         56002
>Category:       kern
>Synopsis:       lockstat shows huge times on aarch64
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Feb 21 09:55:00 +0000 2021
>Originator:     mlelstv%serpens.de@localhost
>Release:        NetBSD 9.99.80
>Organization:
	
>Environment:
	
	
System: NetBSD arnold 9.99.80 NetBSD 9.99.80 (EGGHED64) #178: Sun Feb 21 07:34:53 UTC 2021 mlelstv@slowpoke:/home/netbsd-current/obj.evbarm64-el/scratch/netbsd-current/src/sys/arch/evbarm/compile/EGGHED64 evbarm
Architecture: aarch64
Machine: evbarm
>Description:

lockstat may report bogus lock durations like:

Total%  Count   Time/ms          Lock                       Caller
------ ------- --------- ---------------------- ------------------------------
100.00   21134 36893495941.20 ffff0001ffac8100       <all>
  0.00   11095   5162.87 ffff0001ffac8100       sopoll+28

The Time/ms value is calculated from a time value of ULONG_MAX, but
which is only the result of a large uint64_t value that is multiplied by
a double and exceeds the uint64_t range. The value is clamped to ULONG_MAX.

The large value comes directly from the lockstat driver. It summarizes e.g.
lock spin times with

LOCKSTART_START_TIMER(flag, var)
spin
LOCKSTART_STOP_TIMER(flag, var)

At start the cpu_counter() value is substracted from var.
At stop the cpu_counter() value is added to var.

This works fine if variable and cpu_counter() use the full integer range,
also when the integer type overflows.

For aarch64 however we use:

#define cpu_counter() cpu_counter32()

but still compute with (zero-extended) uint64_t values.

This causes a discontinuity when the 32bit value overflows and lockstat
accumulates then negative values.

>How-To-Repeat:

Use lockstat on aarch64.

>Fix:

Find a 64bit cpu_counter.
Emulate a 64bit cpu_counter by tracking overflows.
Multiply the cpu_counter() (and cpu_frequency()) values by 2^32

>Unformatted:
 	
 	


Home | Main Index | Thread Index | Old Index