I have two threads created using the CreateThread() function of the Windows API. My first thread (let's call it IMPORTANT_FAST_ACCESS) pushes some data onto a stack. The second thread (let's call it STACK_ACCESS_SLOW) want's to pop some data off that stack and work with it.
The problem is I want the IMPORTANT_FAST_ACCESS thread to be able to access the stack immediately without waiting for the second thread to do it's operation on it. So I basically want the IMPORTANT_FAST_ACCESS to be allowed to access the stack whenever it wants while the STACK_ACCESS_SLOW thread will look for when it is not used by the other thread and grab pop the stack data it wants.
However what if STACK_ACCESS_SLOW starts to access the stack because it was free 1 second ego but now IMPORTANT_FAST_ACCESS decided it wants to push some data on it and cannot wait?
How can I solve this issue?
You have to synchronize access to the shared stack, no matter how fast or slow the threads are. You cannot allow one thread to modify the stack while another thread is using it, and vice versa.
If you don't want the faster thread to be delayed by the slower thread, you have to make sure the slower thread does not keep a lock on the stack while processing it. That means having the slower thread either:
pop stack items one at a time, locking and unlocking the stack each time.
lock the stack, make a copy/swap of it, unlock it, and process the copy as needed.
Related
I know each thread has its own stack.
And my textbook says:
Suppose that a particular semaphore implementation uses a LIFO stack of threads for each semaphore. When a thread blocks on a semaphore in a P operation, its ID is pushed onto the stack. Similarly, the V operation pops the top thread ID from the stack and restarts that thread
what I don't understand is. since each thread uses its own stack to store its thread ID, and obviously threads don't share stack with others, so what does LIFO stack of threads mean? because a thread only put its thread onto the stack which won't contain another thread's id, why use LIFO term here, isn't that LIFO only be meaningful if we can push multiple items on stack?
Your OS needs to know which all threads are waiting for each semaphore. To maintain that list, OS can use a LIFO data structure i.e. stack for each semaphore object.
Do not confuse it with stack of each thread.
what I don't understand is. since each thread uses its own stack to store its thread ID, and obviously threads don't share stack with others, so what does LIFO stack of threads mean?
Threads can shared their stacks with others if they want. Each thread having its own stack is no impediment to one thread accessing another thread's stack.
because a thread only put its thread onto the stack which won't contain another thread's id, why use LIFO term here, isn't that LIFO only be meaningful if we can push multiple items on stack?
The fact that each thread has its own stack doesn't prevent others from existing for other purposes. That each thread has its own stack has no effect on what a sempahore can do or not do with a stack.
Think about apples. You can have them. You can share them. You can eat them.
Now, say there are ten children and each has their own apple. Does that mean there cannot exist an eleventh apple that's shared? Does this prevent them from doing other things with other apples? No, it does not.
So, yes, each thread has its own stack. And they can also share those stacks if they want.
But also, a semaphore can have a stack. And it can do anything it wants with that stack. This has nothing whatsoever to do with any other stacks that threads might have.
I'm having a problem deciding on what to do in this situation, I want to have a detached thread, but still be able to join it in case I want to abort it early, presumably before starting a new instance of it, to make sure I don't have the thread still accessing things when it shouldn't.
This means I shouldn't detach the thread right after calling it, so then I have a few options:
Self-detach the thread when it's reaching the end of its execution, but then wouldn't this cause problems if I try to join it from the main thread? This would be my prefered solution if the problem of trying to join it after it's self-detached could be solved. I could dereference the thread handle that the main thread has access to from the self-detaching thread before self-detaching it, however in case the main thread tries to join right before the handle is dereferenced and the thread self-detached this could cause problems, so I'd have to protect the dereferencing in the thread and however (I don't know how, I might need to create a variable to indicate this) I would check if I should join in the main thread with a mutex, which complicates things. Somehow I have a feeling that this isn't the right way to do it.
Leave the thread hanging until eventually I join it, which could take a long time to happen, depending on how I organise things it could be not before I get rid of what it made (e.g. joining the thread right before freeing an image that was loaded/processed by the thread when I don't need it anymore)
Have the main thread poll periodically to know when the thread has done its job, then join it (or detach it actually) and indicate not to try joining it again?
Or should I just call pthread_exit() from the thread, but then what if I try to join it?
If I sound a bit confused it's because I am. I'm writing in C99 using TinyCThread, a simple wrapper to pthread and Win32 API threading. I'm not even sure how to dereference my thread handles, on Windows the thread handle is HANDLE, and setting a handle to NULL seems to do it, I'm not sure that's the right way to do it with the pthread_t type.
Epilogue: Based on John Bollinger's answer I chose to go with detaching the thread, putting most of that thread's code in a mutex, this way if any other thread wants to block until the thread is practically done it can use that mutex.
The price of using an abstraction layer such as TinyCThreads is that you can rely only on the defined characteristics of the abstraction. Both Windows and POSIX provide features and details that are not necessarily reflected by TinyCThreads. On the other hand, this may force you to rely on a firmer foundation than you might otherwise hack together with the help of implementation-specific features.
Anyway, you say,
I want to have a detached thread, but still be able to join it in case I want to abort it early,
but that's inconsistent. Once you detach a thread, you cannot join it. I suspect you meant something more like, "I want a thread that I can join as long as it is running, but that I don't have to join when it terminates." That's at least consistent, but it focuses on mechanism.
What I think you actually want would be described better as a thread that you can cancel synchronously as long as it is running, but that you otherwise don't need to join when it terminates. I note, however, that the whole idea presupposes a way to make the thread terminate early, and it does not appear that TinyCThread provides any built-in facility for that. It will also require a mechanism to determine whether a given thread is still alive, and TinyCThread does not provide that, either.
First, then, you need some additional per-thread shared state that tracks thread status (running / abort requested / terminated). Because the state is shared, you'll need a mutex to protect it, and that will probably need to be per-thread, too. Furthermore, in order to enable one thread (e.g. the main one) to wait for that state to change when it cancels a thread, it will need a per-thread condition variable.
With that in place, the new thread can self-detach, but it must periodically check whether an abort has been requested. When the thread ends its work, whether because it discovers an abort has been requested or because it reaches the normal end of its work, it performs any needed cleanup, sets the status to "terminated", broadcasts to the CV, and exits.
Any thread that wants to cancel another locks the associated mutex, and checks whether the thread is already terminated. If not, it sets the thread status to "abort requested", and waits on the condition variable until the status becomes "terminated". If desired, you could use a timed wait to allow the cancellation request to time out. After successfully canceling the thread, it may be possible to clean up the mutex, cv, and shared variable.
I note that all of that hinges on my interpretation of your request, and in particular, on the prospect that what you're after is aborting / canceling threads. None of the alternatives you floated seem to address that; for the most part they abandon the unwanted thread, which does not serve your expressed interest in preventing it from making unwanted changes to shared state.
It's not clear to me what you want, but you can use a condition variable to implement basically arbitrary joining semantics for threads. The POSIX Rationale contains an example of this, showing how to implement pthread_join with a timeout (search for timed_thread).
Summary of my understanding:
The top memory addresses are used for the? (I initially thought there was only one call stack) stack, and the? stack grows downwards (What and where are the stack and heap?)
However, each thread gets it's own stack allocated, so there should be multiple call stacks in memory (https://stackoverflow.com/a/80113/2415178)
Applications can share threads (e.g, the key application is using the main thread), but several threads can be running at the same time.
There is a CPU register called sp that tracks the stack pointer, the current stack frame of a call stack.
So here's my confusion:
Do all of the call stacks necessary for an application (if this is even possible to know) get allocated when the application gets launched? Or do call stacks get allocated/de-allocated dynamically as applications spin off new threads? And if that is the case, (I know stacks have a fixed size), do the new stacks just get allocated right below the previous stacks-- So you would end up with a stack of stacks in the top addresses of memory? Or am I just fundamentally misunderstanding how call stacks are being created/used?
I am an OS X application developer, so my visual reference for how call stacks are created come from Xcode's stack debugger:
Now I realize that how things are here are more than likely unique to OS X, but I was hoping that conventions would be similar across operating systems.
It appears that each application can execute code on multiple threads, and even spin off new worker threads that belong to the application-- and every thread needs a call stack to keep track of the stack frames.
Which leads me to my last question:
How does the sp register work if there are multiple call stacks? Is it only used for the main call stack? (Presumably the top-most call stack in memory, and associated with the main thread of the OS) [https://stackoverflow.com/a/1213360/2415178]
Do all of the call stacks necessary for an application (if this is even possible to know) get allocated when the application gets launched?
No. Typically, each thread's stack is allocated when that thread is created.
Or do call stacks get allocated/de-allocated dynamically as applications spin off new threads?
Yes.
And if that is the case, (I know stacks have a fixed size), do the new stacks just get allocated right below the previous stacks-- So you would end up with a stack of stacks in the top addresses of memory? Or am I just fundamentally misunderstanding how call stacks are being created/used?
It varies. But the stack just has to be at the top of a large enough chunk of available address space in the memory map for that particular process. It doesn't have to be at the very top. If you need 1MB for the stack, and you have 1MB, you can just reserve that 1MB and have the stack start at the top of it.
How does the sp register work if there are multiple call stacks? Is it only used for the main call stack?
A CPU has as many register sets as threads that can run at a time. When the running thread is switched, the leaving thread's stack pointer is saved and the new thread's stack pointer is restored -- just like all other registers.
There is no "main thread of the OS". There are some kernel threads that do only kernel tasks, but also user-space threads also run in kernel space to run the OS code. Pure kernel threads have their own stacks somewhere in kernel memory. But just like normal threads, it doesn't have to be at the very top, the stack pointer just has to start at the highest address in the chunk used for that stack.
There is no such thing as the "main thread of the OS". Every process has its own set of threads, and those threads are specific to that process, not shared. Typically, at any given point in time, most threads on a system will be suspended awaiting input.
Every thread in a process has its own stack, which is allocated when the thread is created. Most operating systems will leave some space between each stack to allow them to grow if needed, and to prevent them from colliding with each other.
Every thread also has its own set of CPU registers, including a stack pointer (pointing to a location in that thread's stack).
I just begin to learn OS. I feel puzzle about stack. As I found the stack is attached to each thread. That means the life of the stack is when the thread is created and be reclaimed when the thread is completion.
Also search from the google, the argument and some local variable are stored in the thread. But these are allocated at compile time which seems conflict with the former that the stack is attached to a thread and be reclaimed after the thread is finished.
Any one could give me some detail explanation?
the argument and some local variable are stored in the thread. But these are allocated at compile time
That is not correct.
When a thread is started, a stack is associated with that thread. When a thread terminates, that stack will be reclaimed.
For an example of why that cannot be allocated at compile time, imagine a program that prompts the user for a number of threads to start, and then starts that number of threads. There is no way the compiler could allocate storage for the arguments to methods running on that thread, or for local storage associated with that thread.
I have to use an API to make a call to a third party, and ideally use the response it returns. The API has a built-in 30 second timeout, and does not allow you to set that programatically. I need it to time out in 12 seconds. Here's the call I'm making:
string response = theAPI.FunctionA(a, b, c, d);
I've been thinking I might need to use async calls to accomplish this and abort the thread at 12 seconds. Another stackoverflow question appears to come close to what I'm considering: Implement C# Generic Timeout
...I'm just wondering if this is the best way. Specifically, I keep seeing articles that warn you to call EndInvoke no matter what, and I'm wondering if Abort as in the referenced example will still close the thread appropriately? I see there were some comments with much concern about using Abort.
Aborting threads is generally a bad idea. Why not just let the call complete (or time out after 30 seconds) but ignore the result (and move on) if it takes more than 12 seconds?
Thread.Abort will close the thread, of course, as it will call Win32 TerminateThread.
Outcome of this action will depend on how your API likes to be closed by TerminateThread.
If your method is called somthing like NuclearPlant.MoveRod() or Defibrillator.Shock(), I'd rather wait these 30 seconds.
This method gives no chance to the victim to do some cleanup:
TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code. DLLs attached to the thread are not notified that the thread is terminating. The system frees the thread's initial stack.
As stated in MSDN:
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
If the target thread owns a critical section, the critical section will not be released.
If the target thread is allocating memory from the heap, the heap lock will not be released.
If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.