Potential qnx_hint_attach() hazard?

Hi,

I occasionally faced somehow strange stuff happening with
qnx_hint_attach() under 4.25D (Proc32 4.25J). It was I just forgot to
put the “#include <sys/irqinfo.h>” line in my code - neither wcc386
nor wlink said anything, just like everything went OK, but when the
code attempted to execute qnx_hint_attach(), it caused a kernel fault.

I’ve put the sample sources into my QUICS dir
(/u/s/swdstp/irqdemo.tar.gz), just comment the “#include
<sys/irqinfo.h>” line in kbdirq.h, biuld it, run it and watch your
system crash.

Should it be like that? It doesn’t look like a correct behaviour to me
anyway.

Thanks,

  • Nick

Nikolai Gorbunov <n.gorbunov@swd.ru> wrote:

Hi,

I occasionally faced somehow strange stuff happening with
qnx_hint_attach() under 4.25D (Proc32 4.25J). It was I just forgot to
put the “#include <sys/irqinfo.h>” line in my code - neither wcc386
nor wlink said anything, just like everything went OK, but when the
code attempted to execute qnx_hint_attach(), it caused a kernel fault.

Should it be like that? It doesn’t look like a correct behaviour to me
anyway.

Yes. Well, actually, it can’t be helped. If you take a look at
the definition for qnx_hint_attach(), you will see that it takes:

int qnx_hint_attach((unsigned, void __far *, unsigned)

That __far is not going to be the default type for a pointer to a
function, and if you don’t have the correct prototype, you’re going
to be getting the wrong stuff passed there. Basically, that far
pointer to your function is a 48-bit value, and you passed in a
32-bit function pointer. So, the extra 16-bits are going to come
from the DS you pass, and the extra 16-bits from the DS are going
to come from garbage memory.

This lack of proper prototypes for a function can cause you problems
anywhere – unfortunately, here you are lying to the kernel rather than
to something else in your own program, and this will cause trouble.

If you properly cast you arguments to match the REAL prototype, rather
than relying on C’s automatic munging of arguments to match the
prototype, you wouldn’t have had this problem either – things would
have worked.

-David

QNX Training Services
dagibbs@qnx.com

If you take a look at
the definition for qnx_hint_attach(), you will see that it takes:

int qnx_hint_attach((unsigned, void __far *, unsigned)

That __far is not going to be the default type for a pointer to a
function,

Even if the function is declared as far?

and if you don’t have the correct prototype, you’re going
to be getting the wrong stuff passed there. Basically, that far
pointer to your function is a 48-bit value, and you passed in a
32-bit function pointer.

Did I? The interrupt handler function is declared as “far”, which
should mean that the “address-of” operator should be automatically
returning a far pointer. At least, Watcom C language reference says
that (page 100, “If the type of the operand is ‘type’, then the type
of the result is 'pointer to ‘type’ and the result is the address of
the operand.”).

If you properly cast you arguments to match the REAL prototype,
rather
than relying on C’s automatic munging of arguments to match the
prototype, you wouldn’t have had this problem either – things would
have worked.

Tried an explicit cast - yes, of course it worked. But - actually, I
took the sample code from the qnx_hint_attach() docs, yet there is no
exlicit cast there which means that “Simon says, it should work as it
is”.

“Nikolai Gorbunov” <n.gorbunov@swd.ru> wrote in message
news:96vuao$a3$1@inn.qnx.com

If you take a look at
the definition for qnx_hint_attach(), you will see that it takes:

int qnx_hint_attach((unsigned, void __far *, unsigned)

That __far is not going to be the default type for a pointer to a
function,

Even if the function is declared as far?



and if you don’t have the correct prototype, you’re going
to be getting the wrong stuff passed there. Basically, that far
pointer to your function is a 48-bit value, and you passed in a
32-bit function pointer.

Did I? The interrupt handler function is declared as “far”, which
should mean that the “address-of” operator should be automatically
returning a far pointer. At least, Watcom C language reference says
that (page 100, “If the type of the operand is ‘type’, then the type
of the result is 'pointer to ‘type’ and the result is the address of
the operand.”).

If you properly cast you arguments to match the REAL prototype,
rather
than relying on C’s automatic munging of arguments to match the
prototype, you wouldn’t have had this problem either – things would
have worked.

Tried an explicit cast - yes, of course it worked. But - actually, I
took the sample code from the qnx_hint_attach() docs, yet there is no
exlicit cast there which means that “Simon says, it should work as it
is”.

The example does include sys/irqinfo.h. Hence it doesn’t need the cast.

It appears that because watcom uses register passing it needs to know
the type of t

This is the assembly code with the prototypes

mov edx,00000001H
mov ebx,offset y_
mov cx,cs
mov eax,edx
call qnx_hint_attach_

Notice that the offset y (which is the name off the function)
gets passed in variable ebx.

mov ebx,00000001H
mov edx,offset y_
mov eax,ebx
mov cx,cs
call qnx_hint_attach_

Notice that the offset y (which is the name off the function)
gets passed in variable edx.

According to Watcom’s manual far pointer should be pass
in either [ECX EBX] or [EDX EAX] pair. In the example without prototypes
the par [ECX EDX] is used which is “invalid”.

So a far pointer does gets passed (just like the Watcom manual
pointed out at page 100), but since their is no prototypes
Watcom doesn’t really know what register pair to use.
It is possible to define a function and forcing the register
pair to be used. Hence watcom has no real way to tell
what register pair to use without the prototypes being
defined. I could probably have guessed better but then
you would be relying on a overly intelligent compiler

The moral is always compile with warnings enable (-w9)
They can save lots of time :wink: