what is the stack of a task and what is it used for ? - uC/OS-II - embedded

So I am reading from MicroC/OS-II book, but in the section for task stacks I couldn't find exactly what the stack is and most importantly - what is it used for. I know it is not something long and difficult, but I kinda' have to understand it. The book only says how to set the stack size and some other things like this.
So, can somebody explain me in short and simple words what is the task stack and what is it used for, in uC/OS-II ?

In general in the context of a procedural programming language, the stack is where a function/procedure/sub-routine's local variables and return address are stored (in a "stack frame") - the greater the call depth, the more stack frames are stored - one for each function that has not yet returned. That part is true regardless of whether you are using an RTOS such as MicroC/OS-II or not.
In a single threaded environment, only one stack is required, and this is normally provided for you as part of the C runtime environment set-up for example. In a multi-threaded environment, you need a stack for each separate thread of execution, and it is typically up to you to allocate stack space for each thread, or at least to specify its length.

I don't know MicroC/OS-II, but the stack of a task is nearly always the same:
During the execution of a task, it stores data that are required in the current context. This means when a subroutine (method, etc.) is called, a "stack frame" is stored on top of the stack. This stack frame stores local variables of the called subroutine, the return address used when the subroutine is finished, and some other info. When the subroutine returns, the stack frame is deleted. If the subroutine calls another one (or itself recursively), another stack frame is stored on top of the current one.
In contrast to a stack where stored data are deleted in reverse order as the have been stored, a heap stores data a long as their memory is not freed, which can be done in an arbitrary order.

Many processors have a stack pointer, and most of those have instructions that specifically use that stack pointer. The stack pointer is a register that holds an address, not unlike the program counter. The stack is simply memory pointed to by the stack pointer, at a higher level you or the operating system or someone divides the available memory space up for different uses, a little for data a little for program a little for heap (mallocs and frees) and some for the stack. The stack pointer and associated instructions allow code to temporarily allocate some memory. A global variable for example is at least for the life of your program stuck at one memory location. A local variable though only needs a memory location while the function is being executed, when the function returns you dont need that local variable memory (statically defined locals are allocated like globals but only available during that function, so not temporary). You could do a malloc and free in the function to allocate this local memory, or you could simply use the stack. And many/most compilers simply use the stack. In addition to local variables you might need to store the return address, if function a() calls function b() to get from b back to where you were in a you need to return to the next instruction after the call to b(). if B calls c then within the context of b() you need to save the return to a() and now within c() you need to know how to return to b(). And so on. This is architecture and calling convention dependent, some architectures always use the stack for returns, some lean toward using a specific register. When nesting calls though all architectures are going to need to eventually use the stack for the return address, so the stack is used here as well. If function a() calls itself 10 times and has one local integer and the return address lets say it needs 8 bytes of stack per call, so first call moves the stack pointer 8 bytes allocating 8 bytes, the second call another 8 and so on. when you start to hit returns, the the stack pointer moves back 8 bytes, another return another 8 bytes back on the stack pointer.
Now translate that from a single application to multiple applications with the illusion if executing simultaneously (an operating system) for each application/task/procedure/thread/whatever you probably want each of them to have their own stack. This is often quite easy as you just need to save the stack pointer from the prior task and set the stack pointer to the last value from the next task when it was switched out. You can of course get much more complicated and have protection mechanisms so each application can only live within its memory space including stack and heap. and mmus can make it even more complicated by having physical memory chopped up into many pieces and the mmu makes it look like separate pieces are linear within the applications virtual address space. etc.
as nurd_droid pointed out some processors have different stack pointers depending on the mode of the processor. you might have one for user/application mode, then when a system call happens a system/superuser stack pointer, and an interrupt happens an interrupt stack pointer. Some architectures simply have one stack pointer...Some architectures the stack is not in the main memory space the stack and stack pointer are buried in the logic and you dont really see it (often in this case the stack size is quite limited and can roll around on itself or other bad things if you dont manage your stack usage).

