Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

semtake function in ISR

754 views
Skip to first unread message

san...@gmail.com

unread,
Jan 30, 2008, 7:12:10 AM1/30/08
to
Hi Forum,

I have a doubt regarding the usage of SemTake in interrupt service
routine.
According to Vxworks document its given that we should not call
SemTake in Interrupt Service routines.

i have a simple code as below, can you please guide me that whether my
usage of semTake is proper or not.

i have a interrupt service routine, which called during any interrupt
from the controller,


void serviceInt()
{
disable_all_interrupt();
netJobadd(process_Int());
}

Above ISR inturn calls the process_Int() routine, which is as below.

void process_Int()
{
semTake(semname, WAIT_FOREVER);
:
:
:
data_accum();
:
enable_all_interrupt();
:
semGive(semname);
}

Here before calling the SemTake() in process_Int(), i am disabling the
interrupts.

And processInt() is interrupt service function but it is called in
task level using netjobadd()

Can you please tell me whether the above procedure is correct one?

Thanks In Advance.

gvarndell

unread,
Jan 30, 2008, 7:19:31 AM1/30/08
to

Technically, I think what you're doing is ok, but it's not how I would
go about it.
netJobAdd should be used by network drivers.
It's purpose is to get work done -- at tasking level in the context of
tNetTask -- it is not an extension of interrupt processing.
Once you start doing application work in net jobs, you run the risk
that your networking devices will become impaired.

HTH
GV


san...@gmail.com

unread,
Jan 30, 2008, 7:31:55 AM1/30/08
to
Thanks for the reply.

You mean to say that, since the above mentioned process_Int() has
SemTake, which runs under task level,
will slowdown the network process and may cause networkcrash or other
network problems.

gvarndell

unread,
Jan 30, 2008, 7:54:22 AM1/30/08
to

Yes.
Also, you disabling all interrupts in ISR context and enabling them in
task context.
I'm not sure exactly what the functions enable_all_interrupt() and
disable_all_interrupt() do, but they are not needed.
In fact, if you were successful in disabling all interrupts in an ISR
context, and that condition persisted when the kernel returned to
tasking, your system would be dead.

HTH
GV

peter....@gmail.com

unread,
Jan 30, 2008, 9:48:02 AM1/30/08
to
I don't usually yell, but what you are doing screams to me as BAD
CODING PRACTICE!! DANGER WILL ROBINSON, DANGER!!

Now that I have your attention, here is my reasoning. Feel free to
yell and scream at me if anyone believes I am wrong.

I was going to go on about why one should not call semTake() in an
ISR, but upon closer inspection, it is being called from task-level.

I don't think this will work as you expect, and I expect that if you
keep it, you will encounter some strange bizarre effects that you are
not expecting. Unexpected strange and bizarre events are seldom a
good thing when it comes to software.

I shall attempt to illustrate.

#1.
Each task and ISR context keeps track of the various processor flags,
including whether interrupts are enabled or disabled. On the x86
processors, that information is packaged in the EFLAGS register. Now,
lets imagine the following scenario.
- Two tasks are ready to run: taskA and taskB. Neither have locked
interrupts.
- TaskA is scheduled to run. It locks interrupts. Then it calls
semTake(semId, WAIT_FOREVER).
- TaskA gets the semaphore and continues chugging along, eventually
unlocking interrupts.
This looks good, right? Wrong! But what could be wrong? The answer
to that lies in the time between when it requested a lock on the
semaphore and the time at which it got it. TaskA could have blocked.
In this example, if it blocked taskB would run and it would have
interrupts enabled! Remember, taskB has its own EFLAGS register which
is loaded when the task context switch occurs. So when taskB
executes, it will enable interrupts for its duration. During that
period, interrupts may go off and be serviced.
Thus, don't expect that if you lock interrupts and call a blockable
routine that interrupts will stay locked until you get your resource.

#2. In this post, you do not mention what version of VxWorks you are
using. At one time for the 5.x versions (I assume it still exists for
6.x) there was a note that said if you lock interrupts don't make a
kernel call as upon returning from the kernel call, the interrupts
are not guaranteed to be locked. This is because many of the kernel
routines would lock interrupts at some point themselves without saving
the previous state--they effectively assumed that they were unlocked
prior to being called. This particular issue was generally limitted
to architecture specific implementations. Some of them had been
fixed, but I can not say if all of them have.

