If there are 3 tasks(T1,T2,t3) with priority P1 P2 P3.
P1 is pended.
Assume that task P2 is doing some computation. During its execution, it wants to Yield the CPU to other tasks in the system.
Will TaskDelay(0) still works in this condition? or it works only when all the tasks are with same priority?
Regards, Prabhu
taskDelay(0) will not cause a lower priority task to take control of the CPU.
Only if a task at the same priority is ready to execute would taskDelay(0) cause a context switch.
taskDelay(0) essentially causes a task at priority x to be put at the end of the priority x ready queue. If it is the only task at that priority, it retains the CPU.
Related
I have a situation here in my code where all tasks are running with same priority based on round robin (with fixed time slice of 50ms) scheduling algorithm. Now I want to run one particular task say Task A, exactly within a time period of 10ms to update some communication db. Since,current scheduling is based on round robin with fixed time slice of 50ms due to that the Task A is not able to get called exactly in 10ms. I am not getting any solution to cope up with the current problem.
Please do provide your valuable suggestion & advice.
Thanks in advance,
Vijay Khaitan
Not exactly sure what you are asking here. If you do not want Task A to run longer than 10ms, and you know that you will return from your communication functions in less than that, you can take a time reading at the beginning of Task A, and call osThreadYield() from Task A after you hit 10ms (busy loop).
If you are somewhere in Task B, and need to call Task A in exactly 10ms, it becomes a bit more complicated, since you don't know what thread can preempt your Task B at that time. What you can try, is in Task B, keep a handle to Task A. Then when you are ready to wait 10ms, do the following:
osThreadId id;
id = osThreadGetId (); // id for the currently running thread
osThreadSetPriority(id, osPriorityRealtime); // Make sure we get back here quickly
osWait(10); // Wait 10ms
osThreadSetPriority(id, osPriorityNormal); // Go back to normal
// If you need to create Task A, do so here, otherwise you can
// use osSignalSet here and osSignalWait in Task A
You can also call directly create Task A, set its priority to osPriorityRealtime, yield from Task B, and have the first method in Task A be osWait(10). As soon as you return, set its priority back to normal.
I am working on an embedded application for an ARM platform and a PowerPC platform as well. This application is a bare-metal application so no OS whatsoever. It will perform all initialization of hardware before entering an infinite loop from where my main application logic will reside.
My main question is is there any way interrupts can be used to perform asynchronous behavior(thinking thread like functionality) to check certain characteristics of the hardware and on any hardware subsystem error, cause a reset, log the occurrence, etc. I guess I am trying to implement something like a watchdog but I want it to behave completely asynchronously and without requiring any intervention by the main application(like kicking the watchdog). Thanks!
Round-Robin Scheduling - is what you probably need to implement or just use already existed (a number of them are open and accessible on the net).
Round-robin (RR) is one of the algorithms employed by process and network schedulers in computing. As the term is generally used, time slices are assigned to each process in equal portions and in circular order, handling all processes without priority (also known as cyclic executive). Round-robin scheduling is simple, easy to implement, and starvation-free. Round-robin scheduling can also be applied to other scheduling problems, such as data packet scheduling in computer networks. It is an Operating System concept.
In order to schedule processes fairly, a round-robin scheduler generally employs time-sharing, giving each job a time slot or quantum (its allowance of CPU time), and interrupting the job if it is not completed by then. The job is resumed next time a time slot is assigned to that process. In the absence of time-sharing, or if the quanta were large relative to the sizes of the jobs, a process that produced large jobs would be favoured over other processes.
Round Robin algorithm is a pre-emptive algorithm as the scheduler forces the process out of the CPU once the time quota expires.
For example, if the time slot is 100 milliseconds, and job1 takes a total time of 250 ms to complete, the round-robin scheduler will suspend the job after 100 ms and give other jobs their time on the CPU. Once the other jobs have had their equal share (100 ms each), job1 will get another allocation of CPU time and the cycle will repeat. This process continues until the job finishes and needs no more time on the CPU.
But before bringing RR into your application you need first to be able to enable and adjust a timer interrupt and its handler. Once you've done with processing timer IRQ you can even implement simple stuff inside it or think about RR or simple RTOS.
What I would suggest is a central loop that calls the foreground handlers.
The interrupt service routines put a value in a byte somewhere.
The foreground handlers look at that byte
The foreground and background "communicate" with that byte (or a structure of some sort)
Here's some pseudo code
The_Top_Of_This_Loop:
Call Check_What_ISR_01_Did
Call Check_What_ISR_02_Did
Call Check_What_ISR_03_Did
Call Check_What_ISR_04_Did
Call Update_The_Rest_Of_The_System
Jump The_Top_Of_This_Loop
The foreground subroutine will do something like this (again, pseudo code, you write something real)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Subroutine name: Check_What_ISR_01_Did ;
; ;
; Looks at the indicator from the background and takes ;
; the appropriate action. ;
; ;
; On Entry: Nothing ;
; ;
; On Exit: Reg_00 is messed up, don't believe it ;
; ;
; ;
; ;
; ;
; ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Check_What_ISR_01_Did:
Move Reg_00.Byte, The_ISR_01_Flag ;The ISR Set this if he did anything
Cmp Reg_00.Byte, Nothing_Happened ;Did anything happen since last time ?
Jz We_Are_Done ;No, there's nothing to do
; ;else yes, so examine what to do
; ;and so on
; ; blah
; ; blah
; ; blah
We_Are_Done:
Return ;End of foreground routine
The actual ISR will do something like this...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Interrupt Service Routine 01 ;
; ;
; Checks to see if a button was pushed. ;
; ;
; On Entry: Nothing ;
; ;
; On Exit: The_ISR_01_Flag is updated to hold ;
; a value which the foreground will ;
; use to make a decision ;
; ;
; ;
; ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ISR_01:
Push {All The Registers And Flags} ;This is the background; leave with no trace
; ;Do whatever
; ; your real
; ; code needs
; ; to do to look
; ; at a button
Move Reg_00.Byte, Nothing_Happened ;This is a defined constant value somewhere
Move The_ISR_01_Flag, Reg_00.Byte ;The foreground routine will see this
Jump We_Are_Done ;There's nothing else to do now
We_Are_Done:
Pop {All The Registers And Flags} ;Don't forget the stack
IntReturn ;End of ISR
Again, this is all pseudo code, use real syntax and so on.
You can use a timer and routinely check on the hardware characteristics. However if the timer is regular and in sync with the clock, it is a synchronous interrupt.
Any interrupt that happens asynchronously(i.e, without being in sync with clock) can be handled by an ISR. In ARM, they refer to interrupts as exception . Based on the time required for Hardware verification, the routines to check hardware characteristics can be made in such exception handlers.
One of the main purpose of RTOS is to give time bound results and for addressing real time asynchronous events/interrupts. However, the RTOS is able to handle such multiple asynchronous tasks / interrupts due to the presence of scheduler which in turn relies on context switch. So, you may need to have a thin layer of scheduler on bare metal. The type of scheduler in term depends based on your requirement. If time is not a concern, you may just keep pushing into a queue and handle it at your own time, else you may need to have an appropriate scheduler.
There is one Producer and n consumers.
producer us assigning n jobs to n consumers and calling pthread_cond_wait() n times to wait for the assigned job to be completed by consumers.
Each Consumer after consuming job calls pthread_cond_signal() to notify the producer.
My question is "Will n calls to pthread_cond_signal() by consumer makes the producer to come out of pthread_cond_wait() n times? Or is there any case where multiple signals be merged into single signal so that pthread_cond_wait() comes out less than n times?
If the producer isn't actually waiting inside a call to pthread_cond_wait() when a consumer thread calls pthread_cond_signal(), then that signal will get 'lost' (ie., if the producer thread later rolls into the pthread_cond_wait(), it will block until another signal is sent).
That is why condition variables must be used in conjunction with some other "boolean predicate" that is checked while holding the mutex used with the condition variable. That predicate is the actual final word on whether or not the thread deciding whether or not to wait should wait. Another reason that the predicate is the final word is that a thread blocked in pthread_cond_wait() can be spuriously awakened.
From the POSIX docs on pthread_cond_wait():
When using condition variables there is always a Boolean predicate
involving shared variables associated with each condition wait that is
true if the thread should proceed. Spurious wakeups from the
pthread_cond_timedwait() or pthread_cond_wait() functions may occur.
Since the return from pthread_cond_timedwait() or pthread_cond_wait()
does not imply anything about the value of this predicate, the
predicate should be re-evaluated upon such return.
I am going through process synchronization, and facing difficulty in understanding semaphore. So here is my doubt:
the source says that
" Semaphore S is an integer variable that is accessed through standard atomic operations i.e. wait() and signal().
It also provided basic definition of wait()
wait(Semaphore S)
{
while S<=0
; //no operation
S--;
}
Definition of signal()
signal(S)
{
S++;
}
Let the initial value of a semaphore be 1, and say there are two concurrent processes P0 and P1 which are not supposed to perform operations of their critical section simultaneously.
Now say P0 is in its critical section, so the Semaphore S must have value 0, now say P1 wants to enter its critical section so it executes wait(), and in wait() it continuously loops, now to exit from the loop the semaphore value must be incremented, but it may not be possible because according the source, wait() is an atomic operation and can't be interrupted and thus the process P0 can't call signal() in a single processor system.
I want to know, is the understanding i have so far is correct or not. and if correct then how come process P0 call signal() when process P1 is strucked in while loop?
I think the top-voted answer is inaccurate!
Operation wait() and signal() must be completely atomic; no two processes can execute wait() or signal() operation simultaneously because they are implemented in kernel and processes in kernel mode can not be preempted.
If several processes attempt a P(S) simultaneously, only one process will be allowed to proceed(non-preemptive kernel that is free of race condition).
for the above implementation to work preemption is necessary (preemptive kernel)
read about the atomicity of semaphore operations
http://personal.kent.edu/~rmuhamma/OpSystems/Myos/semaphore.htm
https://en.wikibooks.org/wiki/Operating_System_Design/Processes/Semaphores
I think it's an inaccuracy in your source. Atomic for the wait() operation means each iteration of it is atomic, meaning S-- is performed without interruption, but the whole operation is interruptible after each completion of S-- inside the while loop.
I don't think, keeping an infinite while loop inside the wait() operation is wise. I would go for Stallings' example;
void semWait(semaphore s){
s.count--;
if(s.count<0)
*place this process in s.queue and block this process
}
I think what the book means for the atomic operation is testing S<=0 to be true as well as S--. Just like testAndset() it mention before.
if both separate operations S<=0 and S-- are atomic but can be interrupt by other process, this method won't work.
imagine two process p0 and p1, if p0 want to enter the critical section and tested S<=0 to be true. and it was interrupted by p1 and tested S<=0 also be true. then both of the process will enter the critical section. And that's wrong.
the actual not atomic operation is inside the while loop, even if the while loop is empty, other process can still interrupt current one when S<=0 tested to be false, which enable other process can continue their work in critical section and release the lock.
however, I think the code from the book can not actually use in OS since I don't know how to make operations S<=0 to be true and S-- together atomic. more possible way to do that is put the S-- inside the while loop like SomeWittyUsername said.
When a task attempts to acquire a semaphore that is unavailable, the semaphore places the task onto a wait queue and puts the task to sleep.The processor is then free to execute other code.When the semaphore becomes available, one of the tasks on the wait queue is awakened so that it can then acquire the semaphore.
while S<=0
; //no operation This doesn't mean that the processor running this code. The process/task is blocked until it gets the semaphore.
i think ,
when process P1 is strucked in while loop it will be in the wait state.processor will switch over among the process p0 & p1 (context switching) so the priority goes to p0 and it call signal() and then s will be incremented by 1 and p0 exit from the section so process P1 can enter into critical section and can avoid the mutual exclusion
I am using a microcontroller with a C51 core. I have a fairly timeconsuming and large subroutine that needs to be called every 500ms. An RTOS is not being used.
The way I am doing it right now is that I have an existing Timer interrupt of 10 ms. I set a flag after every 50 interrupts that is checked for being true in the main program loop. If the Flag is true the subroutine is called. The issue is that by the time the program loop comes round to servicing the flag, it is already more than 500ms,sometimes even >515 ms in case of certain code paths. The time taken is not accurately predictable.
Obviously, the subroutine cannot be called from inside the timer interrupt due to that large time it takes to execute.The subroutine takes 50ms to 89ms depending upon various conditions.
Is there a way to ensure that the subroutine is called in exactly 500ms each time?
I think you have some conflicting/not-thought-through requirements here. You say that you can't call this code from the timer ISR because it takes too long to run (implying that it is a lower-priority than something else which would be delayed), but then you are being hit by the fact that something else which should have been lower-priority is delaying it when you run it from the foreground path ('program loop').
If this work must happen at exactly 500ms, then run it from the timer routine, and deal with the fall-out from that. This is effectively what a pre-emptive RTOS would be doing anyway.
If you want it to run from the 'program loop', then you will have to make sure than nothing else which runs from that loop ever takes more than the maximum delay you can tolerate - often that means breaking your other long-running work into state-machines which can do a little bit of work per pass through the loop.
I don't think there's a way to guarantee it but this solution may provide an acceptable alternative.
Might I suggest not setting a flag but instead modifying a value?
Here's how it could work.
1/ Start a value at zero.
2/ Every 10ms interrupt, increase this value by 10 in the ISR (interrupt service routine).
3/ In the main loop, if the value is >= 500, subtract 500 from the value and do your 500ms activities.
You will have to be careful to watch for race conditions between the timer and main program in modifying the value.
This has the advantage that the function runs as close as possible to the 500ms boundaries regardless of latency or duration.
If, for some reason, your function starts 20ms late in one iteration, the value will already be 520 so your function will then set it to 20, meaning it will only wait 480ms before the next iteration.
That seems to me to be the best way to achieve what you want.
I haven't touched the 8051 for many years (assuming that's what C51 is targeting which seems a safe bet given your description) but it may have an instruction which will subtract 50 without an interrupt being possible. However, I seem to remember the architecture was pretty simple so you may have to disable or delay interrupts while it does the load/modify/store operation.
volatile int xtime = 0;
void isr_10ms(void) {
xtime += 10;
}
void loop(void) {
while (1) {
/* Do all your regular main stuff here. */
if (xtime >= 500) {
xtime -= 500;
/* Do your 500ms activity here */
}
}
}
You can also use two flags - a "pre-action" flag, and a "trigger" flag (using Mike F's as a starting point):
#define PREACTION_HOLD_TICKS (2)
#define TOTAL_WAIT_TICKS (10)
volatile unsigned char pre_action_flag;
volatile unsigned char trigger_flag;
static isr_ticks;
interrupt void timer0_isr (void) {
isr_ticks--;
if (!isr_ticks) {
isr_ticks=TOTAL_WAIT_TICKS;
trigger_flag=1;
} else {
if (isr_ticks==PREACTION_HOLD_TICKS)
preaction_flag=1;
}
}
// ...
int main(...) {
isr_ticks = TOTAL_WAIT_TICKS;
preaction_flag = 0;
tigger_flag = 0;
// ...
while (1) {
if (preaction_flag) {
preaction_flag=0;
while(!trigger_flag)
;
trigger_flag=0;
service_routine();
} else {
main_processing_routines();
}
}
}
A good option is to use an RTOS or write your own simple RTOS.
An RTOS to meet your needs will only need to do the following:
schedule periodic tasks
schedule round robin tasks
preform context switching
Your requirements are the following:
execute a periodic task every 500ms
in the extra time between execute round robin tasks ( doing non-time critical operations )
An RTOS like this will guarantee a 99.9% chance that your code will execute on time. I can't say 100% because whatever operations your do in your ISR's may interfere with the RTOS. This is a problem with 8-bit micro-controllers that can only execute one instruction at a time.
Writing an RTOS is tricky, but do-able. Here is an example of small ( 900 lines ) RTOS targeted at ATMEL's 8-bit AVR platform.
The following is the Report and Code created for the class CSC 460: Real Time Operating Systems ( at the University of Victoria ).
Would this do what you need?
#define FUDGE_MARGIN 2 //In 10ms increments
volatile unsigned int ticks = 0;
void timer_10ms_interrupt( void ) { ticks++; }
void mainloop( void )
{
unsigned int next_time = ticks+50;
while( 1 )
{
do_mainloopy_stuff();
if( ticks >= next_time-FUDGE_MARGIN )
{
while( ticks < next_time );
do_500ms_thingy();
next_time += 50;
}
}
}
NB: If you got behind with servicing your every-500ms task then this would queue them up, which may not be what you want.
One straightforward solution is to have a timer interrupt that fires off at 500ms...
If you have some flexibility in your hardware design, you can cascade the output of one timer to a second stage counter to get you a long time base. I forget, but I vaguely recall being able to cascade timers on the x51.
Ah, one more alternative for consideration -- the x51 architecture allow two levels of interrupt priorities. If you have some hardware flexibility, you can cause one of the external interrupt pins to be raised by the timer ISR at 500ms intervals, and then let the lower-level interrupt processing of your every-500ms code to occur.
Depending on your particular x51, you might be able to also generate a lower priority interrupt completely internal to your device.
See part 11.2 in this document I found on the web: http://www.esacademy.com/automation/docs/c51primer/c11.htm
Why do you have a time-critical routine that takes so long to run?
I agree with some of the others that there may be an architectural issue here.
If the purpose of having precise 500ms (or whatever) intervals is to have signal changes occuring at specific time intervals, you may be better off with a fast ISR that ouputs the new signals based on a previous calculation, and then set a flag that would cause the new calculation to run outside of the ISR.
Can you better describe what this long-running routine is doing, and what the need for the specific interval is for?
Addition based on the comments:
If you can insure that the time in the service routine is of a predictable duration, you might get away with missing the timer interrupt postings...
To take your example, if your timer interrupt is set for 10 ms periods, and you know your service routine will take 89ms, just go ahead and count up 41 timer interrupts, then do your 89 ms activity and miss eight timer interrupts (42nd to 49th).
Then, when your ISR exits (and clears the pending interrupt), the "first" interrupt of the next round of 500ms will occur about a ms later.
Given that you're "resource maxed" suggests that you have your other timer and interrupt sources also in use -- which means that relying on the main loop to be timed accurately isn't going to work, because those other interrupt sources could fire at the wrong moment.
If I'm interpretting your question correctly, you have:
a main loop
some high priority operation that needs to be run every 500ms, for a duration of up to 89ms
a 10ms timer that also performs a small number of operations.
There are three options as I see it.
The first is to use a second timer of a lower priority for your 500ms operations. You can still process your 10ms interrupt, and once complete continue servicing your 500ms timer interrupt.
Second option - doe you actually need to service your 10ms interrupt every 10ms? Is it doing anything other than time keeping? If not, and if your hardware will allow you to determine the number of 10ms ticks that have passed while processing your 500ms op's (ie. by not using the interrupts themselves), then can you start your 500ms op's within the 10ms interrupt and process the 10ms ticks that you missed when you're done.
Third option: To follow on from Justin Tanner's answer, it sounds like you could produce your own preemptive multitasking kernel to fill your requirements without too much trouble.
It sounds like all you need is two tasks - one for the main super loop and one for your 500ms task.
The code to swap between two contexts (ie. two copies of all of your registers, using different stack pointers) is very simple, and usually consists of a series of register pushes (to save the current context), a series of register pops (to restore your new context) and a return from interrupt instruction. Once your 500ms op's are complete, you restore the original context.
(I guess that strictly this is a hybrid of preemptive and cooperative multitasking, but that's not important right now)
edit:
There is a simple fourth option. Liberally pepper your main super loop with checks for whether the 500ms has elapsed, both before and after any lengthy operations.
Not exactly 500ms, but you may be able to reduce the latency to a tolerable level.