Hi, Does anyone know how can I determine the gcc compiler not to insert any code before my function's prologue? This is how the function begins, I am interested if I can determine the compiler to generate code after the last instruction, the mov instruction should be after the stmdb instruction. 604: e1a05000 mov r5, r0 608: ef0000d3 svc 0x000000d3 60c: e96d50ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}^ Thank you! Lucian
It might help if you could describe what you want to achieve, to avoid getting the right answer to the wrong question. Also you should show the significant part of the source code and a little more of the resulting code.
Hi, I'm writing some system calls for a custom OS, just my free time project and for fun. UINT8 LRTOS_u8MutexRelease(tstMutex *pMutex) { 604: e1a05000 mov r5, r0 UINT8 u8ReturnValue = nE_N_OK; UINT8 u8TaskPrio = 0; /* Switch to SVC mode and disable interrupts */ CPU_vSwitchToSvc(); 608: ef0000d3 svc 0x000000d3 /* Storing the USR context used to execute the current system call */ CPU_vStoreUsrContext(); 60c: e96d50ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}^ The idea is that the last 2 instructions are the prologue of my system calls, a task switch can occur inside this naked function or system call. I need the compiler to recognize the first 2 functions as being the prologue of the naked function so that it never places anything before the last 2 instructions. Thank you! Lucian
If you want to avoid having code placed before your manually generated prologue, then do not place any code there yourself. And be sure to make the asm statement(s) in the prologue "volatile". So move the variables initialization beyond the prologue. And in C99 mode you can use: UINT8 LRTOS_u8MutexRelease(tstMutex *pMutex) { /* Switch to SVC mode and disable interrupts */ CPU_vSwitchToSvc(); /* Storing the USR context used to execute the current system call */ CPU_vStoreUsrContext(); UINT8 u8ReturnValue = nE_N_OK; UINT8 u8TaskPrio = 0; ... body ... }
Hi, The assembler instructions are all volatile ;-). The problem persists after reordering. It seems I can't make the compiler recognize my prologue, would have helped a #pragma or something. Thank you! Lucian
IMHO there is no way to declare code as prologue, other than hacking GCC. Since the compiler choses to move the parameter into some different register before your asms, you may have the redesign the way you are dealing with the OS functions. The way you are doing it is asking for trouble. Even when when you find a way to get the right code tomorrow, the next compiler release could break your concept again. I'd guess that there is no safe way to implement parameterized "naked" functions having a nontrivial body and your prologue/epilogue.
Yeah, the way I handle the functios is a little over the hand but I don't want to have too much overhead, that is why I use this method. Another solution is to build another function vHack and do something like this UINT8 LRTOS_u8MutexRelease(tstMutex *pMutex) { /* Switch to SVC mode and disable interrupts */ CPU_vSwitchToSvc(); 6f8: ef0000d3 svc 0x000000d3 /* Storing the USR context used to execute the current system call */ CPU_vStoreUsrContext(); 6fc: e96d50ff stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}^ /* Prepare the scheduler call, since it will be called after the task is set in sleep mode */ CPU_vPrepareSchedulerCall(); 700: e59f3010 ldr r3, [pc, #16] ; 718 <LRTOS_u8MutexRelease+0x20> 704: e583d000 str sp, [r3] vHack(pMutex); 708: ebffffbd bl 604 <vHack> /* Restoring the USR context used to execute the current system call */ CPU_vRestoreUsrContext(); 70c: e8fd50ff ldm sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}^ /* Switch back to USR mode */ CPU_vSwitchToUsr(); 710: ef000010 svc 0x00000010 /* Function return, since it is a naked function it has no return */ CPU_vFuncReturn(); 714: e1a0f00e mov pc, lr This will add additional stack operations and I don't like it that much. P.S. The concept will not be broken as long as acps is implemented and the naked attribute is kept, hopefully it won't be broken.
This is only version likely to survive compiler upgrades, although you still could face a surprise someday. "naked" functions are a hack, implemented for very rare situations, so you are very much on your own when using them.
The problem is that I can't really build my sys calls so easy without having the naked attribute since I need to know where the user context is saved before entering the system function. If I let the compiler build it's own prologue I endup with system calls that save 4 registers, system calls that save 5 and so on, it would not be so easy to do a task(process) switch. If I go on the aproach with system calls called like the switch SVC with each system call and it's ID I get into trouble since I have to go in a very switch instruction to search for the system call.
What's the reason for all this? Why do you switch to SVC mode instead of SYS mode? SVC mode has it's own R13/SP, so unless you copy the caller's SP you likely need a separate kernel stack for each task. Unless all those kernel functions are non-blocking. And if the kernel runs on the caller's stack, why in SVC mode? BTW: Disabling interrupts as part of each and every kernel function this early makes interrupt latency suffer quite a bit.
Ar Lc wrote: > since I need to know where the user context > is saved before entering the system function. Why? While this is the approach of big operating systems like Unix having separate kernel stacks, the much simpler RTOS kernels usually run the kernel functions on the application stack and defer saving full register context to the time a context switch is actually done. This is also quite a bit faster, since in most occurrences of OS calls a context switch is not actually done.
Each task has it's own stack and one SVC stack, I can acces the stack pointer of the USR mode and I can use it when I need to switch tasks. I do have to rethink a little bit the structure and the idea, maybe I need to change some parts, normally the interrupt latency is not that affected since the functions are really short(including the scheduler). I will have to rethink some things ;-). P.S. You are right, I'll have to rethink the system calls, the problem is that in my case if I release the mutex and there is a higher priority task waiting for the mutex I'll have to do the context switch and place the lower priority task in the ready table.
Ar Lc wrote:
> Each task has it's own stack and one SVC stack
Vague language warning. One SVC stack for each task or one SVC stack
common to all tasks?
In the case of one SVC (kernel) stack for each task: Where exactly do
you need to know the exakt USR context? The context switch needs the
kernel context at time of switch, to know where to continue when
switching back.
In the case of one common SVC stack: IMHO this only works when each and
every kernel function is nonblocking. A rare design decision nowadays.
Sorry was not my intention(I'm not really an english native speaker, my apologies), Yes, one common SVC stack in the entire system, one IRQ stack(since the controller I work on is an ARM9), one FIQ stack, one ABT stack, and as many USR stacks as needed(dependeing on the number of tasks). At the moment I have to know the contex before the system call, it's not a good idea at the moment. I'll need to rethink some things, it's just a weekend learning experience.
Thanks for the constructive discussion. I analyzed the situation and I will start adapting the OS to what you said. Thank you! Lucian
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.