Those are the two big reasons why you should generally avoid locking
interrupts and then blocking.

If you know why you can't call an semaphore from within an ISR, ignore
the rest of this post. If not, read on.

If you are a newbie to VxWorks, here are the reasons why semTake()
should not be called from VxWorks.
- Taking a semaphore is a blockable operation. The rule of thumb
is, when in an interrupt do not block. This is why the manuals have a
list of acceptable VxWorks routines that can be called from an ISR.

But wait, what if the NO_WAIT (0) option is used as the timeout. Then
it can't block. Why can't I use it then?
- This is a longer answer.
- In versions of VxWorks prior to 6.6 there are three types of
semaphores: mutex, binary and counting. VxWorks 6.6 has introduced a
fourth type--reader/writer semaphores. I have not worked with their
6.6 implementation of reader/writer semaphores so I will not comment
on it here.
If you go into target/h/private/semLibP.h and pull up the structure
definition of SEMAPHORE, you will see a union. The macros semCount
and semOwner access the members of this union.
Mutex semaphores track the taskID of the task that successfully
took the semaphore (its owner). This is used for priority inheritance
as well as for enforcing the mutex property that only the owner can
give up the mutex semaphore. ISRs are not allowed to take a mutex
semaphore as it does not have a taskID. Therefore, even if NO_WAIT
were used as the timeout, an ISR can not take a mutex.

Binary semaphores also use semOwner and taskIdCurrent to track the
owner, but for different reasons. A binary semaphore as you may
recall has two states: taken and available, or if you prefer locked
and unlocked. Technically any two different values can be used.
However the ID of the current task (taskIdCurrent) is used to signify
that it is taken, and zero (0) to signify that it is available. This
gives the benefit of adding some debugging information to the
semaphore. That is, one can inspect the contents of the semaphore
structure and determine what task took the semaphore. This can be
very useful. However, in the context of an ISR, taskIdCurrent is
invalid. It no longer identifies the currently running task, but
rather the task that was interrupted. What if the system is idle--no
tasks are running in the system. I can't remember exactly off hand,
but I think it may be NULL. Therefore, if an ISR took it, it would
not look like it was taken. To summarize for binary semaphores--this
restriction comes about as a result of implementation choices.

Finally this brings us to counting semaphores. There is no
technical reason why one shouldn't be able to take a VxWorks counting
semaphore from within an ISR when using NO_WAIT as the timeout. The
only reason why I can see this not being allowed is consistency. It
can't be done for 2 out of the 3 semaphore types, therefore for
consistency, we're going to make it not allowed for 3 out of 3.

I hope all this helps.

Peter Mitsis

A.Holden

unread,
Jan 30, 2008, 2:29:48 PM1/30/08
to
On Jan 30, 4:48 pm, peter.mit...@gmail.com wrote:
> I don't usually yell, but what you are doing screams to me as BAD
> CODING PRACTICE!! DANGER WILL ROBINSON, DANGER!!
>
> Now that I have your attention, here is my reasoning. Feel free to
> yell and scream at me if anyone believes I am wrong.
>
> I was going to go on about why one should not call semTake() in an
> ISR, but upon closer inspection, it is being called from task-level.
>

A tiny comment about taking semaphores from ISR context:
it simply won't work! as "semTake" will ALWAYS return error from ISR-
context.
(and <errno> will be set to S_intLib_NOT_ISR_CALLABLE).

It is another bad practice to never check the returned value from
semTake (and assume it just "succeeded").
Had your <process_int> function actually been called from ISR context,
semTake would have returned immediately (with error), not blocking,
not "taking" anything, and not providing any kind of protection.

Regards,
Allen

san...@gmail.com

unread,
Jan 31, 2008, 3:10:00 AM1/31/08
to
Thank You All for the kind reply.

In my Application i am using mutual exclusion semaphore.
I ran my application today,

