Need clarification about mutexes and semaphores

My last DMA-intensive multithreaded wonder had to withhold replying to the
clients until some undefined time later (when hardware actually provides the
data, which happened asynchronously and often out of order due to the fact
that hardware had hundreds of ‘ports’, its own CPU and memory). So explicit
MsgReply() when data actually was available made good sense.

They have their use. But not if I can reasonably help it. Amen.

“David Bacon” <dbacon@qnx.com> wrote in message
news:1122987974778.dB@inn.qnx.com

For anyone still following this rather dull and rambling
thread, I just want to correct something I wrote earlier:

Happy I may be to interface with Msg* routines at the resmgr
level, but I don’t actually seem to do it! I looked through
my latest multi-threaded, DMA-intensive wonder, and it turns
out I only made two references to Msg* routines (MsgInfo()
and MsgError()), and even the code sequence that contains
those calls is preceded by a warning expressing this
programmer’s surprise that it should be executed at all
(I think iofunc_unblock_default() is already supposed to
have taken care of what that code does).

The reason is that the resmgr_, iofunc_, dispatch_, and
thread_pool_
functions in QNX’s libc, combined with the
fact that the I/O “callbacks” only need to return data to
their callers in order to effect appropriate MsgReply()s,
comprise a higher and more convenient level than the raw
Msg* routines do. So I use 'em.

dB


David Bacon wrote ~ 1 Aug 2005 16:44:57 GMT:
For the sake of their own convenience and risk mitigation,
customers should be encouraged to use POSIX APIs rather than
QNX native message passing where possible. Look at it from
a risk-conscious customer’s point of view (and here we’re
usually talking about the manager, not his brilliant
programmer, who never sees risks):

Suppose you were trying to choose between Linux and QNX, and
were leaning in favour of QNX because of its architectural
advantages, but for some reason thought you needed to use the
native message-passing API in QNX even at the applications
level to get any kind of decent performance, convenience, or
whatever. You would run immediately to Linux rather than
paint yourself into a corner like that. But if you know you
can write portable POSIX code and get good performance out of
it on QNX, your investment is protected in case other factors
compel a switch to, say, BSD, Linux, or Solaris.

And I really am talking only about the applications level.
I am very happy to interface with the Msg* routines at the
resource manager level, and if Bill Caroselli wants to write
a library that gives his clients (applications programmers)
a portable interface because he supports that library on a
variety of systems, that’s great. But his library will be
a piece of infrastructure: it is systems software, not
applications software.

Applications programmers will always do best to use the most
portable, high-level interface that is practicable for their
needs.

dB


Rennie Allen wrote ~ Mon, 01 Aug 2005 16:13:07 -0700:
Igor Kovalenko wrote:

Ok, I think I see what you’re saying now, but again you use an
irrelevant
example to make your point. We were discussing writing applications,
not
system libraries.

The issue was that David Bacon said that he agreed that it is
inappropriate that application developers use MsgSend directly (this is
a blanket statement). I then pointed out an example where using
MsgSend
directly (as an application developer) is quite likely appropriate.
How
more relevant could it possibly be (actual customer, who is an actual
application developer, who - for some reason - required the ability to
replace the timer_* set of functions) ?

Rennie

Right, I went the route of just blocking the client right
in my io_read() callback for that (making sure to take off
the attr lock the correct number of times before the blocking
call and put it back on the correct number of times afterwards,
of course). I still haven’t found any compelling reason to do
it this way rather than the way you do it, however.

dB


“Igor Kovalenko” wrote ~ Tue, 2 Aug 2005 11:48:20 -0500:

My last DMA-intensive multithreaded wonder had to withhold replying to the
clients until some undefined time later (when hardware actually provides the
data, which happened asynchronously and often out of order due to the fact
that hardware had hundreds of ‘ports’, its own CPU and memory). So explicit
MsgReply() when data actually was available made good sense.

They have their use. But not if I can reasonably help it. Amen.

“David Bacon” <> dbacon@qnx.com> > wrote in message
news:> 1122987974778.dB@inn.qnx.com> …
For anyone still following this rather dull and rambling
thread, I just want to correct something I wrote earlier:

Happy I may be to interface with Msg* routines at the resmgr
level, but I don’t actually seem to do it! I looked through
my latest multi-threaded, DMA-intensive wonder, and it turns
out I only made two references to Msg* routines (MsgInfo()
and MsgError()), and even the code sequence that contains
those calls is preceded by a warning expressing this
programmer’s surprise that it should be executed at all
(I think iofunc_unblock_default() is already supposed to
have taken care of what that code does).

The reason is that the resmgr_, iofunc_, dispatch_, and
thread_pool_
functions in QNX’s libc, combined with the
fact that the I/O “callbacks” only need to return data to
their callers in order to effect appropriate MsgReply()s,
comprise a higher and more convenient level than the raw
Msg* routines do. So I use 'em.

dB


David Bacon wrote ~ 1 Aug 2005 16:44:57 GMT:
For the sake of their own convenience and risk mitigation,
customers should be encouraged to use POSIX APIs rather than
QNX native message passing where possible. Look at it from
a risk-conscious customer’s point of view (and here we’re
usually talking about the manager, not his brilliant
programmer, who never sees risks):

Suppose you were trying to choose between Linux and QNX, and
were leaning in favour of QNX because of its architectural
advantages, but for some reason thought you needed to use the
native message-passing API in QNX even at the applications
level to get any kind of decent performance, convenience, or
whatever. You would run immediately to Linux rather than
paint yourself into a corner like that. But if you know you
can write portable POSIX code and get good performance out of
it on QNX, your investment is protected in case other factors
compel a switch to, say, BSD, Linux, or Solaris.

And I really am talking only about the applications level.
I am very happy to interface with the Msg* routines at the
resource manager level, and if Bill Caroselli wants to write
a library that gives his clients (applications programmers)
a portable interface because he supports that library on a
variety of systems, that’s great. But his library will be
a piece of infrastructure: it is systems software, not
applications software.

Applications programmers will always do best to use the most
portable, high-level interface that is practicable for their
needs.

dB


Rennie Allen wrote ~ Mon, 01 Aug 2005 16:13:07 -0700:
Igor Kovalenko wrote:

Ok, I think I see what you’re saying now, but again you use an
irrelevant
example to make your point. We were discussing writing applications,
not
system libraries.

The issue was that David Bacon said that he agreed that it is
inappropriate that application developers use MsgSend directly (this is
a blanket statement). I then pointed out an example where using
MsgSend
directly (as an application developer) is quite likely appropriate.
How
more relevant could it possibly be (actual customer, who is an actual
application developer, who - for some reason - required the ability to
replace the timer_* set of functions) ?

Rennie


\

“Rennie Allen” <rnogspamallen@comcast.net> wrote in message
news:dco6d2$t8d$1@inn.qnx.com

Your circular logic goes like this:

  1. Application programmers should avoid using the Msg* API at all cost.

  2. Application programmers are application programmers because they use an
    API (i.e. they are a “customer” of another programmer).

  3. System programmers write the API (other programmers are their
    “customers”) and therefore it is OK for them to use the Msg* functions.

  4. Given the definition in (2) the System programmer is (after using the
    Msg* functions in (3)) now an application programmer (since he is a
    “customer” of another programmer). Since he is now an application
    programmer goto (1).

The (4) is genuine demagogical bullshit.

The fact that you use some API does not mean you’re writing an application -
you might as well be writing a higher-level API on top of lower level one,
or you might be writing a driver. Which is the case when ‘System programmer’
uses Msg*. I said “if your product is an API then you’re not writing an
application”. I never said “if you’re using an API then you’re writing an
application” because that would make anything an ‘application’, including
large parts of the OS itself since they are definitely written using some
API. I have already said that such a definition is too wide to be useful, so
at this point you should already know that there’s no ‘circularity’ in my
arguments other than one you’re trying to artificially impose.

My logic (which does not suffer from this circularity) goes like this:

Whether you are acting as an application programmer or system programmer
depends on your final product. If the final product is an API you are
acting as a system programmer.

Your logic suffers from what is best described by an old russian joke:

Two friends grow up together, then one of them leaves for a university and
comes back several years later. His friend asks “so what did you study?” -
The Logic, replies he. - And what is that? - Well… I will give you an
example: - do you have an aquarium? - yes! - so you like fish then? - of
course! - and then you probably like fishing? - indeed - and fishing is no
fun without vodka? - yes! - so when you get drunk do you want a woman? -
yes! - so therefore you’re a heterosexual. - right!!! that is very clever!!!
Enlightened, the friend goes off and meets another local friend and promptly
asks him: - have you heard of The Logic? - no, what is that? - well, do you
have an aquarium? - no… - ah, then you must be gay!

If the final product is not an API you are acting as an application
programmer.

Now who exactly is the proverbial, illogical “wife” in this scenario ?

It does not matter what you ‘final product’ is. On the way to producing it
you might play several roles - when writing drivers, APIs, applications,
etc. If you’re at some point a customer of your own API (which not a good
idea too, but happens out of necessity), you still play those distinct roles
and rules are different when you play each one. At least if you care about
quality of your work.

Direct messaging is not some plague on the API landscape to be handled
only by coders equipped with the s/w equivalent of biohazard suits. It is
a clean simple (non-portable) form of IPC. Sometimes writing non-portable
code is completely acceptable, even desirable (working non-portable code
trumps non-working portable code any day).

