public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Force consecutive operation when using asm volatile macro
@ 2008-10-06 13:01 Jari Kuusisto
  2008-10-07  4:26 ` Ian Lance Taylor
  0 siblings, 1 reply; 8+ messages in thread
From: Jari Kuusisto @ 2008-10-06 13:01 UTC (permalink / raw)
  To: gcc-help

Hello,

I've successfully updated gcc 2.95.3 to 4.3.2 (made necessary syntax 
changes to code etc.).

With GCC 2.95.3 I've used a critical section asm volatile macro to enter 
and exit critical sections in the code. When entering critical section, 
there are two asm volatile lines needed. On critical section exit only 
one asm volatile line is required.

After upgrading from gcc 2.95.3 to 4.3.2 the critical section handling 
in the code stopped working. It seems that some of the code that should 
be in critical section seems to be relocated outside the critical 
section. I do know that asm volatile does not guarantee consecutive 
execution of the code. I also know that using singe asm would fix this 
problem, but in my case it is not possible.

I've managed to to get around this problem by replacing the critical 
section macros with assembler functions as the blr instruction forces 
the correct consecutive operation when entering and exiting critical 
section. However, this function call type implementation seems to 
significantly slow down runtime operation of the software. The result is 
that the performance improvement gained with new gcc optimizations is 
waisted due to this  function call  type implementation.

If I enable all other optimizations from -O2 but not the 
-freorder-blocks the code is working with the old asm volatile macros, 
but this is not an option.

Is there any other way to force the consecutive operation of asm 
volatile macros?

BR. Jari Kuusisto

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Force consecutive operation when using asm volatile macro
  2008-10-06 13:01 Force consecutive operation when using asm volatile macro Jari Kuusisto
@ 2008-10-07  4:26 ` Ian Lance Taylor
  2008-10-07  4:43   ` Jari Kuusisto
  0 siblings, 1 reply; 8+ messages in thread
From: Ian Lance Taylor @ 2008-10-07  4:26 UTC (permalink / raw)
  To: Jari Kuusisto; +Cc: gcc-help

Jari Kuusisto <jari.h.kuusisto@gmail.com> writes:

> After upgrading from gcc 2.95.3 to 4.3.2 the critical section handling
> in the code stopped working. It seems that some of the code that
> should be in critical section seems to be relocated outside the
> critical section. I do know that asm volatile does not guarantee
> consecutive execution of the code. I also know that using singe asm
> would fix this problem, but in my case it is not possible.
>
> I've managed to to get around this problem by replacing the critical
> section macros with assembler functions as the blr instruction forces
> the correct consecutive operation when entering and exiting critical
> section. However, this function call type implementation seems to
> significantly slow down runtime operation of the software. The result
> is that the performance improvement gained with new gcc optimizations
> is waisted due to this  function call  type implementation.
>
> If I enable all other optimizations from -O2 but not the
> -freorder-blocks the code is working with the old asm volatile macros,
> but this is not an option.
>
> Is there any other way to force the consecutive operation of asm
> volatile macros?


You're going to have to show us the code.

Ian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Force consecutive operation when using asm volatile macro
  2008-10-07  4:26 ` Ian Lance Taylor
@ 2008-10-07  4:43   ` Jari Kuusisto
  2008-10-07  4:52     ` Ian Lance Taylor
  0 siblings, 1 reply; 8+ messages in thread
From: Jari Kuusisto @ 2008-10-07  4:43 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-help

Hello Ian,

Here's an example function from uC/OS where the critical section asm 
macro code seems not to work as expected (but with critical section 
function it works).

