There is usually exactly one call stack associated with a running program (or more accurately, with each task or thread of a process.)
Adding a subroutine's entry to the call stack is sometimes called winding; conversely, removing entries is unwinding.
In high-level programming languages, the specifics of the call stack are usually hidden from the programmer.The actual details of the stack in a programming language depend upon the compiler, operating system, and the available instruction set.A call stack is composed of stack frames (sometimes called activation records). Each stack frame corresponds to a call to a subroutine which has not yet terminated with a return.
The memory locations within a frame are often accessed via a register called the stack pointer, which also serves to indicate the current top of the stack. Alternatively, memory within the frame may be accessed via a separate register, often termed the frame pointer, which typically points to some fixed point in the frame structure, such as the location for the return address.
Tread Safe: Reentrant
A computer program or routine is described as reentrant if it can be safely called recursively or from multiple processes. To be reentrant, a function must hold no static data, must not return a pointer to static data, must work only on the data provided to it by the caller, and must not call non-reentrant functions.
There are a few ways to achieve thread-safety:
- re-entrancy: Basically, writing code in such a way that it can be interrupted during one task, reentered to perform another task, and then resumed on its original task. This usually precludes the saving of state information, such as by using static or global variables. 【Not Share】
- mutual exclusion: Access to shared data is serialized using mechanisms that ensure only one thread is accessing the shared data at any time. Great care is required if a piece of code accesses multiple shared pieces of data - problems include race conditions, deadlocks, livelocks, starvation, and various other ills enumerated in many operating systems textbooks. 【Prudent Share】
- thread-local storage: Variables are localized so that each thread has its own private copy. The variables retain their values across subroutine and other code boundaries, and the code which accesses them might not be reentrant, but since they are local to each thread, they are thread-safe.【Not Share】
- Atomic operations: Shared data are accessed by using atomic operations which cannot be interrupted by other threads. This usually requires using special machine language instructions, which might be available in a runtime library. Since the operations are atomic, the shared data are always kept in a valid state, no matter what other threads access it. Atomic operations form the basis of many thread locking mechanisms. 【Prudent Share】


No comments:
Post a Comment