Need clarification about mutexes and semaphores

Igor Kovalenko <kovalenko@comcast.net> wrote:

Indeed. But it is up to you whether or not your resmgr will do stream
buffering at all. You can say that your read() or write() will only handle
this much of data at a time and avoid streaming altogether. And ioctl()
normally does not stream at all, althoug AFAIR it can only pass up to 64k of
data at a time.

I haven’t looked in detail at ioctl(), other than a glance through the
code a while back to see that it parses off a bunch of special ones
it recognises, then dumped anything it didn’t to devctl().

Now, devctl() nominally has a 64K limit, because the devctl that
you issue encodes a “length” parameter into a certain number of
bits, but devctl() also takes a pointer to the message and a
length as independent paramaters, and I don’t think it enforces
the 64K nominal limit on the length/copy action. (Though, it
does enforce the directionanility of the to/from/tofrom macros.)

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Shouldn’t that be 16K, David? Two bits are taken up for those
direction flags.

Incidentally, I quite agree with Igor on the other off-topic topic
that has been discussed in this thread: native message passing is
very nice, but not appropriate for application-level programming.

And finally, back on the original topic, I always found Sebesta’s
terminology regarding synchronization useful: he distinguishes
between “competition synchronization” as typified by mutexes from
“cooperation synchronization” as typified by condvars.

dB


David Gibbs wrote ~ 28 Jul 2005 15:42:34 GMT:

Igor Kovalenko <> kovalenko@comcast.net> > wrote:

Indeed. But it is up to you whether or not your resmgr will do stream
buffering at all. You can say that your read() or write() will only handle
this much of data at a time and avoid streaming altogether. And ioctl()
normally does not stream at all, althoug AFAIR it can only pass up to 64k of
data at a time.

I haven’t looked in detail at ioctl(), other than a glance through the
code a while back to see that it parses off a bunch of special ones
it recognises, then dumped anything it didn’t to devctl().

Now, devctl() nominally has a 64K limit, because the devctl that
you issue encodes a “length” parameter into a certain number of
bits, but devctl() also takes a pointer to the message and a
length as independent paramaters, and I don’t think it enforces
the 64K nominal limit on the length/copy action. (Though, it
does enforce the directionanility of the to/from/tofrom macros.)

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

David Bacon <dbacon@qnx.com> wrote:

Shouldn’t that be 16K, David? Two bits are taken up for those
direction flags.

I didn’t check the math, just trusted Igor’s. It might be
16K.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Doh… I did not do any math, just remembered there was some limit. And now
it is all my fault, eh? :wink:

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:dcb4ob$dri$1@inn.qnx.com

David Bacon <> dbacon@qnx.com> > wrote:
Shouldn’t that be 16K, David? Two bits are taken up for those
direction flags.

I didn’t check the math, just trusted Igor’s. It might be
16K.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

David Gibbs wrote:

David Bacon <> dbacon@qnx.com> > wrote:

Shouldn’t that be 16K, David? Two bits are taken up for those
direction flags.


I didn’t check the math, just trusted Igor’s. It might be
16K.

However … from a design perspective I would never send 16k from one
application address space to an other. This could slow down the system
if the send actions are too frequently.

Shared memory is your frend and helps you to avoid sensless copy actions.

–Armin

And you’d be wrong Armin.
I was under the same belief, until I actually measured what is faster.
Believe it or not, message pass will be faster.

The catch with shared memory that people forget is that you have to
explicitly synchronize it, while with message passing you get the benefit of
implicit syncronization. In a general case, each transaction (passing a
single block of data through a shared memory) will require 2 semaphores on
each side, for total of 4 kernel calls. With message passing you will need
only 3 kernel calls. And 1 kernel call costs more than data copying…

If you wish, write your own benchmark and measure. In my tests message pass
was always faster, no matter how large buffers I tried (up to 128k I think).

Now for those of you who think I argued against message passing… no. I
argued against using raw message passing in the user level apps. And I
argued against senseless using of message passing (layer upon layer of
message passing). Shared memory can be faster if it creates a ‘shortcut’
between the layers (so instead of 6 kernel calls for 2 layers of message
passing you only use 4 kernel calls with shared memory).