void  OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                           /* Allocate 
storage for CPU status register      */
    OS_CPU_SR  cpu_sr;
    cpu_sr = 0;                                       /* Prevent 
compiler warning                      */
#endif   
    if (OSIntNesting > 0) {                           /* See if called 
from ISR ...                    */
        *err = OS_ERR_PEND_ISR;                       /* ... can't PEND 
from an ISR                    */
        return;
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                    /* Validate 
'pevent'                             */
        *err = OS_ERR_PEVENT_NULL;
        return;
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event 
block type                     */
        *err = OS_ERR_EVENT_TYPE;
        return;
    }
    OS_ENTER_CRITICAL();
    if (pevent->OSEventCnt > 0) {                     /* If sem. is 
positive, resource available ...   */
        pevent->OSEventCnt--;                         /* ... decrement 
semaphore only if positive.     */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        return;
    }
                                                      /* Otherwise, must 
wait until event occurs       */
    OSTCBCur->OSTCBStat   |= OS_STAT_SEM;             /* Resource not 
available, pend on semaphore     */
    OSTCBCur->OSTCBPendTO  = FALSE;
    OSTCBCur->OSTCBDly     = timeout;                 /* Store pend 
timeout in TCB                     */
    OS_EventTaskWait(pevent);                         /* Suspend task 
until event or timeout occurs    */
    OS_EXIT_CRITICAL();
    OS_Sched();                                       /* Find next 
highest priority task ready         */
    OS_ENTER_CRITICAL();
    if (OSTCBCur->OSTCBPendTO == TRUE) {              /* See if we 
timedout                            */
        OS_EventTO(pevent);
        OS_EXIT_CRITICAL();
        *err = OS_TIMEOUT;                            /* Indicate that 
didn't get event within TO      */
        return;
    }
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
    OS_EXIT_CRITICAL();
    *err = OS_NO_ERR;
}

INT8U  OSSemPost (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3                                /* Allocate 
storage for CPU status register */
    OS_CPU_SR  cpu_sr;                              
    cpu_sr = 0;                                            /* Prevent 
compiler warning                 */
#endif   
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                         /* Validate 
'pevent'                        */
        return (OS_ERR_PEVENT_NULL);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {        /* Validate 
event block type                */
        return (OS_ERR_EVENT_TYPE);
    }
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                          /* See if 
any task waiting for semaphore*/
        (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM); /* Ready 
HPT waiting on event           */
        OS_EXIT_CRITICAL();
        OS_Sched();                                            /* Find 
HPT ready to run                */
        return (OS_NO_ERR);
    }
    if (pevent->OSEventCnt < 65535u) {                /* Make sure 
semaphore will not overflow         */
        pevent->OSEventCnt++;                         /* Increment 
semaphore count to register event   */
        OS_EXIT_CRITICAL();
        return (OS_NO_ERR);
    }
    OS_EXIT_CRITICAL();                               /* Semaphore value 
has reached its maximum       */
    return (OS_SEM_OVF);
}

With this asm macro implementation the semaphore handling is not working 
with new GCC version:

    #define OS_ENTER_CRITICAL() asm volatile("mfmsr 
%0":"=r"(cpu_sr));asm volatile("mtspr 81,r0")
    #define OS_EXIT_CRITICAL()  asm volatile("mtmsr %0"::"r"(cpu_sr))

But when using function-type implementation for critical section 
enter/exit, the semaphore handling works as expected:

h-file:
        void OSEnterCriticalFunc(OS_CPU_SR *cpu_sr);
        void OSExitCriticalFunc(OS_CPU_SR *cpu_sr);
        #define OS_ENTER_CRITICAL() ( OSEnterCriticalFunc( &cpu_sr ) )
        #define OS_EXIT_CRITICAL()  ( OSExitCriticalFunc ( &cpu_sr ) )

c-file:
void OSEnterCriticalFunc(OS_CPU_SR *cpu_sr)
{
    asm volatile("mfmsr %0":"=r"(*cpu_sr));
    asm volatile("mtspr 81,r0");
}

void OSExitCriticalFunc(OS_CPU_SR *cpu_sr)
{
    asm volatile("mtmsr %0"::"r"(*cpu_sr));
}

BR. Jari Kuusisto