I was not giving you any advice in the first place. You’re welcome to use
Msg* or whatever other raw kernel calls you like in your aplications. Others
will make their own judgement.

I am finished with this discussion (i.e. I am pulling an Igor > :wink:> .

Nice try. Maybe you can pull that foot out of your mouth as well.

– igor

Igor Kovalenko wrote:


And if you’re writing a replacement for timer_* functions, then what is your
product may I ask? Would not that by chance be an API?

Re-read definition of product. Re-read your own statements on how to
differentiate application code from system code. Does that programmers
customer use the timer* functions ? Of course not, therefore the
product is not the timer* functions, but whatever application the
programmer is creating that necessitated that he replace these API
functions.

See above about my wife. If she did or said something silly, it is
inevitably ‘because I caused that’.

Your circular logic goes like this:

  1. Application programmers should avoid using the Msg* API at all cost.

  2. Application programmers are application programmers because they use
    an API (i.e. they are a “customer” of another programmer).

  3. System programmers write the API (other programmers are their
    “customers”) and therefore it is OK for them to use the Msg* functions.

  4. Given the definition in (2) the System programmer is (after using the
    Msg* functions in (3)) now an application programmer (since he is a
    “customer” of another programmer). Since he is now an application
    programmer goto (1).


    My logic (which does not suffer from this circularity) goes like this:

Whether you are acting as an application programmer or system programmer
depends on your final product. If the final product is an API you are
acting as a system programmer. If the final product is not an API you
are acting as an application programmer.

Now who exactly is the proverbial, illogical “wife” in this scenario ?

I am sure that you know what an application programmer is, and that your
attempts to call into question what constitutes application code is
simply an attempt to deflect attention from your untenable position that
the Msg* functions should be avoided at all cost (i.e. “cold day in hell
before I did it again”…“Bad Idea ™”).

Direct messaging is not some plague on the API landscape to be handled
only by coders equipped with the s/w equivalent of biohazard suits. It
is a clean simple (non-portable) form of IPC. Sometimes writing
non-portable code is completely acceptable, even desirable (working
non-portable code trumps non-working portable code any day).

I am finished with this discussion (i.e. I am pulling an Igor :wink:.

Rennie

I will look into this.

Actually the code is burried in a library of mine that was ported from QNX4.
So my “user-leverl” code never sees it.


“Igor Kovalenko” <kovalenko@comcast.net> wrote in message
news:dbudhp$24t$1@inn.qnx.com

What is wrong with SyncMutexLock()? Or TimerCreate()? The same as
MsgSend()… they are QNX-specific kernel calls. Lowest level possible. If
you don’t use the former two directly (I presume you use their POSIX
covers)
then why do you feel that the latter must be an exception?

If as you said you already have resmgr, then why not use ioctl() to pass
your complicated structure? It enforces a lot more discipline and leads to
much more robust and portable code. And yes I know you don’t care about
portability for religious reasons. It is still a Bad Idea to mix up calls
from different abstraction layers in the user-level code (at least when
you
can help it).

“Bill Caroselli” <> qtps@earthlink.net> > wrote in message
news:dbu77f$r4f$> 1@inn.qnx.com> …
I’d like to take exception to your opinion that raw message passing is a
bad
idea. I use the resource manager method to establist the initial
connection. After that I use raw message passing. This allows me to
pass
a
complicted structure with a command field and other parameters. The
‘resource manager’ can then reply with a similar complex structure as
and
when appropriate. I also have a whole library of code to convert a
function
call to a raw send/receive. It is very efficient.

What is wrong with that?


“Igor Kovalenko” <> kovalenko@comcast.net> > wrote in message
news:dbt2pu$41n$> 1@inn.qnx.com> …

After using QNX for 11 years and really learning how to use message
passing, I’d say that if I was designing something I’d avoid using raw
message passing almost at all costs. I’d use it [implicitly] for a
resource
manager of course (and I have written my fair share of those). But
direct
raw message passing between a client (user app) and some ‘server’ -
it’d
be
cold day in hell before I did it again. It is just Bad Idea ™.

\

BTW, my appliactions don’t call MsgSend() directly ever either. I think I
already said I have my own library cover functions that do the MsgSend().
For instance a call to DoThisThing() will initialize the command structure
and do the the MsgSend(). All the application programmers know is that they
called DoThisThing().


“Rennie Allen” <rnogspamallen@comcast.net> wrote in message
news:dclgcr$ba$2@inn.qnx.com

Igor Kovalenko wrote:

Ok, I think I see what you’re saying now, but again you use an
irrelevant
example to make your point. We were discussing writing applications, not
system libraries.

The issue was that David Bacon said that he agreed that it is
inappropriate that application developers use MsgSend directly (this is
a blanket statement). I then pointed out an example where using MsgSend
directly (as an application developer) is quite likely appropriate. How
more relevant could it possibly be (actual customer, who is an actual
application developer, who - for some reason - required the ability to
replace the timer_* set of functions) ?

Rennie

At least we’re all friends here, I hope.


“Mario Charest” postmaster@127.0.0.1 wrote in message
news:dcnq73$kmi$1@inn.qnx.com

I`m getting a headache.

  • Mario

I don’t get your point. Writing well organized cover functions for low
level code is the right thing to do.


“John Nagle” <nagle@downside.com> wrote in message
news:dchhjv$3jm$1@inn.qnx.com

And that’s the real problem. Lack of proper application support
for MsgSend. We had to write a set of C++ classes to encapsulate it
and handle the establishment of connections between different parts of
our system. The High Availability Toolkit has some similar
functionality, I’ve heard.

That is fine, as long as DoThisThing() makes more sense than ioctl() or
write(). By that I mean that it should

  1. do more work than write() or ioctl() could
    AND
  2. could not be reasonably (efficiently and elegantly) expressed in terms of
    write() or ioctl()
    AND
    (3) represent a logically distinct operation (as opposed to an arbitrary
    fragment of larger work).

I have done that myself in the spin utility, when I wanted to obtain
swapping stats from proc. There’s just no reasonable way to do that other
than sending a special message to procnto.

However I am against having a lot of DoThisThing()s when those conditions
are not met. While it often seems like a good idea for the original author
to hide most of the logic in the DoThisThing()s, it tends to produce
headache for people who have to maintain your code later. You essentially
end up with some sort of ‘custom API’. The problem with it is that it will
require extensive documentation for the code to be readable/understandable
and exhaustive testing for it to be reliable. It is a lot of effort and IMHO
only makes sense if this API is used by yourself often enough or used by
people other than you. More often than not, documentation is missing and
testing is limited, especially when you’re using your own API.

OTOH, writing your code using well known APIs produces code that is easier
to read and understand, since most people will be familiar with the
functions and their effects.

– igor

“Bill Caroselli” <qtps@earthlink.net> wrote in message
news:dcof2k$616$1@inn.qnx.com

BTW, my appliactions don’t call MsgSend() directly ever either. I think I
already said I have my own library cover functions that do the MsgSend().
For instance a call to DoThisThing() will initialize the command structure
and do the the MsgSend(). All the application programmers know is that
they
called DoThisThing().


“Rennie Allen” <> rnogspamallen@comcast.net> > wrote in message
news:dclgcr$ba$> 2@inn.qnx.com> …
Igor Kovalenko wrote:

Ok, I think I see what you’re saying now, but again you use an
irrelevant
example to make your point. We were discussing writing applications,
not
system libraries.

The issue was that David Bacon said that he agreed that it is
inappropriate that application developers use MsgSend directly (this is
a blanket statement). I then pointed out an example where using MsgSend
directly (as an application developer) is quite likely appropriate. How
more relevant could it possibly be (actual customer, who is an actual
application developer, who - for some reason - required the ability to
replace the timer_* set of functions) ?

Rennie

Not necessarily. See my reply to your other posting for some arguments
against it. I have ran across an awful lot of code that abuses the wrappers,
such as ‘solaris_send_data_over_socket()’. People even claimed they did it
for portability reasons, which is silly given the function name. Basically,
all their code was written using wrappers for already portable functions
that do little more than confuse a reader unfamiliar with the code.

“Bill Caroselli” <qtps@earthlink.net> wrote in message
news:dcogmd$7de$1@inn.qnx.com

I don’t get your point. Writing well organized cover functions for low
level code is the right thing to do.


“John Nagle” <> nagle@downside.com> > wrote in message
news:dchhjv$3jm$> 1@inn.qnx.com> …

And that’s the real problem. Lack of proper application support
for MsgSend. We had to write a set of C++ classes to encapsulate it
and handle the establishment of connections between different parts of
our system. The High Availability Toolkit has some similar
functionality, I’ve heard.

Hi Alain…

…and thank-you for your question. I also benefited from the discussion
that fallowed. Indeed there are many good and experienced programmers
that explained quite a few things very well.

For example, Igor and David did a very good job (I think) with regard to
the distinction between mutex and semaphores (as they relate to shared
memory and to your original question). I went back to some books,
reviewed a few topics, and updated some code as a result. This thread
has been a very good training both from the programatical and
philosophical point of view. :slight_smile:

Regards…

Miguel.


Alain Achkar wrote:

Well, thanks for everyone for their input!

I surely got a lot of explanations to help me with my design decision,
which is a great thing on this newsgroup!