MIPS / targetOS strange behavior

In this snippet from a semaphore post routine, sem->count is -1 before execution and 0 after, but the wrong branch is taken about once a week if it feels like it.

++sem->count; lw v0, 20(s3) ; s3 contains a pointer to the semaphore struct, offset 20 is the count within the semaphore addiu v0, v0, 1 ; Increment count sw v0, 20(s3) ; Write count out to semaphore structure

if ((savedSemCount = sem->count)

Reply to
tbroberg
Loading thread data ...

That's no way to implement a semaphor. That's the kind of thing you're supposed to *use* a semaphor around to protect them from outside interference.

"Atomic" operation, ring a bell? 5 instructions is hardly atomic.

In a nutshell: a semaphor can't be implemented in portable C. You need non-portable tricks or assembly code for that.

If you know you need a semaphor, it's somewhat amazing you don't know why the above isn't implementing the semantics of a semaphor. Hint: imagine a taskswitch between any 2 of those 5 instructions. Imagine what that might do, and how that could affect the state of this semaphor.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

Hans, you are absolutely correct. The fragment I picked to show the problem is not a semaphore, it's just a fragment of the semPost() routine that addresses only the specific question I'm asking.

I know this isn't sufficient information to take on the problem as a whole, just the part that is beyond my experience. This is intentional to avoid wasting people's time with stuff I can do myself and to keep the discussion focussed on the tough issue.

Thanks for your reply, - Tim.

Reply to
tbroberg

Tim,

I agree with Hans - this is not how you implement semaphores. Take a look at the Load Linked (LL) and Store Conditional (SC) instructions that are useful for implementing synchronization primitives.

BTW I think you have a bug in your modified code. Note how you load v0 but increment and store v1:

Regards,

-- Georgi

Reply to
Georgi

Try disassembling the binary to check that the delay slot between store/load is actually filled, and that there is no (broken) reordering.

I assume sem->count is declared volatile, and this is why you get an explicit reload for each reference.

Are you using gcc w/gas? Gas automatically fills delay slots, and gcc got a bunch of delay slot changes in 4.0.1. Either way, check the actual output, not just .s files produced by the compiler.

Reply to
Jan Brittenson

You got only half of my point. Not only is this not a semaphor, the effect you see is what you get if a code sequence should have a semaphor around it, but doesn't. It's not just failing to *be* a semaphor, it fails to *have* one.

It's perfectly possible for another thread of control to intervene between the two C statements and change that counter before the if statement looks at it. That this happens only so rarely is a rather clear indicator it's this kind of random coincidence you're looking at. In other words, the problem is not that the if is taking the wrong exit --- the problem is that you think you know which exit it must take.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

I think what Hans wants to lead you to is, you need to protect your semaphore code (e.g. disable interrupts) to avoid task-switching.

--
42Bastian
Do not email to bastian42@yahoo.com, it's a spam-only account :-)
 Click to see the full signature
Reply to
42Bastian Schick

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.