Stack is a data structure of type last in first out (LIFO) which is used by procedural languages to do push/pop local variable, CPU registers, return addresses before making a function call or when an interrupt occurs or for preparation of context switches.
Variables, registers are popped out in exactly reverse order when compared to order they are pushed on stack.
Stack can grow upwards or downwards in memory. This is something that will depend upon the micro-controller.
Also, many micro-controllers have multiple stacks.
1) User stack
2) Exception stack or Interrupt stack
If RTOS is used then each process/thread/task will have its own stack. In this case user SP micro-controller register will be reassigned by context switch routine to point to stack for currently active process/thread/task.
Exception stack or Interrupt stack is shared across the system.

Related

How does the JVM know how many values to pop into a new frame when invoking a method via invokevirtual?

When a method is called via invokevirtual, the calling method pops off the values to pass to the called method along with the objectref and places them in the new stack frame.
How does it know which stack entry is the objectref? My guess is that it does so by looking at the type of the called method and parses this to determine how many values to pop off, but this seems extremely inefficient. Is there some other mechanism that I'm overlooking?
When you use the class file format as starting point, the method descriptor is the only way to determine, which values from the operand stack have to become the first local variables of the new stack frame.
As an exception to the rule, the invokeinterface instruction has an embedded count which can be used to determine the number of (type 1) elements to consume. As the documentation states:
The count operand of the invokeinterface instruction records a measure of the number of argument values, where an argument value of type long or type double contributes two units to the count value and an argument of any other type contributes one unit. This information can also be derived from the descriptor of the selected method. The redundancy is historical.
This historical redundancy doesn’t change the fact that the JVM has to cope with method descriptors as the source of this information, e.g. for invokevirtual, invokestatic, invokespecial, or invokedynamic. Further, a conforming JVM is required to verify this information, to throw an error if the invokeinterface’s count differs from the count derived from the method descriptor.
Generally, the verifier is responsible for detecting when method invocations are inconsistent to the stack frame’s state and therefore, has to process the method descriptors and model their effect on the operand stack. This implies that, unless you’re using a JVM that verifies each instruction right before its actual execution, it has to handle these descriptors even without executing an actual invocation. The obvious solution is to convert the method descriptors into an easier-to-process internal representation in a first step.
In short, these method descriptors are inefficient but with a reasonable JVM implementation you’re paying the costs only once, not for every invocation.
There's no one "right" way to do this, but the simplest strategy is to leave the values on the stack, and the called method refers to them via negative offsets. For example, if the called method has 3 params, they're referenced from the base stack offset minus 3, 2, and 1. Each is copied to a local variable and then referenced in the usual manner. The stack offset can be updated to reflect that the params have been consumed. Of course, each local param can also be initially assigned by a bunch of pops, one for each param.
Other tricks can be performed to speed things up. There's no reason that local variables need to be stored differently than the stack. They can be stored on the stack itself. The passed in params occupy their original locations on the stack, and then additional space is allocated for the remaining local variables by just updating the stack offset. A base stack offset is remembered, and all local variables are referenced via the base offset.
Essentially, a local variable is just like a stack slot, except it can be accessed at any time, regardless of what's currently been pushed on top.

Where is JVM PC stored during a call?

I am currently reading the last specification of the JVM. It is clear that each thread has its own call stack and its own program counter that keeps track of the (next) instruction to execute.
My question is maybe dump, but from the description, I cannot find an answer.
Where is the current program counter stored when a new or a method is invoked?
In other terms, how does the thread now where to continue after the invokation of a method?
The answer is implementation-dependent as different hardware architectures and even different JVMs may implement this behavior in different ways. In the standard Oracle JVM, most of your bytecode will be compiled to native code by JIT (Just in Time compiler) and method calls will be executed as for native code (give or take some extra code which may be added to handle checkpointing etc.). On a PC this means that current register values, including the instruction pointer / program counter will be saved on the stack before a method call. When returning from the call, the processor pops these values from the stack, among them the return address.

How Can I Aware Register Spilling via Objdump File?

