Unregistering functions from the version manager is safeguarded by a check for quiescence. Quiescence is detected by monitoring entrance and exit to functions using use counters. However, usage counters are not always sufficient. Some functions, like do_exit in Linux, never return. An exit use counter would never be decremented, and quiescence would never be detected. Functions that never return lack a ret instruction at the end. For those functions a different methodology of examining the stack is applied. For all processes in the system, a copy of their stack pointer (%esp) is decremented until its value reaches the bottom of the stack. If the item pointed to by the stack pointer (the top-most 4-byte value), when interpreted as a pointer, points at an updated function the check fails. If function arguments pushed on the stack coincidentally evaluate to such a pointer address the framework conservatively assume the function is non-quiescent. This stack walk-through approach does not require a kernel compiled specially. For example, it will work for kernels compiled without frame pointers.
Some functions may delay their execution complicating removal. Examples include a process sleeping in a device driver waiting for response from hardware, or a process sleeping indefinitely on sys_wait while waiting for a child process to exit. DynAMOS first removes the trampoline, enabling access to the original function. While at least one process is still using the cloned function on its stack, the framework waits for the function to exit. If after a period of time (5 secs) the cloned function has still not quiesced, removal fails and the function clone remains active. Removal can be attempted at a later time, or the framework can be instructed to continuously attempt removal until it succeeds. Waiting does not endanger safety and does not require user action. It simply delays removal.