Detecting support for unaligned words

F

fox

Maybe this is not the best group to ask this question,
but I don't know a better one.

I'm looking for a *portable* program in C (I mean source code)
to detect whether unaligned word access is:
a. handled by the main processor (e.g. x86)
b. not supported (e.g. Sparc running Solaris)
c. emulated in software (e.g. Alpha running Linux)

By "unaligned word access" I mean access to a 16-bit word
at an odd address or to a 32-bit word at an address that
is not multiple of 4.

Cases 'b' and 'c' don't need to differentiated.

Thanks,
Piotr
 
M

Michael Mair

Maybe this is not the best group to ask this question,
but I don't know a better one.

I'm looking for a *portable* program in C (I mean source code)
to detect whether unaligned word access is:
a. handled by the main processor (e.g. x86)
b. not supported (e.g. Sparc running Solaris)
c. emulated in software (e.g. Alpha running Linux)

By "unaligned word access" I mean access to a 16-bit word
at an odd address or to a 32-bit word at an address that
is not multiple of 4.

Cases 'b' and 'c' don't need to differentiated.

There is no such program -- you of course can do nice little
tricks like memmove()ing inside an array by 1, accessing the
old address+1 and hoping for the same result. However, there
is no guarantee that this works always. In addition, it may
be possible but needs a compiler extension etc.

Cheers
Michael
 
C

Clark S. Cox III

Maybe this is not the best group to ask this question,
but I don't know a better one.

I'm looking for a *portable* program in C (I mean source code)
to detect whether unaligned word access is:
a. handled by the main processor (e.g. x86)
b. not supported (e.g. Sparc running Solaris)
c. emulated in software (e.g. Alpha running Linux)

No such program exists (no could it).
 
T

tedu

I'm looking for a *portable* program in C (I mean source code)
to detect whether unaligned word access is:
a. handled by the main processor (e.g. x86)
b. not supported (e.g. Sparc running Solaris)
c. emulated in software (e.g. Alpha running Linux)

By "unaligned word access" I mean access to a 16-bit word
at an odd address or to a 32-bit word at an address that
is not multiple of 4.

it's not perfect, but should fail on the conservative side in most
cases.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main(int argc, char **argv)
{
FILE *fp;
char buf[1024];

if (system("uname -m > myfilewithmachineinfo") == 0) {
fp = fopen("myfilewithmachineinfo", "r");
if (fp) {
fgets(buf, sizeof buf, fp);
fclose(fp);
if (strstr(buf, "i386")) {
printf("Unaligned access is ok\n");
return 0;
} else if (strstr(buf, "alpha")) {
printf("Unaligned access is done in software\n");
return 0;
}
}
}
printf("Unaligned access is not ok\n");
}
 
F

fox

I'm disappointed with your answers.
Here's a program that differentiates case 'b' from 'a' and 'c':

#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
jmp_buf jmpbuf;
void bus_err()
{
longjmp(jmpbuf, 1);
}
int main(void)
{
#ifndef SIGBUS
return 0;
#else
int l[2];
if (setjmp(jmpbuf) == 0) {
signal(SIGBUS, bus_err);
*((int *) ((char *) l + 1)) = 1;
signal(SIGBUS, SIG_DFL);
return 0;
}
else {
signal(SIGBUS, SIG_DFL);
return 1;
}
#endif
}
 
W

Walter Roberson

I'm disappointed with your answers.
Here's a program that differentiates case 'b' from 'a' and 'c':
signal(SIGBUS, bus_err);

You asked for a portable standard program.

http://www.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html

"The ISO C standard only requires the signal names SIGABRT, SIGFPE,
SIGILL, SIGINT, SIGSEGV, and SIGTERM to be defined."

You do check #ifndef SIGBUS but you return a constant value
if it is not defined, which is NOT a portable way of detecting
whether unaligned accesses are permitted or not.

Your original posting also asked for three cases to be differentiated
and said that the second (no support) and third (software support)
need not be differentiated, but your program cannot differentiate
the third case from the first, and so fails the specifications that you
yourself posted.

You are also mis-using SIGBUS according to opengroup:

SIGBUS Access to an undefined portion of a memory object.