– igor

“Armin Steinhoff” <a-steinhoff@web.de> wrote in message
news:dccsmm$mm5$1@inn.qnx.com

David Gibbs wrote:
David Bacon <> dbacon@qnx.com> > wrote:

Shouldn’t that be 16K, David? Two bits are taken up for those
direction flags.


I didn’t check the math, just trusted Igor’s. It might be
16K.

However … from a design perspective I would never send 16k from one
application address space to an other. This could slow down the system if
the send actions are too frequently.

Shared memory is your frend and helps you to avoid sensless copy actions.

–Armin

David Bacon wrote:


Incidentally, I quite agree with Igor on the other off-topic topic
that has been discussed in this thread: native message passing is
very nice, but not appropriate for application-level programming.

I think there is a degree of terminological sloppiness being used in
this thread. MsgSend is only one API for message passing. The initial
“on-topic” aspect of this thread was regarding whether shared mutexes
were really necessary, and whether message passing is a superior
solution to many IPC problems (especially those where synchronization is
required).

Message passing is a superior solution for many IPC problems, and
applications should use it, where it is a superior mechanism (this has
nothing to do with whether MsgSend is used as the interface to message
passing or not).

That said, I happen to disagree that MsgSend is never appropriate for
application level programming (never covers a whole lot of ground, both
temporal and spatial).

There was a thread a while back where someone wanted to replicate Posix
timer_* functionality (whether replicating Posix timer_* functionality
makes sense or not, is a topic for some other thread).

Given the requirement to replace what is already a O/S function (and a
Posix one at that), it appears obvious (to me at least) that MsgSend is
in fact, appropriate, since the calls being replicated are themselves
not implemented through a “resource manager” interface. What possible
portability gains would be realized from re-implementing what is already
a standard Posix API on top of Posix read/write semantics (verses on top
of a simple MsgSend) ?

Rennie

Igor Kovalenko wrote:

“John Nagle” <> nagle@overbot.com> > wrote in message
news:dc6cdf$qke$> 1@inn.qnx.com> …

Bill Caroselli wrote:

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?

I don’t see the enthusiasm for resource managers. I’ve written one, for
FireWire cameras, but that was because it really was something for which
stream-based read and write made sense.



The enthusiasm here is better organisation of the code, portability of
client side and number of conviniences in terms of infrastructure of the
entire system.

I’ve written quite enough of that stuff to know that making your server a
formal resmgr will force you to do things [more or less] right, whereas
doing it raw will allow to cut too many corners and end up with sloppy code.
I don’t doubt that you could write a good code with raw messages, but
working in a large project you have to think in statistical terms and use
methods that give statistically better results.

In fact I consider even the resmgr-level API of QNX too ‘raw’ for casual
use. There’s way to many chances to miss some angles and then a long painful
process of debugging and fixing ensues. When you’re doing it alone, you
might be fine. When it is done in parallel by half a dozen or more people
(doing different components) you’re much better off with a more high-level
[and yes, less flexible] abstraction to hide some complexities and eliminate
most common logic mistakes. Once you design and debug that layer, you get
much better quality of code from its users.

And given how you have to contemplate moving to another platform now,
portability of client side is not a minor advantage either.


If you want an interprocess subroutine call, MsgSend is the right
mechanism. Putting stream buffering on top of messaging, and then
having to delimit the streams in some way, is complicated and
inefficient. Yes, the sockets-based world does it that way,
and pays a heavy price for it. See any CORBA implementation.


Indeed. But it is up to you whether or not your resmgr will do stream
buffering at all. You can say that your read() or write() will only handle
this much of data at a time and avoid streaming altogether. And ioctl()
normally does not stream at all, althoug AFAIR it can only pass up to 64k of
data at a time.

In my experience we found that even very specialized resmgrs that have no
corresponding hardware and operate exclusively through ioctl() with
predefined structures can benefit by using resmgr approach. First, you get
the benefit of consistent and convinient open(). It can be used by shell
scripts that start your system to check for readiness of the subsystems
(instead of stuffing dumb sleeps after myserver &). Also you can use
read/write as debug/test interfaces (like you do cat /proc/ipstats to see
status of tiny TCP stack or you can echo"xxx" > /dev/myserver to automate
testing, etc). After I have written a high level library to make creation of
that sort of resmgrs real easy…

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.

