freertos subpriority of xSemaphoreTake() within same priority tasks - task

I have three tasks with same priority.
Task A
mutextake()
//critical code
mutexgive()
Task B
mutextake()
//critical code
mutexgive()
Task C
mutextake()
//critical code
mutexgive()
Each of them run critical code guarded by a mutex. However I would like to set a "subpriority" to who would take the mutex in the event that two of the tasks are blocking waiting for the mutex. I dont want to set the tasks with different priorities as this will cause complications within the design of other tasks. Is this a feature with freertos to set a "subpriority" for a task to grab a mutex before another of the same priority?

In a word "no". FreeRTOS inter-task communication objects (https://www.freertos.org/Inter-Task-Communication.html) have lists of tasks waiting to send and lists of tasks waiting to receive (taking a mutex being a receive). The task in the list that succeeds when the operation can complete is the task with the highest priority - or if the tasks have equal priority - the task that has been waiting the longest.

Related

multiple definitions for serial queue online, so got confused

i have came across two kind of definitions for serial queue after reading online.
1st version: serial queue performs one task at a time.
2nd version: serial queue execute tasks serially, so task1 have to finish before task2 starts.
can you tell me which one is right exactly ?
As Ratul Sharker said, both versions are saying the same thing.
1st version: serial queue performs one task at a time.
You only can have one task running, so your task have to finish before another is started.
Task 1 starts
Task 1 ends
Task 2 starts
Task 2 ends
2nd version: serial queue execute tasks serially, so task1 have to finish before task2 starts
Obviously, the result is the same as the 1st version.
But! That 2nd version might be speaking of callbacks or another sort of paradigms with multithreading, where you could run more than one task, but Task 2 will wait for Task 1 to end.
In any case, two tasks are serial if one starts after the other ends, simple as that.
From the appledoc
Operations within a queue are organized according to their readiness, priority level, and interoperation dependencies, and are executed accordingly. If all of the queued operations have the same queuePriority and are ready to execute when they are put in the queue—that is, their isReady property returns true—they’re executed in the order in which they were submitted to the queue. Otherwise, the operation queue always executes the one with the highest priority relative to the other ready operations.
However, you should never rely on queue semantics to ensure a specific execution order of operations, because changes in the readiness of an operation can change the resulting execution order. Interoperation dependencies provide an absolute execution order for operations, even if those operations are located in different operation queues. An operation object is not considered ready to execute until all of its dependent operations have finished executing.
So the queued operations are intended to be executed serially, but it never garunteed. To ensure execution order dependencies must be specified to get the full proof exact behaviour.

iOS GCD custom concurrent queue execution sequence

I have question regarding this issue ,
According to Apple's documents
Concurrent
Concurrent queues (also known as a type of global dispatch queue) execute one or more tasks concurrently, but tasks are still started in the order in which they were added to the queue. The currently executing tasks run on distinct threads that are managed by the dispatch queue. The exact number of tasks executing at any given point is variable and depends on system conditions.
In iOS 5 and later, you can create concurrent dispatch queues yourself by specifying DISPATCH_QUEUE_CONCURRENT as the queue type. In addition, there are four predefined global concurrent queues for your application to use. For more information on how to get the global concurrent queues, see Getting the Global Concurrent Dispatch Queues.
And i do a test, using the sample code ,
dispatch_queue_t concurrentQueue;
concurrentQueue = dispatch_queue_create("com.gcd.concurrentQueue",
DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSLog(#"First job ");
});
dispatch_async(concurrentQueue, ^{
NSLog(#"Second job");
});
dispatch_async(concurrentQueue, ^{
NSLog(#"Third job ");
});
But the results seems not as the order in which they are added, here is the results,
2015-06-03 18:36:38.114 GooglyPuff[58461:1110680] First job
2015-06-03 18:36:38.114 GooglyPuff[58461:1110682] Third job
2015-06-03 18:36:38.114 GooglyPuff[58461:1110679] Second job
So my question is , shouldn't it be
First, Second , Third ?
Any advice is welcome , and thanks for your help.
"Concurrent" means they run at the same time and no assumptions should be made about where in their progress any of them will be at any given moment and which will finish first. That is the whole meaning and implication of concurrency: between one line of code and the next in one concurrent operation - even during one line of code - anything else from any other concurrent operation might be happening.
So, in answer to your particular question, these tasks may have started in a known order, but that happened very quickly, and after that point their progress is interleaved unpredictably. And your NSLog calls are part of that progress; they do not, and cannot, tell you when the tasks started!
The documentation is correct - they will indeed start in the order you added them to the queue. Once in the queue, they will be started one after the other, but on concurrent threads. The order they will finish is dependent on how long the task will take to execute. Here's a thought experiment, imagine your code was like this instead:
dispatch_async(concurrentQueue, ^{
JobThatTakes_3_SecToExecute(); // Job 1 (3 seconds to execute)
});
dispatch_async(concurrentQueue, ^{
JobThatTakes_2_SecToExecute(); // Job 2 (2 seconds to execute)
});
dispatch_async(concurrentQueue, ^{
JobThatTakes_1_SecToExecute(); // Job 3 (1 second to execute)
});
The overhead in and out of the queue should be very small compared to these job lengths, so you would expect them to finish up in about the time that their task takes to execute. In this case they'd finish roughly 1 second apart starting with Job 3, then 2, then 1. The total time the queue would take to complete will be about the length of Job 1, since it takes the longest to execute. This is lovely, since the total time is set primarily by the longest job, not the sum of the jobs. However, you don't have any say in what order they finish, since that's dictated by the task duration.
Change dispatch_async to dispatch_sync in this example and the queue will take about 6 seconds to complete. They'll come out in this order: Job 1, 2, then 3. This will guarantee that your results come out in the order you wanted, but it will take much longer.
So back to the significance of what the docs mean by "tasks are still started in the order in which they were added to the queue" for concurrent queues. This will be noticeable if your job is resource constrained. Say you're putting a big pile of long duration tasks in a concurrent queue on a 2 CPU machine. It is unlikely you'll be able to run a dozen CPU-pegging tasks concurrently here; some will have to wait while others run. The order that you put them into the queue will decide who gets to run next as resources free up. In your example, the tasks are of super short duration and involve console locking (as Rob mentioned), so queue / locking overhead can mess with your expectations.
Another (probably more important) reason the order of execution in concurrent queues matter is when barriers are used. You may need to run some sort of a task every N other tasks, which is where a barrier would come in handy. The fixed order of execution will assure that the barrier executes after N tasks have completed concurrently, provided you put the barrier in the queue in the right spot.

NSOperation - queuePriority

What does queuepriority mean. According to what i understand, it decides the execution within the operation queue. But, when i use a queue with only 1 concurrent operation, the queue priority does not make any effect. It executes the operation in the same order in which it is added.
The queuePriority property might have no effect, as you said yourself, in cases where a queue is serial only in which case operations are executed in the order they arrive. This is not 100% accurate because the operations will attempt to be launched in the order of priorities but I'm guessing that in the case you describe the operations are getting enqueued slower than they are being executed. Consider this example of a completely legal execution sequence:
If Op1 already executes by the time Op2 is enqueued, Op1 will not be interrupted in favor of Op2, even if Op2's priority is higher.

NSOperation hierarchy, units of work

So I was wondering what the best way to break out long tasks into NSOperations. If I have 3 long running tasks, is it better to have one NSOperation subclass that basically does something like
Single NSOperation subclass
- (void)main {
// do long running task 1
// do long running task 2
// do long running task 3
// call back the delegate
}
Or is it better to have each task be a subclass of NSOperation, and then manage each task from my ViewController as a single unit of work? Thanks in advance.
It depends whether the operation queue is serial (i.e. max concurrent operations 1) or parallel, and what the nature of the work is. If the queue is serial, then it really doesn't matter. If the queue is parallel, then it depends on a bunch of factors:
is the work safe to do concurrently
does the work contend on a shared resource (such as network or disk IO, or a lock) that would remove the concurrency
is each unit of work sufficiently large to be worth the overhead of dispatching separately
(edit)
Also, if you don't need the advanced features of NSOperationQueue (operation dependencies and priorities, KVO, etc...), consider using dispatch queues instead. They're significantly lighter weight.

Is dispatch_sync(dispatch_get_global_queue(xxx), task) sync or async

As Apple's document says, dispatch_get_global_queue() is a concurrent queue, and dispatch_sync is something meaning serial.Then the tasks are processed async or sync?
You're getting confused between what a queue is and what async vs sync means.
A queue is an entity on which blocks can be run. These can be serial or concurrent. Serial means that if you put block on in the order A, B, C, D, then they will be executed A, then B, then C, then D. Concurrent means that these same blocks might be executed in a different order and possibly even more than one at the same time (assuming you have multiple cores on which to run, obviously).
Then onto async vs sync. Async means that when you call dispatch_async, it will return immediately and the block will be queued on the queue. Sync means that when you call dispatch_sync it will return only after the block has finished executing.
So to fully answer your question, if you dispatch_sync onto a global concurrent queue then this block will be run, perhaps in parallel with other blocks on that queue, but in a synchronous manner - i.e. it won't return until the block is finished.
Apple Doc says
dispatch_get_global_queue
Returns a well-known global concurrent queue of a given priority
level.
dispatch_queue_t dispatch_get_global_queue(
long priority,
unsigned long flags);
Parameters
priority The priority of the queue being retrieved. For a
list of possible values, see “dispatch_queue_priority_t”. flags This
value is reserved for future use. You should always pass 0. Return
Value Returns the requested global queue.
Discussion
The well-known global concurrent queues cannot be modified.
Calls to dispatch_suspend, dispatch_resume, dispatch_set_context, and
the like have no effect when used with queues returned by this
function.
Blocks submitted to these global concurrent queues may be executed
concurrently with respect to each other.
Availability Available in iOS 4.0 and later. Declared In
dispatch/queue.h
In the Discussion they have said that-> 'blocks submitted MAY be executed concurrently wrt each other.'
So Tasks may be processed Async with each other.

Resources