how to schedule after the current thread has terminated? - stack

I am creating a user defined thread library. I use Round-Robin scheduling algorithm and use the context switching method. But, I am unable to know what to do when a thread finishes its execution before the allotted time slot. The program is getting terminated. I actually want to reschedule all the threads, by calling the schedule function when the current thread gets terminated.
I found two ways to overcome this problem.
By calling explicitly thread_exit function at the end of the function that is being executed by the current thread.
By changing the stack contents such that the thread_exit function gets executed after the current function gets terminated.
But I am unable to find how to apply these solutions....
Anybody out there... plz help me...

It sounds like you have a bit of a design flaw. If I'm understanding you correctly, you're trying to implement a solution where you have threads that can be allocated to perform some task and after the task is complete, the thread goes idle waiting for the next task.
If that's true, I think I would design something like a daemon process or service that manages a queue for tasks coming in, a pool of threads responsible for executing the tasks with a controller that listens for new tasks.

Related

Freertos Cortex M3 - Port Yield jumps back to main()

im currently implementing freertos on a efm32gg mcu.
i use a startup thread to initialize the project.
this thread disables context switch (TaskSuspendAll) during the project initialization where other modules create their threads, so the initialization is only interrupted by interrupts, not by other threads.
at the end of the project initialization, the startup thread enabled context switch (ResumeAll).
the current demo project adds 1 thread which would blink a led.
as soon as the startup thread enables critical sections, which leads to the portYield call at some point, the application jumps back to the main() (I dont know if through a reset or through a call to main).
but when i just use the startup thread and keep the project initialization function empty, then as desired, freertos keeps running the idle task..
does someone have an idea what the reason for such a behavior could be?
With regards to creating threads while the scheduler is suspended, see number list item 9 on the following page of the FAQ, which basically says not to do that. The reason being that creating a thread may result in a context switch being needed (if the thread has a priority above the thread that created it), but if the scheduler is suspended that can't happen: https://www.freertos.org/FAQHelp.html
If you want to have an initialisation thread that creates other threads, but you don't want the other threads to run yet, then I would recommend having the priority of the initialisation thread above that of any threads it creates - then the scheduler won't choose any other threads. At the end of initialisation you can lower the priority of the initialisation thread, or just delete it, whichever is most appropriate.
I suspect in your case the board is being reset somehow, so you need to find the source of that.

What happens in hardware on SAME thread async calls?