How can I be aware of register spilling by looking at an objdump file?
My thought is that it can be done by tracking the stack pointer: moving sp beyond function prologue and epilogue, indicates register spilling.
I want to know which lines of codes are doing register spilling. Also, where are the registers restored pointed to global variable, also stack?
Register spilling doesn't require moving the stack pointer, a local variable may be spilled to the stack and constantly used directly from there while still in the current frame, and the compiler would just use the stack frame with its offset instead of a register.
Your best bet is just looking for memory addresses being read and/or written to constantly. This may even happen where there are available registers around because of compiler deficiencies, or inability to prove that no other thread/code unit are accessing some local variable by addr (for example if the variable address is copied somewhere out of scope). In such cases maintaining that variable in memory is necessary.

Clarification on stack & heap

I have read that stacks are using to manage function calls, where as heaps are used to store the objects that are allocating. What I understood that non primitive type objects will be stored in heap. I am confused on the following usages in the case of stack & heap:
1) Where the primitive data types, MACROS(#define), static objects, const, and extern?
2) Stacks manages the function calls, but I would like to know what info related to the functions are pushing to the stack?
3) I read somewhere that function related local objects are stored in Stack. So if any allocation of objects happens inside function, stack or heap is used? And if any primitive types objects are declared inside the function, where those are storing?
Sree.
Macros are resolved at compile time. Consts, globals, etc are part of the data segment - not the stack or the heap. https://en.wikipedia.org/wiki/Data_segment
Whenever you call a function it's parameters are pushed onto the stack.
All primitives, local variables, etc inside a function are allocated on the stack.
In simplified terms the compiler calculates how much memory each function needs (the total of all its variable usage). When the function is called that size is simply added to the stack and then it is subtracted in when it is finished.
At the most primitive level the only time heap memory is used (excluding libraries) is when you call malloc.
In the case of Objective-C pretty much every object is allocated dynamically on the heap whenever you call alloc or new. Objective-C is designed that way and heap allocation is normal. C and C++ tend to use the dynamic allocation on the heap less.
To understand what's really happening, you should build a small c program and generate assembly code of it.
What you will find there is the following:
Macros should be evaluated at compile time, not at runtime.
Constants, globals and static things are declared as constants and saved into the executable itself.
Primitive data variables or pointers are stored into CPU registers (extremely fast but limited in quantity) or stored in a stack frame in memory (more space but ca. 1000x slower). To understand stack frames, you should have a look at this explanation. Basically a stack frame is built by moving the stack pointer (which points to the memory location where new values are put onto the stack) down (the stack grows from big memory addresses to smaller ones) so there is some unused space on the stack, which can be locally used during a function.
If you call a function, the return address (the instruction pointer before the call + 1) is pushed onto the stack so when the function returns, the execution jumps to the return address by popping the return address from the stack and jumping to it.
If your function has a lot of arguments, the arguments 7, 8, etc... are stored on the stack before the function is called. All previous arguments are stored in registers
Unlike the stack, the heap space is assigned by the system and can only be accessed (to my knowledge) by interrupting the program and letting the operating system assign memory to the program (which will happen inside a malloc call). As objects are allocated ([NSObject alloc]) they can be found in the heap memory.
Summary
Primitive values and structs are stored next to return addresses of function calls on the stack
large memory allocations above a few bytes are made in heap space. This includes objects and arrays created with malloc.

Can a UNIX process cause its heap and stack to step on each other?

Can this "overrun" condition ever occur? Or, the system guarantees that the stack and heap are two completely isolated areas in the process's virtual address space, so that access/manipulation done in the stack can never affect the heap and vice versa?
One specific scenario that I'd like to find out is whether it's possible for the process to corrupt its memory in such a way that causes the system to no longer correctly manage the stack or heap.
Here is a useful link I've found: What and where are the stack and heap?
I think before that would happen, the program would terminate on either a std::bad_alloc type error (heap) or a stack overflow type error (stack). The heap and stack exist separately, and the only way I could see them intersecting would be in one of the two conditions I mentioned above, either of which would cause the program responsible to crash.