Force consecutive operation when using asm volatile macro
Jari Kuusisto
jari.h.kuusisto@gmail.com
Tue Oct 7 04:43:00 GMT 2008
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
>
More information about the Gcc-help
mailing list