kern/175759: Correct data types for fields of struct qm_trace{} from <sys/queue.h>

Andrey Simonenko simon at comsys.ntu-kpi.kiev.ua
Tue Feb 5 11:40:01 UTC 2013


The following reply was made to PR kern/175759; it has been noted by GNATS.

From: Andrey Simonenko <simon at comsys.ntu-kpi.kiev.ua>
To: Bruce Evans <brde at optusnet.com.au>
Cc: Gleb Smirnoff <glebius at FreeBSD.org>, FreeBSD-gnats-submit at freebsd.org
Subject: Re: kern/175759: Correct data types for fields of struct qm_trace{}
 from <sys/queue.h>
Date: Tue, 5 Feb 2013 13:35:50 +0200

 Bruce Evans wrote:
 
 > Unsigned long is unnecessarily large.  It wastes space on 64-bit
 > arches.  The change doesn't change the wastage, because space was
 > already wasted on 64-bit arches by mispacking the struct (with
 > unnamed padding after the ints).  It changes the API unnecessarily
 > by changing signed variables to unsigned.  Sign variables are
 > easier to use, and changing to unsigned ones risks sign extension
 > bugs.
 
 I did not change order of fields to not change API, that's why
 bigger data type is used without changing size of that structure
 due to padding (at least for current sizes of int and long).
 
 > According to your quote of the C standard, int32_t is enough.  (I
 > couldn't find anything directly about either the type or limit of
 > __LINE__ in the n869.txt draft of C99, but #line is limited to 2**31-1.
 > n1124.pdf says much the same, except it says that __LINE__ is an integer
 > constant where n869.txt says that __LINE__ is a decimal constant.  Both
 > of these seem to be wrong -- "decimal constants" include floating point
 > ones, and "integer constants" include octal and hex ones.)
 
 Using [u]int32_t is enough. but it will require to include <stdint.h>
 if QUEUE_MACRO_DEBUG is defined.  By the way including just <sys/queue.h>
 is not enough because it does not include <stddef.h> for NULL.
 
 > The change preserves many style bugs:
 > - no prefix in member names
 > - member names not sorted inversely on size.  This gives the space
 >    wastage.
 > - member names not indented
 > - space between '*' and member names.
 
 I'll repeat my idea how to improve QUEUE_MACRO_DEBUG, I did not
 post it in the first message, because it contains more changes:
 
 1. Allow a user to specify how many places to remember via QMD_TRACE_N.
    by default this value is 2 (as now).
 
 2. Initialize struct qm_trace{} in *_INIT() and *_INITIALIZER(),
    all initialized HEADs will have defined values in trace information.
 
 3. All trace information is saved in the info[QMD_TRACE_N] array, each
    element is a structure with file name and line number.  If QMD_TRACE_N
    is small, then this array can be split into two arrays to save space;
    if QMD_TRACE_N is big, then one array will work faster because of CPU
    cache lines.
 
 4. Lists' elements usually are not initialized (via bzero() for example),
    so first entry in the info[] array will have some random index for
    lists' elements.
 
 5. Using info[] array allows to specify arbitrary number of elements and
    does not require to move data from one element into another (as now).
    Position in array is (idx = (idx + 1) % QMD_TRACE_N) and during
    debugging at will be necessary to look at info[idx] to find the most
    recent change of HEAD or element.
 
 So, the main change is (I improved it, because of optimization):
 
 #define	QMD_TRACE(x) do {						\
 	unsigned int __idx;						\
 	__idx = ((x)->trace.idx + 1) % QMD_TRACE_N;			\
 	(x)->trace.idx = __idx;						\
 	(x)->trace.info[__idx].file = __FILE__;				\
 	(x)->trace.info[__idx].line = __LINE__;				\
 } while (0)
 
 It cam seem that this change makes QUEUE_MACRO_DEBUG more complex.
 Actually using info[] array with 2 elements (default value) should work
 faster than current implementation, since it does not require to copy
 data lastline -> prevline and lastfile -> prevfile, and that for(;;) in
 QMD_TRACE_INIT() for 1 element should be unrolled.
 
 Comparing generated code for QMD_TRACE under FreeBSD/amd64 9.1-STABLE
 by gcc from the base system and by clang-3.2 from Ports for the following
 file with -DQMD_TRACE_N=2^x (for non 2^x values the code will be more
 complex) and "-O2 -DQUEUE_MACRO_DEBUG":
 
 ------
 #include <stddef.h>
 #ifdef QUEUE_DEFAULT
 # include <sys/queue.h>
 #else
 # include "queue.h"
 #endif
 
 struct foo {
 	int x;
 	int y;
 	TAILQ_ENTRY(foo) link;
 };
 
 TAILQ_HEAD(foo_tailq, foo);
 
 void
 func(struct foo_tailq *foo_tailq, struct foo *foo)
 {
 	TAILQ_REMOVE(foo_tailq, foo, link);
 }
 ------
 
 1. GCC: 
 
    Now:    6 cmds: 4 mov to mem, 2 mov from mem.
    New: 9-10 cmds: 3 mov to mem, 1 mov from mem, 5 cmds with regs.
 
 2. clang:
 
    Now:    6 cmds: 4 mov to mem, 2 mov from mem.
    New:    7 cmds: 3 mov to mem, 1 mov from mem, 3 cmds with regs.
 
 The diff can be found here:
 
 http://lists.freebsd.org/pipermail/freebsd-bugs/2013-February/051665.html
 
 It contains many lines, because I renamed some debugging related macro
 names to improve style, added debugging to TAILQ_SWAP(), corrected
 TAILQ_INSERT_AFTER() and TAILQ_INSERT_BEFORE() (added parentheses for
 listelm).


More information about the freebsd-bugs mailing list