I checked the return value of the SemTake. It didn't returned any
error number.
Return value was 0.

And my application runs properly.

I think, since processInt() function is running in task level,
SemTake is working properly.

I think vxworks may fail occassionally, due to the usage of SemTake in
my application.(i.e in processInt() function)

if i am entirely doing wrong, please clear me.

Thank you...

san...@gmail.com

unread,
Jan 31, 2008, 3:17:02 AM1/31/08
to
this is related to previous discussion.

My Vxworks version is 5.5.1

gvarndell

unread,
Jan 31, 2008, 4:42:46 AM1/31/08
to

Create your own task to do whatever work is currently being done in
netTask.
In your task, wait for a semaphore to be given - binary, counting --
it depends on your siituation.
In the ISR, do nothing more than give the semaphore that will awaken
your task -- don't do a netJobAdd.
Then your task is free to do whatever it wants.
Don't spawn your task at a higher priority than tNetTask.
It's really quite simple.

HTH,
GV

shashi

unread,
Jan 31, 2008, 10:38:43 AM1/31/08
to
On Jan 31, 3:42 am, gvarndell <gvarnd...@hotmail.com> wrote:
> On Jan 31, 3:10 am, sant...@gmail.com wrote:
>
>
>
>
>
> > Thank You All for the kind reply.
>
> > In my Application i am using mutual exclusion semaphore.
> > I ran my application today,
>
> > I checked the return value of the SemTake. It didn't returned any
> > error number.
> > Return value was 0.
>
> > And my application runs properly.
>
> > I think, since processInt() function is running in task level,
> > SemTake is working properly.
>
> > I thinkvxworksmay fail occassionally, due to the usage of SemTake in

> > my application.(i.e in processInt() function)
>
> > if i am entirely doing wrong, please clear me.
>
> Create your own task to do whatever work is currently being done in
> netTask.
> In your task, wait for a semaphore to be given - binary, counting --
> it depends on your siituation.
> In the ISR, do nothing more than give the semaphore that will awaken
> your task -- don't do a netJobAdd.
> Then your task is free to do whatever it wants.
> Don't spawn your task at a higher priority than tNetTask.
> It's really quite simple.
>
> HTH,
> GV- Hide quoted text -
>
> - Show quoted text -


Hi,

I can figure out from code that once u get interrupt u want to
manipulate data. So use of semaphore is for data sync purpose. So
always remember a thumb rule. Use Binary Semaphore and ISR should
never take semaphore .Second mistake u r doing is disabling interrupt
and waiting for semaphore. Suppose if that semaphore is not freed so
u'll keep on waiting for semaphore in int disabled sate. So, u r
losing data.

Second rule u should follow is y'r isr should be dependent only on
interrupt not on any other parallel condition.


Y'r code should be


Hardware Interrupt

ISR
{

H/W status and interrupt stuff
fetch or manipulate data.
Release semaphore

}


ApplicatipnTask
{


While(1)
{
Semtake in waitforever state
{

Process data
}
}


}

Let me know if you have any concerned. This is regardless of vxworks
version.

Regards
Shashi
+732-485-4133

gvarndell

unread,
Jan 31, 2008, 12:10:32 PM1/31/08
to

(Putting your phone number in a posting is a bad idea)
Why, oh why, are so many people jumping on the 'you can't pend on a
semaphore in an ISR' bandwagon?
The OP is NOT doing that -- in spite of the thread title.
He was a little confused, which is not uncommon in this group.

GV


cthomeroaster

unread,
Jan 31, 2008, 9:16:06 PM1/31/08
to
Almost surely, your code example is not what you want to do. As
others have posted, the ISR should GIVE a semaphore to unblock your
work task (processInt), which is waits forever for the semaphore. If
required, you could use msgQSend or a pipe (both NO_WAIT timeouts) to
both unblock your work task and pass some control information.

It should be noted that while the specific system calls are VxWorks
specific, the concepts are not. ISR's should NEVER perform blocking
operations and should do the minimum amount of work required to
service the hardware device and queue information to process later at
non-interrupt level.

On Jan 31, 3:10 am, sant...@gmail.com wrote:

0 new messages