Detecting support for unaligned words

Discussion in 'C Programming' started by fox, Nov 7, 2005.

  1. fox

    fox Guest

    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
     
    fox, Nov 7, 2005
    #1
    1. Advertisements

  2. fox

    Michael Mair Guest

    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
     
    Michael Mair, Nov 7, 2005
    #2
    1. Advertisements

  3. No such program exists (no could it).
     
    Clark S. Cox III, Nov 7, 2005
    #3
  4. fox

    tedu Guest

    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");
    }
     
    tedu, Nov 7, 2005
    #4
  5. fox

    fox Guest

    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
    }
     
    fox, Nov 8, 2005
    #5
  6. 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.
     
    Walter Roberson, Nov 8, 2005
    #6
  7. fox

    fox Guest

    You do check #ifndef SIGBUS but you return a constant value
    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".
    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.
    No. You can read on this page:
    "Signal: SIGBUS, Reason: Invalid address alignment."
    Maybe it's better to use exit() directly in the signal handler.
    I didn't write this program.
     
    fox, Nov 8, 2005
    #7
  8. [/QUOTE]
    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."
    That is not a "clear" indication that the program was not the one you
    wanted.
    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.

    Dang inconsistancies in POSIX documentation.

    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.
     
    Walter Roberson, Nov 8, 2005
    #8
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.