Directory services for message passing have needed improvement for
some time. They’re actually better in QNX 6.3; global name_attach
finally works. Amusingly, even under QNX 6.21, you can use name_open
across the net. name_open(“foo”,0) just opens “/dev/name/local/foo”.
And so, you can do “name_open(”…/…/…/net/nodename/name/local/foo",0)"
and connect across the net. Works fine.

But the whole concept of service location for message passing needs
work.

The underlying mechanisms are so good, yet the higher level support
and tutorials are weak.

This is where it really hurts that there are almost no third-party
books for QNX.

John Nagle
Team Overbot

John Nagle wrote:

Igor Kovalenko wrote:

“John Nagle” <> nagle@overbot.com> > wrote in message
news:dc6cdf$qke$> 1@inn.qnx.com> …

Bill Caroselli wrote:

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?


I don’t see the enthusiasm for resource managers. I’ve written one, for
FireWire cameras, but that was because it really was something for which
stream-based read and write made sense.



The enthusiasm here is better organisation of the code, portability of
client side and number of conviniences in terms of infrastructure of
the entire system.

I’ve written quite enough of that stuff to know that making your
server a formal resmgr will force you to do things [more or less]
right, whereas doing it raw will allow to cut too many corners and end
up with sloppy code. I don’t doubt that you could write a good code
with raw messages, but working in a large project you have to think in
statistical terms and use methods that give statistically better results.

In fact I consider even the resmgr-level API of QNX too ‘raw’ for
casual use. There’s way to many chances to miss some angles and then a
long painful process of debugging and fixing ensues. When you’re doing
it alone, you might be fine. When it is done in parallel by half a
dozen or more people (doing different components) you’re much better
off with a more high-level [and yes, less flexible] abstraction to
hide some complexities and eliminate most common logic mistakes. Once
you design and debug that layer, you get much better quality of code
from its users.

And given how you have to contemplate moving to another platform now,
portability of client side is not a minor advantage either.


If you want an interprocess subroutine call, MsgSend is the right
mechanism. Putting stream buffering on top of messaging, and then
having to delimit the streams in some way, is complicated and
inefficient. Yes, the sockets-based world does it that way,
and pays a heavy price for it. See any CORBA implementation.



Indeed. But it is up to you whether or not your resmgr will do stream
buffering at all. You can say that your read() or write() will only
handle this much of data at a time and avoid streaming altogether. And
ioctl() normally does not stream at all, althoug AFAIR it can only
pass up to 64k of data at a time.

In my experience we found that even very specialized resmgrs that have
no corresponding hardware and operate exclusively through ioctl() with
predefined structures can benefit by using resmgr approach. First, you
get the benefit of consistent and convinient open(). It can be used by
shell scripts that start your system to check for readiness of the
subsystems (instead of stuffing dumb sleeps after myserver &). Also
you can use read/write as debug/test interfaces (like you do cat
/proc/ipstats to see status of tiny TCP stack or you can echo"xxx"
/dev/myserver to automate testing, etc). After I have written a high
level library to make creation of that sort of resmgrs real easy…


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.

Directory services for message passing have needed improvement for
some time. They’re actually better in QNX 6.3; global name_attach
finally works. Amusingly, even under QNX 6.21, you can use name_open
across the net. name_open(“foo”,0) just opens “/dev/name/local/foo”.
And so, you can do “name_open(”…/…/…/net/nodename/name/local/foo",0)"
and connect across the net. Works fine.

But the whole concept of service location for message passing needs
work.

The underlying mechanisms are so good, yet the higher level support
and tutorials are weak.

This is where it really hurts that there are almost no third-party
books for QNX.

… not realy, try this book:

http://www.parse.com/products/books/index.html

The training is also excellent:

http://www.parse.com/products/training/index.html

–Armin

John Nagle
Team Overbot

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

David Bacon wrote:
Incidentally, I quite agree with Igor on the other off-topic topic
that has been discussed in this thread: native message passing is
very nice, but not appropriate for application-level programming.

I think there is a degree of terminological sloppiness being used in this
thread. MsgSend is only one API for message passing. The initial
“on-topic” aspect of this thread was regarding whether shared mutexes were
really necessary, and whether message passing is a superior solution to
many IPC problems (especially those where synchronization is required).

Message passing is a superior solution for many IPC problems, and
applications should use it, where it is a superior mechanism (this has
nothing to do with whether MsgSend is used as the interface to message
passing or not).

I don’t think that switching the subject makes the terminology any less
sloppy. We were talking specifically about using raw message passing at the
application level. Nobody is arguing that message passing should not be
used.

That said, I happen to disagree that MsgSend is never appropriate for
application level programming (never covers a whole lot of ground, both
temporal and spatial).

Even I did not say ‘never’. I said ‘if you can help it’.

There was a thread a while back where someone wanted to replicate Posix
timer_* functionality (whether replicating Posix timer_* functionality
makes sense or not, is a topic for some other thread).

Given the requirement to replace what is already a O/S function (and a
Posix one at that), it appears obvious (to me at least) that MsgSend is in
fact, appropriate, since the calls being replicated are themselves not
implemented through a “resource manager” interface. What possible
portability gains would be realized from re-implementing what is already a
standard Posix API on top of Posix read/write semantics (verses on top of
a simple MsgSend) ?

I just can’t make out what you’re saying here at all ;(

– igor

“Igor Kovalenko” <kovalenko@comcast.net> wrote in message
news:dck9ok$2uc$1@inn.qnx.com

“Rennie Allen” <> rnogspamallen@comcast.net> > wrote in message
[…]
There was a thread a while back where someone wanted to replicate Posix
timer_* functionality (whether replicating Posix timer_* functionality
makes sense or not, is a topic for some other thread).

Given the requirement to replace what is already a O/S function (and a
Posix one at that), it appears obvious (to me at least) that MsgSend is
in fact, appropriate, since the calls being replicated are themselves not
implemented through a “resource manager” interface. What possible
portability gains would be realized from re-implementing what is already
a standard Posix API on top of Posix read/write semantics (verses on top
of a simple MsgSend) ?

I just can’t make out what you’re saying here at all ;(

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. Of course a good chunk of libc in QNX is based on
MsgSend() by neccessity. And in Linux they jump to kernel to do something
similar, etc. The point is, you use libc functions rather than its
underlying mechanism directly. I am assuming that you do not dispute the
portability gain afforded by using POSIX libc functions. The library itself
is not portable, but the applications written using it are (more or less
anyway).

A write() or ioctl() is a suitable POSIX cover for MsgSend() in the same
sense as timer_create() is a suitable cover for TimerCreate(). If you don’t
find the latter an appropriate way to code your applications, I do not see
why the former would qualify. And I mean applications, not some
QNX-specific library or server.

– igor

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: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) ?

It is funny how we run in circles repeating our arguments. Both David and I
have said that replacing timer_* set of functions is NOT application level
programming and therefore is outside of the scope of our discussion.

You are treating the expression ‘application programming’ in such a wide
sense that it makes it useless (and in that sense in could indeed make what
we said ‘blanket statements’). Our interpretation of it is narrow -
‘application programming’ means writing client side code exclusively (as
opposed to writing drivers, servers, libraries or other system
infrastructure). Another way to make the distinction clear is by looking at
who is the customer of the code written by a particular developer. If your
customer is another programmer, then you’re NOT writing an application. It
is system-level programming and our arguments against Msg* do not apply.

– igor

Igor Kovalenko wrote:

[…] makes the terminology any less
sloppy. We were talking specifically about using raw message passing at the
application level. Nobody is arguing that message passing should not be
used.

Using terminology that implies that using Msg* functions equates to
using message passing, while using the resource manager framework
doesn’t, is likely to confuse a new qnx user. I realize that David
Bacon did say “native” message passing, but this does not imply (to me)
that the comments are restricted to the Msg* API. How is sending a
write() to a resource manager not native message passing ?

Re-read the original post, and the following devolution of conversation.
Can you honestly tell me that you believe that this is going to aid
the OP in developing a good solution under QNX ? I thought that John
Nagles’ post was helpful, and most of what followed was (at best)
confusing and unhelpful to a new user; unfortunately my attempts to
rescue it have, thus far, been fruitless.

Rennie

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

Igor Kovalenko wrote:

You are treating the expression ‘application programming’ in such a wide
sense that it makes it useless (and in that sense in could indeed make what
we said ‘blanket statements’).

Sigh. I wouldn’t think we would need to discuss what constitutes
application code in qnx.rtos… but here goes…

First couple of definitions:

API - Application Programming Interface.
Product - A packaged entity produced by a programmer.

Application programming is what is done by programmers who make use of
an API to solve a problem in the domain of their product (which can not
be another API).

System programming is what is done by programmers who assemble a set of
unpublished interfaces to solve a problem in the domain of their product
(which is a published API).

You may notice that the “pivot point” here is the concept referred to as
an API. If your product is an API you are a system programmer, if it
isn’t you are an application programmer. No further definition (or
restriction) of what an application programmer can and can’t do is
necessary. This definition is clean, robust and universally accepted
(at least I thought so, until now :wink:

In the real world, application programmers write resource managers,
drivers, and scheduling algorithms (sometimes they find it necessary to
duplicate the functionality of one of the APIs they purchased).
Application programmers are identified not by the classes of the
software entities they construct, but by the final product they deliver
to their customer (strangely enough you seem to espouse this very
definition below).

Our interpretation of it is narrow -

‘application programming’ means writing client side code exclusively (as
opposed to writing drivers, servers, libraries or other system
infrastructure).

I don’t know if it is narrow, but it is certainly wrong.

Another way to make the distinction clear is by looking at

who is the customer of the code written by a particular developer. If your
customer is another programmer, then you’re NOT writing an application. It
is system-level programming and our arguments against Msg* do not apply.

Since we apparently agree that a system programmer (and the act of
system programming) is identified by whether or not a new API is the
product (not by the class of software module that was written), then you
have argued successfully against your own position, since there is
nothing in the OPs post that indicates they intended to produce a new
API as the final product (thus by the usual definition of an application
programmer, they were in fact, acting as an AP when they wrote what you
implied qualifies them as a SP, and thus your “rules” that disqualify
them from writing code that uses Msg* don’t apply).

We can now move on by agreeing that John Nagle was right in the first
place :slight_smile:

ps: if the second-to-last paragraph above is difficult to follow, it is
because it attempts to unravel the circular logic used in your arguments
(I tried hard to simplify it).

Rennie

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

Igor Kovalenko wrote:

You are treating the expression ‘application programming’ in such a wide
sense that it makes it useless (and in that sense in could indeed make
what we said ‘blanket statements’).

Sigh. I wouldn’t think we would need to discuss what constitutes
application code in qnx.rtos… but here goes…

First couple of definitions:

API - Application Programming Interface.
Product - A packaged entity produced by a programmer.

Application programming is what is done by programmers who make use of an
API to solve a problem in the domain of their product (which can not be
another API).

System programming is what is done by programmers who assemble a set of
unpublished interfaces to solve a problem in the domain of their product
(which is a published API).

Thanks for these revelations.

You may notice that the “pivot point” here is the concept referred to as
an API. If your product is an API you are a system programmer, if it
isn’t you are an application programmer. No further definition (or
restriction) of what an application programmer can and can’t do is
necessary. This definition is clean, robust and universally accepted (at
least I thought so, until now > :wink:

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?

In the real world, application programmers write resource managers,
drivers, and scheduling algorithms (sometimes they find it necessary to
duplicate the functionality of one of the APIs they purchased).

I have been in the real world few times myself. Thanks one more time.

Application programmers are identified not by the classes of the software
entities they construct, but by the final product they deliver to their
customer (strangely enough you seem to espouse this very definition
below).

Our interpretation of it is narrow -
‘application programming’ means writing client side code exclusively (as
opposed to writing drivers, servers, libraries or other system
infrastructure).

I don’t know if it is narrow, but it is certainly wrong.

This reminds me of arguing with my wife. If I am saying something she does
not like, I am wrong. Evidently, by definition - since she does not provide
any arguments either.

Another way to make the distinction clear is by looking at
who is the customer of the code written by a particular developer. If
your customer is another programmer, then you’re NOT writing an
application. It
is system-level programming and our arguments against Msg* do not apply.

Since we apparently agree that a system programmer (and the act of system
programming) is identified by whether or not a new API is the product (not
by the class of software module that was written), then you have argued
successfully against your own position, since there is nothing in the OPs
post that indicates they intended to produce a new API as the final
product (thus by the usual definition of an application programmer, they
were in fact, acting as an AP when they wrote what you implied qualifies
them as a SP, and thus your “rules” that disqualify them from writing code
that uses Msg* don’t apply).

I was refering to your example, not to whatever ‘they’ are doing. You have
tried to use the example with relacing timer_* set as a justification for
using Msg* API in applications. I have countered that if you’re writing a
replacement for libc function, you’re not writing an application and your
example is invalid. Not sure how you missed this up to now, but I hope you
get it now that in the last few postings I was countering your example, not
advising the original poster on when use or not use Msg*. Although do I
realize now that I should not waste any more time doing so.

We can now move on by agreeing that John Nagle was right in the first
place > :slight_smile:

ps: if the second-to-last paragraph above is difficult to follow, it is
because it attempts to unravel the circular logic used in your arguments
(I tried hard to simplify it).

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

– igor

Rennie Allen wrote:

Igor Kovalenko wrote:

You are treating the expression ‘application programming’ in such a
wide sense that it makes it useless (and in that sense in could indeed
make what we said ‘blanket statements’).


Sigh. I wouldn’t think we would need to discuss what constitutes
application code in qnx.rtos… but here goes…

First couple of definitions:

API - Application Programming Interface.
Product - A packaged entity produced by a programmer.

Application programming is what is done by programmers who make use of
an API to solve a problem in the domain of their product (which can not
be another API).

System programming is what is done by programmers who assemble a set of
unpublished interfaces to solve a problem in the domain of their product
(which is a published API).

You may notice that the “pivot point” here is the concept referred to as
an API. If your product is an API you are a system programmer, if it
isn’t you are an application programmer. No further definition (or
restriction) of what an application programmer can and can’t do is
necessary. This definition is clean, robust and universally accepted
(at least I thought so, until now > :wink:

… and your statement below is a contradiction to your statements
above :slight_smile:

In the real world, application programmers write resource managers,
… I would say SYSTEM programmers write resource managers,

drivers a.s.o

–Armin

and scheduling algorithms (sometimes they find it necessary to
duplicate the functionality of one of the APIs they purchased).
Application programmers are identified not by the classes of the
software entities they construct, but by the final product they deliver
to their customer (strangely enough you seem to espouse this very
definition below).

Our interpretation of it is narrow -

‘application programming’ means writing client side code exclusively
(as opposed to writing drivers, servers, libraries or other system
infrastructure).


I don’t know if it is narrow, but it is certainly wrong.

Another way to make the distinction clear is by looking at

who is the customer of the code written by a particular developer. If
your customer is another programmer, then you’re NOT writing an
application. It
is system-level programming and our arguments against Msg* do not apply.


Since we apparently agree that a system programmer (and the act of
system programming) is identified by whether or not a new API is the
product (not by the class of software module that was written), then you
have argued successfully against your own position, since there is
nothing in the OPs post that indicates they intended to produce a new
API as the final product (thus by the usual definition of an application
programmer, they were in fact, acting as an AP when they wrote what you
implied qualifies them as a SP, and thus your “rules” that disqualify
them from writing code that uses Msg* don’t apply).

We can now move on by agreeing that John Nagle was right in the first
place > :slight_smile:

ps: if the second-to-last paragraph above is difficult to follow, it is
because it attempts to unravel the circular logic used in your arguments
(I tried hard to simplify it).

Rennie

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

I`m getting a headache.

  • Mario