Note, related but not the same: iPhone - Grand Central Dispatch main thread
I've failed at this question many times, so here's source code:
While on the main thread
dispatch_async( dispatch_get_main_queue(), ^{ NSString * str = #"Interrupt myself to do something."} );
I'm just curious, when a thread switches, it stores its registers in Thread Local Storage, switches context, runs from its new spot in the Program Counter (which I assume is within a copy of the program that simply uses a different stack and register), then it "goes back" to the main thread.
When it interrupts itself, I'm just wondering what decides when it should, and what happens to the Thread Local stuff.
I've read up on this a little, but I'm still wrapping my head around the fact that programs are not continuous. They're just "something to do in small chunks when the OS decides to run a chunk of a process, or its chunks (threads).
I am self-taught, which might add to my lack of register/asm knowledge that may be standard to any scholar.
Thanks. The code should help, this is iOS specific, but I believe the answer/question is related to any language going from main-to-main.
Since every past attempt has resulted in lengthy answers that ignore the reason I'm asking this, I will iterate one last time....
This is for the SAME thread. Main-to-main. Does it really just stop itself, move the program counter elsewhere, go, then end at the block? Also don't these things usually change at branches (if/for and blocks too).
Pointing me in the right direction works too, but like I said, previously the question was misread.
It is hard to answer your question specifically without having access to the internals of GCD, but generically, the answer is no, simply adding a unit of work to a dispatch queue will not immediately interrupt the executing code.
As you suggest context switches are expensive, not only in terms of state saving & restoration but also the processor will need to dump the instruction pipeline resulting in wasted cycles.
Typically the operating system will keep executing the current task until it suspends (e.g. waits on a network or other IO operation) or perhaps is interrupted by some external event (pressing the home key on the phone), but there are also time limits to prevent a runaway task from locking the whole device (This is pre-emptive multi-tasking, as opposed to co-operative multitasking where the task needs to relinquish the CPU)
With dispatch_async there is no guarantee of when the code will execute in relation to the current code block. The code block may not even be next in the queue - other threads may have added other units of work to the queue before this one.
I think the thing that's confusing you is the use of dispatch_async( dispatch_get_main_queue()), which submits code to run on a queue on the main thread.
Using dispatch_async on the main queue:
When you call dispatch_async( dispatch_get_main_queue()), it adds a unit of work to the main queue, which runs it's jobs from the main thread.
If you run this call from the main thread, the results are the same. The work gets added to the main queue for later processing.
When you make this call from the main thread, the system doesn't check the main queue for work to do until your code returns.
Think of this as a one-cook kitchen. As the cook works, he puts trays of dishes in the dishwashing area. He doesn't stop to do dishes until he gets to a breaking point in what he's currently doing. At that point he takes a tray of dishes, loads it into the dishwasher, and then goes back to cooking.
The cook knows that he has to check for dishes each time he gets to a breaking point, and then completes a dishwashing task before returning to cooking.
Using dispatch_async on a background queue:
A dispatch_async call to a background queue is like a 2-person kitchen. There is a dishwasher working at the same time. The cook puts a tray of dishes into the dishwashing station (the queue) and the dishwasher (the other thread) picks up that task as soon as it's finished with it's previous tasks, while the cook continues to work on cooking.
The above assumes a machine with multiple processors, which is the norm these days. Each processor can do work at the same time without having to juggle multiple tasks.
If you are running on a single-core system with preemptive multitasking, submitting tasks to separate threads/background queues has the same effect as if there were multiple processors, but now the OS has to do a juggling act. There's only one person in the kitchen, but he wears multiple hats. The person is doing the cook job, and the OS shouts "Switch!" The cook jots down notes on what he was doing (saves state) and then jumps into the dish-pit and starts washing dishes, and keeps washing dishes until the OS yells "Switch!" again, and the worker again saves state, switches to the next role, and picks up that role (cook) where it was left off.
Multi-tasking is more costly on a single-core system because each time the worker switches roles, it has to save the current state, then load the saved state for the other role, and continue. Those context switches take time.

Stop child threads started by `performSelector` on `viewDidDisappear`

To begin, I realise I may be causing this problem by addressing a previous problem incorrectly...
In a ViewController main thread I am starting a background thread to get updated data from a server using:
[self performSelectorInBackground:#selector(sampleTask:) withObject:#"CMD" ];
This process can take 15-30 seconds so in the main thread I display a local cache of the data from a SQLite database (populated from a previous request to the server the last time the view was opened) and reload the table once the sync with the server is finished.
If the user navigates back out of this view before the sync with the server is finished, the background thread keeps running until it is done. This itself isn't a problem, until the user changes their mind and goes back into this view again. If the timing is right, there's two background threads trying to sync data with the server. If the user does this a few times, the thread count can build up. Eventually the app will collapse, if not cause other problems on the device.
Is there a way to stop the created threads on a trigger like viewDidDisappear?
Or should I be writing a lock to a shared resource (e.g. NSUserDefaults) to prevent a new background thread from being started?
Or -- like I mentioned in the first line -- do I have a bad approach to the issue of updating the local cache that is just causing further problems like this one?
I think you can use simple bool valued semaphore which shows that some sync task is performing. So before performing the next similar task you should check that semaphore.
If you recreate your viewcontroller each time you need static class variable common for all instances of your view controller.
performSelector:withObject:afterDelay: does not create a separate thread.
To quote part of the docs on that method:
Invokes a method of the receiver on the current thread using the
default mode after a delay
It uses a timer to trigger your selector after a delay. As such it is subject to the same accuracy limitations as NSTimer. (The method performSelectorInBackground:withObject: does submit your selector on a background thread.)
But back to your question.
You can use the method
cancelPreviousPerformRequestsWithTarget:selector:object:
To cancel a pending call to performSelector:withObject:afterDelay:

Suspending already executing task NSOperationQueue

I have problem suspending the current task being executed, I have tried to set NSOperationQueue setSuspended=YES for pausing and setSuspended=NO for resuming the process.
According to apple docs I can not suspend already executing task.
If you want to issue a temporary halt to the execution of operations, you can suspend the corresponding operation queue using the setSuspended: method. Suspending a queue does not cause already executing operations to pause in the middle of their tasks. It simply prevents new operations from being scheduled for execution. You might suspend a queue in response to a user request to pause any ongoing work, because the expectation is that the user might eventually want to resume that work.
My app needs to suspend the time taking upload operation in case of internet unavailability and finally resume the same operation once internet is available. Is there any work around for this? or I just need to start the currently executing task from zero?
I think you need to start from zero. otherwise two problems will come there. If you resume the current uploading you cant assure that you are not missed any packets or not. At the same time if the connection available after a long period of time, server may delete the data that you uploaded previously because of the incomplete operation.
Whether or not you can resume or pause a operation queue is not your issue here...
If it worked like you imagined it could (and it doesn't) when you get back to servicing the TCP connection it may very well be in a bad state, it could have timed out, closed remotely...
you will want to find out what your server supports and use the parts of a REST (or similar) service to resume a stalled upload on a brand new fresh connection.
If you haven't yet, print out this and put it on the walls of your cube, make t-shirts for your family members to wear... maybe add it as a screensaver?

Why a thread is aborted in ASP.NET MVC (again)?

Here is what I do in a controller action:
create and start a new Thread that does a relatively long processing task (~30 seconds on average, but might be several minutes)
immediately return the page response so the user knows processing has started (trivially, a Json with a task ID for polling purposes).
At some random point, ThreadAbortException is thrown, so the async task does not complete. The exception is not thrown every time, it just happens randomly roughly 25% of the times.
Points to note:
I'm not calling Response.End or Response.Redirect - there isn't even a request running when the exception is thrown
I tried using ThreadPool and I got the same behavior
I know running threads in ASP.NET has several caveats but I don't care right now
Any suggestion?
The problem is you shouldn't do it this way. If you need a task to run for a long period of time in the background ASP.Net should either spawn a process to handle it or add the work item to a queue for a Windows Service to handle.
Does this help since you want to fire and forget.
"Delegates provide a method called BeginInvoke that allows us to call the delegate asychronously."
http://hackingon.net/post/Asynchronous-fire-and-forget-method-calls-in-NET.aspx
How about using an Asynchronous controller?
The problem was that the app was being recycled. I perfectly know that when that happens, all threads are aborted, I didn't expect the application to recycle. The reason is that the async process used changed temp files stored in the app root, and that caused a recycle.
I feel dumb.

Resources