On Sun, 9 Nov 2008, Andrew Morton wrote: > On Sun, 09 Nov 2008 23:20:00 -0500 (EST) Nicolas Pitre <nico@xxxxxxx> wrote: > > > On Sun, 9 Nov 2008, Mathieu Desnoyers wrote: > > > > > * Nicolas Pitre (nico@xxxxxxx) wrote: > > > > Do you really have such instances where multiple call sites are needed? > > > > That sounds even more confusing to me than the current model. Better > > > > encapsulate the usage of this macro within some function which has a > > > > stronger meaning, such as sched_clock(), and call _that_ from multiple > > > > sites instead. > > > > > > I see a few reasons for it : > > > > > > - If we want to inline the whole read function so we don't pay the extra > > > runtime cost of a function call, this would become required. > > > > You can inline it as you want as long as it remains in the same .c file. > > The static variable is still shared amongst all call sites in that case. > > Please don't rely upon deep compiler behaviour like that. It is > unobvious to the reader and it might break if someone uses it incorrectly, > or if the compiler implementation changes, or if a non-gcc compiler is > used, etc. If a compiler doesn't reference the same storage for a static variable used by a function that gets inlined in the same compilation unit then it is utterly broken. > It is far better to make the management of the state explicit and at > the control of the caller. Get the caller to allocate the state and > pass its address into this function. Simple, clear, explicit and > robust. Sigh... What about this compromize then? diff --git a/include/linux/cnt32_to_63.h b/include/linux/cnt32_to_63.h index 7605fdd..74ce767 100644 --- a/include/linux/cnt32_to_63.h +++ b/include/linux/cnt32_to_63.h @@ -32,8 +32,9 @@ union cnt32_to_63 { /** - * cnt32_to_63 - Expand a 32-bit counter to a 63-bit counter + * __cnt32_to_63 - Expand a 32-bit counter to a 63-bit counter * @cnt_lo: The low part of the counter + * @cnt_hi_p: Pointer to storage for the extended part of the counter * * Many hardware clock counters are only 32 bits wide and therefore have * a relatively short period making wrap-arounds rather frequent. This @@ -75,16 +76,31 @@ union cnt32_to_63 { * clear-bit instruction. Otherwise caller must remember to clear the top * bit explicitly. */ -#define cnt32_to_63(cnt_lo) \ +#define __cnt32_to_63(cnt_lo, cnt_hi_p) \ ({ \ - static u32 __m_cnt_hi; \ union cnt32_to_63 __x; \ - __x.hi = __m_cnt_hi; \ + __x.hi = *(cnt_hi_p); \ smp_rmb(); \ __x.lo = (cnt_lo); \ if (unlikely((s32)(__x.hi ^ __x.lo) < 0)) \ - __m_cnt_hi = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \ + *(cnt_hi_p) = __x.hi = (__x.hi ^ 0x80000000) + (__x.hi >> 31); \ __x.val; \ }) +/** + * cnt32_to_63 - Expand a 32-bit counter to a 63-bit counter + * @cnt_lo: The low part of the counter + * + * This is the same as __cnt32_to_63() except that the storage for the + * extended part of the counter is implicit. Because this uses a static + * variable, a user of this code must not be an inline function unless + * that function is contained in a single .c file for a given counter. + * All usage requirements for __cnt32_to_63() also apply here as well. + */ +#define cnt32_to_63(cnt_lo) \ +({ \ + static u32 __m_cnt_hi; \ + __cnt32_to_63(cnt_lo, &__m_cnt_hi); \ +}) + #endif Nicolas -- To unsubscribe from this list: send the line "unsubscribe linux-arch" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html