Ian Lance Taylor wrote:
> Jari Kuusisto <jari.h.kuusisto@gmail.com> writes:
>
>   
>> After upgrading from gcc 2.95.3 to 4.3.2 the critical section handling
>> in the code stopped working. It seems that some of the code that
>> should be in critical section seems to be relocated outside the
>> critical section. I do know that asm volatile does not guarantee
>> consecutive execution of the code. I also know that using singe asm
>> would fix this problem, but in my case it is not possible.
>>
>> I've managed to to get around this problem by replacing the critical
>> section macros with assembler functions as the blr instruction forces
>> the correct consecutive operation when entering and exiting critical
>> section. However, this function call type implementation seems to
>> significantly slow down runtime operation of the software. The result
>> is that the performance improvement gained with new gcc optimizations
>> is waisted due to this  function call  type implementation.
>>
>> If I enable all other optimizations from -O2 but not the
>> -freorder-blocks the code is working with the old asm volatile macros,
>> but this is not an option.
>>
>> Is there any other way to force the consecutive operation of asm
>> volatile macros?
>>     
>
>
> You're going to have to show us the code.
>
> Ian
>   

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Force consecutive operation when using asm volatile macro
  2008-10-07  4:43   ` Jari Kuusisto
@ 2008-10-07  4:52     ` Ian Lance Taylor
  2008-10-07  6:50       ` Jari Kuusisto
  0 siblings, 1 reply; 8+ messages in thread
From: Ian Lance Taylor @ 2008-10-07  4:52 UTC (permalink / raw)
  To: Jari Kuusisto; +Cc: gcc-help

Jari Kuusisto <jari.h.kuusisto@gmail.com> writes:

> Here's an example function from uC/OS where the critical section asm
> macro code seems not to work as expected (but with critical section
> function it works).

It might help to see how it fails.  That said...

>    #define OS_ENTER_CRITICAL() asm volatile("mfmsr
> %0":"=r"(cpu_sr));asm volatile("mtspr 81,r0")
>    #define OS_EXIT_CRITICAL()  asm volatile("mtmsr %0"::"r"(cpu_sr))

...there is nothing in these asm statements which tells the compiler
that it can't schedule instructions across them.  The asm statements
say that the asm must not be deleted, but they don't say anything
about running before or after any other instructions.

Depending upon your requirements, it may suffice to simply say
    asm volatile("mfmsr %" : "=r" : : "memory");
    asm volatile("mtspr 81,r0" : : : "memory");
and
    asm volatile("mtmsr %0" : : "r" (cpu_sr) : "memory");

Ian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Force consecutive operation when using asm volatile macro
  2008-10-07  4:52     ` Ian Lance Taylor
@ 2008-10-07  6:50       ` Jari Kuusisto
  2008-10-07  7:48         ` Andrew Haley
  0 siblings, 1 reply; 8+ messages in thread
From: Jari Kuusisto @ 2008-10-07  6:50 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-help

Hi,

Ian Lance Taylor wrote:
> Jari Kuusisto <jari.h.kuusisto@gmail.com> writes:
>
>   
>> Here's an example function from uC/OS where the critical section asm
>> macro code seems not to work as expected (but with critical section
>> function it works).
>>     
>
> It might help to see how it fails.  That said...
>
>   
>>    #define OS_ENTER_CRITICAL() asm volatile("mfmsr
>> %0":"=r"(cpu_sr));asm volatile("mtspr 81,r0")
>>    #define OS_EXIT_CRITICAL()  asm volatile("mtmsr %0"::"r"(cpu_sr))
>>     
>
> ...there is nothing in these asm statements which tells the compiler
> that it can't schedule instructions across them.  The asm statements
> say that the asm must not be deleted, but they don't say anything
> about running before or after any other instructions.
>
> Depending upon your requirements, it may suffice to simply say
>     asm volatile("mfmsr %" : "=r" : : "memory");
>     asm volatile("mtspr 81,r0" : : : "memory");
> and
>     asm volatile("mtmsr %0" : : "r" (cpu_sr) : "memory");
>
> Ian
>   

