xTaskGetTickCount on 32bit is inefficient

helarsen wrote on Sunday, May 24, 2009:

xTaskGetTickCount in Task.c does more work than needed when implemented on 32bit processors so should’nt the function be written somewhat like the following where it is assumed the configUSE_16_BIT_TICKS!=1 on 32b cores?
portTickType xTaskGetTickCount( void )
#if (configUSE_16_BIT_TICKS==1)
portTickType xTicks;
    /* Critical section required if running on a 16 bit processor. */
        xTicks = xTickCount;

    return xTicks;
#else //(configUSE_16_BIT_TICKS==0)
    return (xTickCount);//Allready atomic

The reason for the critical section on 16b processors is that grabbing of the xTickCOunt copy must be atomic. On 32b this is inherent, so with 32b there is no need to add the overhead of the critical section. Right?


rtel wrote on Sunday, May 24, 2009:

I think what you are saying…is that the critical section is not required on all processors, and you would be correct.  It has been discussed here before.

xTaskGetTickCount() is not called by the kernel itself anywhere, only applications.  My preference it to keep it as it is to prevent yet another conditional compilation, which would be ugly.

You could optimise it completely, and make it an inline access to a global variable for the occasions where the critical section is not needed.

Ideally you could use something like

#if( sizeof( portTickType ) != sizeof( portBASE_TYPE ) )

I think also it has been suggested previously that there could be another type of critical section, one that only has an effect when the data types are not compatable…


alainm3 wrote on Monday, May 25, 2009:

Hi Richard,

first of all I do not believe that a conditional complie is uglier than a lot of useless code that can be replaced by a single memory read !!!

It even seems like an elegand solution would be to have an inline function for 32 bits that the compiler can optimize out. Something like this:

---- in the .h file —
#if( sizeof( portTickType ) == sizeof( portBASE_TYPE ) )
#  define xTaskGetTickCount( ) (xTickCount)
portTickType xTaskGetTickCount( void );

  — in the .c file —
#if( sizeof( portTickType ) != sizeof( portBASE_TYPE ) )

… regular function for 8 and 16 bit with critical sections


richard_damon wrote on Monday, May 25, 2009:

The big problem is that is illegal code. sizeof is not allowed in #if statements as the preprocesor doesn’t know the size of types (or even what is a type).

You would need a config parameter which indicates that portTickType is an atomic type.

helarsen wrote on Wednesday, May 27, 2009:

I am in doubt if xTaskGetTickCount() may be called from an ISR when implemented as it currently is - using a critical section which esentially means that IRQ is disabled then re-enabled again. Is this ok to do inside an ISR? On the ARM ADuC702x which I use it boils down to __disable_interrupt() then __enable_interrupt.

I ask because xTaskGetTickCount() is actually very useful to call from the ISR in order to add time stamps to the acquisition data.

In fact such practical use pattern is another argument for optimizing the xTaskGetTickCount() in order to conserve the precious ISR time to a minimum.

I acknowledge the desire to keep the number of #if()/#endif’s down, in particular in such a multidimensional project (processor vs. compiler) as FreeRTOS. But in the case of xTaskGetTickCount() an exception is justified - at least so I think.


richard_damon wrote on Wednesday, May 27, 2009:

A better solution to getting the tick count in an ISR is to make a xTaskGetTickCountFromISR function, to follow the mold of ISRs only use FromISR entry points, That entry would be a simple fetch of the tick counter, since it is in an interrupt, there is the built in critical section for the access if it is needed (since ISRs that access the kernel don’t nest).

davedoors wrote on Thursday, May 28, 2009:

> I am in doubt if xTaskGetTickCount() may be called from an

It does not end in FromISR(), so it cannot be called from an ISR.