Slashdot Mirror


Porting to 64-bit Linux

An anonymous reader writes "As 64-bit architectures continue to gain popularity it is becoming more and more important to make sure that your software is ready for the shift. IBMDeveloperworks takes a look at a few of the most common pitfalls when making sure your applications are 64-bit ready. From the article: 'Major hardware vendors have recently expanded their 64-bit offerings because of the performance, value, and scalability that 64-bit platforms can provide. The constraints of 32-bit systems, particularly the 4GB virtual memory ceiling, have spurred companies to consider migrating to 64-bit platforms. Knowing how to port applications to comply with a 64-bit architecture can help you write portable and efficient code.'"

13 of 120 comments (clear)

  1. Just a recompile? by Bromskloss · · Score: 1, Informative

    Provided your code isn't written in assembly, do you really _have_ to do anything else than to recompile it? Of course, you might want to make changes to make better use of the 64 bits, but to just make it run, wouldn't this be enough?

    --
    Swedish plasma phys. PhD student; MSc EE; knows maths, programming, electronics; finance interest; seeks opportunities
    1. Re:Just a recompile? by cnettel · · Score: 5, Informative
      Unless you assume:
      1. sizeof(int) == sizeof(void*), or
      2. sizeof(int) == 4
      If your codebase only makes the first OR the second assumption, you can tweak the compiler to like you by defines. If you also assume that sizeof(void*) == 4, you have bigger problems. Note that you can do this in rather innocent ways, like dumping a complete structure on disk, knowing that pointer values will be invalid, but just assuming that the structure will be the same size if you read it back later.

      In addition, and this is hellish, a 32-bit MOV is (generally) atomic on x86. You can rely on the high-order word and the low-order word staying together, without race conditions. The memory access semantics are different on x64 and many other platforms. This is not related to 64-bitness per se, you could see if you ported to multi-threaded 32-bit PPC as well, but it will still surface if you do the transition to AMD64/EM64T/x64. Or rather, it will result in an additional one-in-a-million crash in your source, that you'll blame on bad memory chips in the user's machine.

  2. Most of the time it's easy. by PhrostyMcByte · · Score: 4, Informative

    If you don't make assumptions about pointer sizes in your code, always use size_t in the appropriate places, etc, it is generally just a quick recompile for x64. I find a lot of open source code (I'm sure this isn't exclusive to open source, but, well, I can't see closed source!) spits out hundreds to thousands of warnings about assigning the return of strlen() to an int and other similar and usually harmless things, but most of the time it Just Works (tm).

    The only area I've ran into things being significantly harder is writing clean lock-free algorithms due to the lack of a CMPXCHG16B instruction in the original spec - only EMT64 and very recent AMD64 models have it. There are a couple ways to hack around this limitation but they aren't very pretty.

  3. Re:Well written portable code is fine by Anonymous Coward · · Score: 1, Informative

    What you want is provided by the stdint.h header (and before that, inttypes.h), which among other things, provides types which are at least X bits, exactly X bits, or the fastest type with at least X bits. Only the at-least-X bits types are guaranteed to exist, up to the maximum word size on the machine. (After all, C is still used on machines with 24-bit and 31-bit word sizes, among others, and some that don't even use 2-complement arithmetic.)

    However, using something like "int_least32_t" directly in your code is generally frowned upon. Good standard portable programming practice is to create your own typedef of the sized types:

            typedef int_least32_t answer_t;

            answer_t hello = 42;

    Floating point is generally IEEE 754 standardized and so doesn't have any special types. Besides, you don't really care how many bits a floating point type has, just its precision and range.

    Providing software emulation for user-specified bit widths, as you suggested, is a neat idea and all, but it's outside of the scope of a language like C/C++. Even newer languages generally don't offer this. Generally, C/C++ programmers are interested in efficiency, low-level hardware access, or lowest common denominator, "stupid compiler" portability, and they can't do this if they're not using non-primitive types. If you don't care about this, then you're probably using the wrong language.

    Anyway, there are plenty of arbitrary precision libraries for people who need to work with types of arbitrary, or even unlimited width. Most modern languages (not counting C) also have such types built in now, some even promoting primitive types to and from extended range types as needed.

  4. Been there, done that by ChaoticCoyote · · Score: 2, Informative

    I've been running a 100% 64-bit dual Opteron rig for almost two years, under Gentoo. No emulation libraries, no multilib, just 64-bit code. Other than Open Office, I've had almost no trouble at all.

    BTW, "64-bits" don't make programs run faster (in general) — code compiled for AMD64/EMT64 runs faster than its 32-bit counterpart (for the most part) because of the extra general-purpose registers in the AMD 64-bit design.

  5. Use stdint.h! by Chemisor · · Score: 5, Informative

    The article doesn't appear to mention this, but there is a C99 standard header stdint.h, which defines fixed width types. I haven't seen any OSS project use it, for some reason, but it has all the types you need for portable development; int32_t, uint64_t, constant wrappers like UINT64_C, and, of course, limit constants for all of the fixed-size types. Using these is much better than all those size-based #ifdef'ed typedefs I see people use all over their code.

  6. More subtleties can arise ... by AK76 · · Score: 5, Informative

    I did a lot of 64-bit cleaning up for the PHP project, and I can tell you that there are more subtle issues that may arise when porting from 32-bit to 64-bit.

    One example:
    on a 32-bit Intel machine, a double is precise enough to distinguish LONG_MAX (the highest representable long) from LONG_MAX+1 (a number that doesn't fit in a long anymore). So for instance, to determine whether a long multiplication has overflowed, you could repeat the same multiplication using doubles and compare the result to (double)LONG_MAX.
    In contrast, on a 64-bit platform LONG_MAX and LONG_MAX+1 are mapped to the same double representation, so there's no way to do the comparison anymore.
    As this example involves static casts, it is something the compiler will usually not warn you about.

    Another thing to be careful about is passing pointers to variadic functions (eg. sscanf), because usually the compiler doesn't know the expected types, as they are buried in the format string, not in the function prototype.

    1. Re:More subtleties can arise ... by Anonymous Coward · · Score: 1, Informative

      One example:
      on a 32-bit Intel machine, a double is precise enough to distinguish LONG_MAX (the highest representable long) from LONG_MAX+1 (a number that doesn't fit in a long anymore). So for instance, to determine whether a long multiplication has overflowed, you could repeat the same multiplication using doubles and compare the result to (double)LONG_MAX.


      That seems like a terrible way to do it... couldn't you just find the highest set bit position in the multiplicands and add?

      Or better yet, IIRC when you do a 32-bit multiply on x86 you get a 64-bit result. You might have to delve into assembly, but you can directly check for overflow.

  7. Re:/lib was botched, so yes you must port librarie by dastrike · · Score: 2, Informative
    We'll have a /lib directory without libraries, and the "/lib64" wart lasting until the end of time

    Nah. That's a bit pessimistic outlook. Already today /lib64 is a mere symlink to /lib on current distributions. The symlink may have to be kept around of for a while though until the early nomenclature oopses have been effectively phased out.

    $ uname -m
    x86_64
    $ ls -ld /lib*
    drwxr-xr-x 17 root root 4544 2006-03-26 14:52 /lib
    drwxr-xr-x 2 root root 2120 2006-04-02 13:59 /lib32
    lrwxrwxrwx 1 root root 3 2006-02-28 03:09 /lib64 -> lib
    --
    while true; do eject; eject -t; done
  8. Re:64 bit porting is more of a compiler problem by Anonymous Coward · · Score: 1, Informative

    I dunno what 'GNU toolchain' you're using, but I always get warnings about truncation in assignments and comparisons, and with GCC 4.x the signedness warnings are so strict as to almost be absurd (they may have crossed the line with char vs signed char vs unsigned char warnings--yes those are all three distinct types, regardless of whether plain char is effectively signed or unsigned).

    The `quad' type was a BSD anachronism, and in any event "Unix" specific (quad what? C doesn't guaranteed that char is an octet). Remember that C is not Unix, though Unix is C. `long long' could just as well be 128-bit on any platform, including some future Unix. C99 has specified fixed-width signed and unsigned integer types, so use them. They're optional in C99 but I believe mandatory in SUSv3, just like char must only be minimally 8 bits in C99, but exactly 8 bits in SUSv3.

    As for `long void *', what possible legitimate use could you have for that? If you're trying to employ a 64-bit pointer from 32-bit code you're already fubar'd. At that point you don't even have C code anymore, because by definition `void *' must be able to hold any and all pointer values. It's literally not a "void pointer" if there's another pointer type which is larger.

  9. Re:64bit ain't all it's cracked up to be.. by Hal_Porter · · Score: 2, Informative

    It's because of the pagetables. AMD added another level to take the page tables to a 52bit physical address space. The page table entries are compatible with PAE, which most OS's already support. x86 is 3 level, x86-64 is 4 level.

    There's space in the page table entries to handle 64 bits, but adding extra levels to the translation probably has a performance impact. There's still debate about the best way to do 64 bit address translation, and 52 bits is plenty for now. And when they change, it will only affect the bits of the OS that handle paging, user application and even device drives will always see a flat 64 bit virtual address space.

    Like all of x86-64, it's a designed for a subtle mix of good performance in the short term and a painless upgrade path for current OS kernels, without really compromising anything in the long term.

    --
    echo -e 'global _start\n _start:\n mov eax, 2\n int 80h\n jmp _start' > a.asm; nasm a.asm -f elf; ld a.o -o a;
  10. 9-bit by r00t · · Score: 2, Informative

    char was 9-bit

    C requires at least 8 bits for char, so 6 isn't good enough.
    All types must be a multiple of the size of char, because
    sizeof(char) is 1 by definition and fractions are not OK.

    Valid sizes are thus: 9, 12, 18, 36

    The char-short-int-long progression may be one of:

    9,18,18,36 a likely choice
    9,18,27,36 this is the cool way: sizeof(int)==3
    9,18,36,36 a likely choice
    9,27,27,36
    9,27,36,36
    9,36,36,36 a likely choice
    12,24,24,36
    12,24,36,36
    12,36,36,36
    18,18,18,36
    18,18,36,36
    18,36,36,36
    36,36,36,36

  11. Re:Specifying bit lengths by larry+bagina · · Score: 2, Informative

    it could be the fact that the preprocessor doesn't understand sizeof()

    --
    Do you even lift?

    These aren't the 'roids you're looking for.