I've now tested this method, the exact macro lines are now:

    #define OS_ENTER_CRITICAL() asm volatile("mfmsr %0":"=r"(cpu_sr) : : 
"memory");asm volatile("mtspr 81,r0" : : : "memory")
    #define OS_EXIT_CRITICAL()  asm volatile("mtmsr %0"::"r"(cpu_sr) : 
"memory")

An this solution seems to be working, and performance values were now 
improved. Could you please explain to me what this "memory" section in 
asm line actually does?

Thanks for your help!

BR. Jari

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Force consecutive operation when using asm volatile macro
  2008-10-07  6:50       ` Jari Kuusisto
@ 2008-10-07  7:48         ` Andrew Haley
  2008-10-07 10:25           ` Jari Kuusisto
  0 siblings, 1 reply; 8+ messages in thread
From: Andrew Haley @ 2008-10-07  7:48 UTC (permalink / raw)
  To: Jari Kuusisto; +Cc: Ian Lance Taylor, gcc-help

Jari Kuusisto wrote:

> 
> An this solution seems to be working, and performance values were now
> improved. Could you please explain to me what this "memory" section in
> asm line actually does?

Rather than asking Ian himself to explain it to you, please look in the docs.
It's called a memory clobber.

See 5.37 Assembler Instructions with C Expression Operands

Andrew.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Force consecutive operation when using asm volatile macro
  2008-10-07  7:48         ` Andrew Haley
@ 2008-10-07 10:25           ` Jari Kuusisto
  2008-10-07 12:19             ` Andrew Haley
  0 siblings, 1 reply; 8+ messages in thread
From: Jari Kuusisto @ 2008-10-07 10:25 UTC (permalink / raw)
  To: Andrew Haley; +Cc: Ian Lance Taylor, gcc-help

Hi,

Andrew Haley wrote:
> Jari Kuusisto wrote:
>
>   
>> An this solution seems to be working, and performance values were now
>> improved. Could you please explain to me what this "memory" section in
>> asm line actually does?
>>     
>
> Rather than asking Ian himself to explain it to you, please look in the docs.
> It's called a memory clobber.
>
> See 5.37 Assembler Instructions with C Expression Operands
>
> Andrew.
>   

I've read that documentation couple of times before but did not notice 
that memory clobber there before. Now that I know the feature I should 
use, I of course found the definition from the documentation.

But I still ain't exactly sure what the memory clobber actually does, 
but I assume that it prevents reordering code blocks before and after 
the specific asm command because it declares access to memory in an 
unpredictable fashion and GCC cannot move code blocks because of that.

Thanks for your help!

BR. Jari K.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Force consecutive operation when using asm volatile macro
  2008-10-07 10:25           ` Jari Kuusisto
@ 2008-10-07 12:19             ` Andrew Haley
  0 siblings, 0 replies; 8+ messages in thread
From: Andrew Haley @ 2008-10-07 12:19 UTC (permalink / raw)
  To: Jari Kuusisto; +Cc: Ian Lance Taylor, gcc-help

Jari Kuusisto wrote:
> 
> But I still ain't exactly sure what the memory clobber actually does,
> but I assume that it prevents reordering code blocks before and after
> the specific asm command because it declares access to memory in an
> unpredictable fashion and GCC cannot move code blocks because of that.

That is what it does.  It tells gcc that every memory operand is changed
by this asm statement.

Andrew.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-10-07 12:19 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-06 13:01 Force consecutive operation when using asm volatile macro Jari Kuusisto
2008-10-07  4:26 ` Ian Lance Taylor
2008-10-07  4:43   ` Jari Kuusisto
2008-10-07  4:52     ` Ian Lance Taylor
2008-10-07  6:50       ` Jari Kuusisto
2008-10-07  7:48         ` Andrew Haley
2008-10-07 10:25           ` Jari Kuusisto
2008-10-07 12:19             ` Andrew Haley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).