but in your program, the portion was defined, but was being (potentially)
misaddressed. That case is closer to

SIGSEGV Invalid memory reference.


If you found experimentally that you needed to use SIGBUS on
a system instead of SIGSEGV, then clearly on that system there
are system dependancies that make the usage non-portable (SIGSEGV
being the ISO C signal that would appear to be appropriate.)


ISO C says, with respect to the aborting signals,

An implementation need not generate any of these signals, except as
a result of explicit calls to the raise function.

The standard also indicates,

If and when the function returns, if the value of sig is SIGFPE,
SIGILL, SIGSEGV, or any other implementation-defined value
corresponding to a computational exception, the behaviour is
undefined; otherwise the program will resume execution at the
point it was interrrupted.

I would need to look somewhat further to see whether the state
that is restored by longjmp() includes clearing the undefined
state implied by the above paragraph.
 
F

fox

You do check #ifndef SIGBUS but you return a constant value
if it is not defined, which is NOT a portable way of detecting
whether unaligned accesses are permitted or not.

That's right, I conservatively assume that unaligned access is not
supported there.

This is of little importance for me, because this POSIX standard you
pointed me at
says that SIGBUS "shall be supported on all implementations".
Your original posting also asked for three cases to be differentiated
and said that the second (no support) and third (software support)
need not be differentiated, but your program cannot differentiate
the third case from the first, and so fails the specifications that you
yourself posted.

I think I clearly indicated that this program is *not* the one I want.
But at least it does the job partially, so I posted it, so maybe
someone
can improve it rather than start from scratch.
You are also mis-using SIGBUS according to opengroup

No. You can read on this page:
"Signal: SIGBUS, Reason: Invalid address alignment."
I would need to look somewhat further to see whether the state
that is restored by longjmp() includes clearing the undefined
state implied by the above paragraph.

Maybe it's better to use exit() directly in the signal handler.
I didn't write this program.
 
W

Walter Roberson

You do check #ifndef SIGBUS but you return a constant value
if it is not defined, which is NOT a portable way of detecting
whether unaligned accesses are permitted or not.
[/QUOTE]
That's right, I conservatively assume that unaligned access is not
supported there.
This is of little importance for me, because this POSIX standard you
pointed me at
says that SIGBUS "shall be supported on all implementations".

Your original posting emphasized "*portable*" C. POSIX is not portable
within the meaning of comp.lang.c . POSIX is an operating system interface
specification. Windows, for example, did not make a serious attempt
at POSIX until Windows XP (though W2K was getting there.)

When you ask for "portable" code within comp.lang.c, you are going to
get answers that involve ONLY what may be safely done with the C89 or
C99 standards. If the task you ask for cannot be done without OS
extensions, then if you emphasized "portable" then our answer will be
"It can't be done", and if you don't emphasize "portable" then our
answer will be "you can't do it portably, try OS-specific newsgroups."
I think I clearly indicated that this program is *not* the one I want.

That is not a "clear" indication that the program was not the one you
wanted.
But at least it does the job partially, so I posted it, so maybe someone
can improve it rather than start from scratch.

Well, if the program supposedly differentiates no support from
hardware support, then if it worked then the only differentiation
left would be software support. If, though, one has software support
of unaligned accesses, then because the access would complete
in time, the only way to differentiate the cases (besides a hardware
micro-instruction level trace) would be to do -very- careful
timing analyses. Timers are not part of portable C, and high resolution
timers are not required by POSIX.1.

No. You can read on this page:
"Signal: SIGBUS, Reason: Invalid address alignment."

Dang inconsistancies in POSIX documentation.

But at least it does the job partially, so I posted it, so maybe someone
can improve it rather than start from scratch.

What you are asking for CANNOT reliably be done within ISO C without
operating system extensions such as POSIX.1 .. and differentiating
software emulation from direct hardware support is particularily
problematic. For example, what should the answer be for vmware
emulating an x86 running Windows but really running on (say) a Mac OS X
with PowerPC chip? There could be a hardware instruction (that the
compiler might even have used) in the x86 machine code, but since
the program is emulating -everything- on the PowerPC, that's a software
emulation of what would otherwise be a hardware facility... no matter
which answer the program gives, the program would be wrong.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top