FreeRTOS: two tasks with interrupt - freertos

I'm completely new with FreeRTOS. I have two tasks: the first one must be performed continuously in the loop and the second one should turn on only after interrupt and after the second one is done it should return to the first one, which needs to start from the beginning(it's important because the first task collects data and if I continue to perform it from the place where I interrupt I will get the trash.).
Can I use Semaphore for it or is there something better? Thank you in advance.

It is not clear what you are asking or what you want to use the semaphore for. Protecting data access by both the interrupt and the first task? Or maybe signaling the first task? From what I can make out it sounds like you want to have a lower priority task running continuously, then when an interrupt occurs have the interrupt handler unblock a higher priority task that will then preempt the lower priority task and execute. Then when it finishes and blocks again the scheduler will naturally continue running the lower priority task. I'm confused by your statement that if you continue executing from where it was interrupted you will get trash though - interrupts always return to where they interrupted.
The most efficient way of unblocking a task from an interrupt would be a direct-to-task notification. I would also recommend reading some of the generic FreeRTOS documentation and books available on the FreeRTOS.org site.

Related

Task Preemption in FREE RTOS

Going through the manual for Free RTOS, I encountered a sentence where it mentions
It is important to note that the end of a time slice is not the only
place that the scheduler can select a new task to run; as will be
demonstrated throughout this book, the scheduler will also select a
new task to run immediately after the currently executing task enters
the Blocked state, or when an interrupt moves a higher priority task
into the Ready state.
I am confused with the way preemption works in Free RTOS. Consider a task A with priority 1 is in RUNNING state. Also consider task B with higher priority 2 enters READY state when the task A is in the middle of the time slice.
Q1: What type of interrupt is the manual talking about?
Q2: Is the interrupt only way to take the task B to READY state while the task A is in RUNNING state?
Q3: If answer to Q2 is no, when would the task switching occur if it is not interrupt driven? Is it after the time slot ends or is it immediately at the middle of the time slice without waiting for the end of time slice?
You describe the following situation where you have two tasks with different priorities:
Task A with priority 1 (lower), currently in RUNNING state
Task B with priority 2 (higher), entering READY state
In this situation, it's important to ask yourself a question - what would be the possible scenarios that would lead to this situation?
The general rule of a thumb when dealing with tasks of different priorities in FreeRTOS is that the higher priority task will be given all the available time, unless it cannot run due to being SUSPENDED, BLOCKED (waiting for queue, semaphore, mutex) or put in a delay (this also falls into BLOCKED state). Therefore in your case - task A would never enter RUNNING state unless task B was previously either SUSPENDED or BLOCKED.
To answer your questions:
Q1: What type of interrupt is the manual talking about?
I'd assume they're talking about a situation where task B is in a blocked state due to waiting for semaphore/queue and you "give a semaphore" / "send to quque" from an interrupt. Examples of this happening: IO level interrupt giving a semaphore, UART interrupt pushing received byte into a queue.
Q2: Is the interrupt only way to take the task B to READY state while the task A is in RUNNING state?
I'd say no. Other examples that come to mind (apart from the interrupt cases mentioned above):
Task B is SUSPENDED and task A decides to resume task B. When you do so, task B should resume execution immediately and take all the available time from this point on, unless it again enters SUSPENDED or BLOCKED state.
Task B is waiting for a mutex held by task A and task A releases it.
Task B is waiting on a semaphore/queue and task A "gives semaphore", "sends to queue".
Task B was in a delay and that delay ended.
Q3: If answer to Q2 is no, when would the task switching occur if it is not interrupt driven? Is it after the time slot ends or is it immediately at the middle of the time slice without waiting for the end of time slice?
I already listed possible examples above. To mention it again - when you have two tasks with different priorities, then unless the higher priority task gets into BLOCKED or SUSPENDED state, it'll take all available time from the lower priority task. While technically you can still speak of "time slices" in this case, all of the slices will be assigned/consumed by higher priority task. Therefore, speaking of "time slicing" only really makes sense when you have two or more tasks running with same priority, in which case time should be split between them evenly (unless they get BLOCKED or SUSPENDED).

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.

How can I change the background operation priority dynamically using Dispatch or Operation queues.

Here is the problem that I got. I have several tasks to complete in background when application is running. When I run these tasks in background by pushing them to concurrent dispatch queue it takes more then 10 seconds to complete all of them. They basically load data from disk and parse it and represent the result to the user. That is they are just cached results and hugely improve the user experience.
This cached results are used in a particular functionality inside the app, and when that functionality is not used immediately after opening the application, it is not a problem that it takes 10 seconds to load the data that supports that functionality, because when user decides to use it, that data will already be loaded.
But when user immediately enters that function in the app after opening it, it takes considerable time (from the point of view of the user) to load the data. Also the whole data is not needed at the same moment, but rather the piece of it at a given moment.
That's why we need concurrently load the data, and if possible bring the results as soon as possible. That's why I decided to break the data into chunks, and when user requests the data, we should load the corresponding chunk by background thread and give that thread the highest priority. I'll explain what I mean.
Imagine there are 100 pieces of data and it takes more than 10 seconds to load them all. Whenever user queries the data first time, the app determines which chunk of the data user needs and starts loading that chunk. After that part is loaded the remaining data will also be loaded in the background, in order to make later queries faster (without the lag of loading the cache). But here a problem occurs, when user decides to change the query immediately after he has already entered one, and that change occurs for instance on the 2nd second of data loading process (remember it takes more than 10 seconds to load the data and we still have more than 8 seconds to complete the loading process), then in the extreme case user will receive his data waiting until all data will be loaded. That's way I need somehow manage the execution of the background tasks. That is, when user changes the input, I should change the priorities of execution, and give the thread that loads the corresponding chunk the highest priority without stopping it, so it will receive more processor time, and will finish sooner, and deliver results to the user faster, than it would if I have left the priorities the same. I know I can assign priorities to queues. But is there a way that I can change them dynamically while they are still executing?
Or do I need to implement custom thread management, in order to implement these behaviour? I really don't want to dive into thread management, and will be glad if it is possible to implement using only dispatch or operation queues.
I hope I've described the problem well. If not please comment bellow what is unclear, I'll explain.
Thank you so much for reading so far :) And special thanks to one who will provide an answer. And very special thanks to one, who will give me solution using dispatch or operation queues :)))
I think you need to move away from thinking about the priority at which the queues are running (which actually doesn't sound very important for the scenario you are describing) and more towards how you can use Dispatch I/O or an even simpler Dispatch source to control how the data is being read in. As you say, it takes 10 seconds the load the data and if the user suddenly changes their query immediately after asking, you need to essentially stop reading the data for the previous request and do whatever needs to be done to fulfill the most recent query. Using Dispatch I/O to chunk the data (asynchronously) and update the UI also asynchronously will allow you to change your mind mid-stream (using some sort of semaphore or cancellation flag) and either continue to trickle the data in (you don't say whether or not that data will remain useful if the user changes their mind or not), suspend the reading process, or cancel it altogether and start a new operation. Eithe way, being able to suspend/resume a source and also have it fire callbacks for reasonably small chunks of data will certainly enable you to make decisions on a much more granular chunk of time than 8 seconds!
I'm afraid the only way to do that is to cancel running operation before starting new one.
You cannot remove it from queue until it's done or canceled.
As an improvement for your problem I would suggest to load things even user doesn't need them in background - so you can load them from cache after it's there.
You can create 2 NSOperationQueue with 2 different priorities and download things in background whenever user is idle on LowPriorityQueue. For important operations you can have high priority queue - which you will cancel each time search term changes.
On top of that you just need to cache results from both of those queues.

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?

How can I sequence asynchronous background tasks with GCD?

I am using GCD on iOS to perform a a time-consuming task on a background thread. The API has a start method that takes two blocks as arguments, both called on the main queue. The first is called when the task starts and the second when the task finishes. This all works.
I actually need to do several of these time-consuming tasks. The API lets me start them all at the same time and then wait for each to finish and update the UI via the blocks. They run concurrently.
However what I actually I want to do is to sequence the time-consuming tasks (still starting each using the API described) so that I can start them all at the same time, have the first one run and give me its call-backs, then have the second one run and give me its call-backs, etc. until all are done.
What is the best way to achieve this with GCD and blocks?
If the tasks were synchronous, I'd just have a loop that ran each in turn, and run all of that asynchronously. But I have call-backs, so that will not work. I'd prefer not to have to chain them, since the object that makes all of this happen could disappear once it has started the sequence of events.
You can create your own serial queue that will execute in FIFO order with dispatch_queue_create. You DO NOT need to specify that it is a serial queue. It will act this way by default.
Sample queue creation:
dispatch_queue_t my_q = dispatch_queue_create("Serial",NULL);
You own this queue, so failing to release it (with dispatch_release) will leak it.
More info is in Apple's docs here.
Is there a particular reason you have to use GCD? Sounds like NSOperationQueue with concurrency of 1 is exactly what you want.

Resources