0

I have written a function that needs to do a 64bit initialisation of memory for an embedded device. Can anyone tell me if this function will carry out this task?

void write64BitValueTo(void* address, U_INT64 pattern)
{

    int i;

    U_INT64 size = (0x20000000 / sizeof(U_INT64));

    //printf("Size = 0x%8X \n",size);
    U_INT64 *ptr = (U_INT64 *) address;

    for(i = 0; i< size; i++)
    {
        *ptr = pattern;
        ptr++;
    }
}
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
JohnB
  • 601
  • 2
  • 10
  • 19
  • possibly, but even if so you really should pass the size 0x20000000 as an argument. – stijn Mar 09 '11 at 10:10
  • It writes the pattern over 512MB starting at the specified address. Is that what's wanted? – Steve Jessop Mar 09 '11 at 10:12
  • Yeah this is just a test function the size will always be the same. – JohnB Mar 09 '11 at 10:12
  • Yes Steve that is what is wanted but each single write must be a 64bit write otherwise its not what is desired. – JohnB Mar 09 '11 at 10:14
  • 3
    Then it's fine, provided that strict aliasing doesn't ruin it. If you write memory using a `U_INT64*`, and the compiler somehow detects that for the remainder of the program you never access the memory using `U_INT64*` or any so-called "compatible type" (which in this case means `U_INT64`, `INT_64` and char types), then it's allowed to conclude that the memory is unused after the write, and optimize it away. It's *very* unlikely that would happen in this case, but to be strictly safe you would have to write using an `unsigned char*`, which means 8 different values in a repeating pattern. – Steve Jessop Mar 09 '11 at 10:19
  • A situation where it theoretically could arise is if you use this function to initialize an array of `double`. Since `double` isn't a compatible type, it's technically undefined behavior to read it back as `double` even if the pattern is a correct bitwise representation of the double value you want. In effect, the compiler may assume that a value accessed as `U_INT64` and a value accessed as `double` cannot possibly refer to the same memory. It typically goes wrong when the aliasing is all within a single function, though, rather than for something like this. – Steve Jessop Mar 09 '11 at 10:21
  • Thanks Steve I don't think I will run into the this problem as U_INT64 is a very common type in my application and used regularly. – JohnB Mar 09 '11 at 10:33
  • 2
    Don't use `int` as the type for your loop variable, but the same as for `size`. – Jens Gustedt Mar 09 '11 at 10:34
  • @Jens good advice. pmg points out below that `i` isn't even necessary, one can loop on `size--`. – Jim Balter Mar 09 '11 at 10:38
  • @Jim, yes I have seen that. But this sort of side effect programming is not everyones taste (at least not mine) and if one would stick to a version as the original, the type should be changed. – Jens Gustedt Mar 09 '11 at 10:42
  • @Jens I don't care for it either, but I also don't like repeating information such as types. Fortunately I don't have to as I rarely use this ancient language anymore. – Jim Balter Mar 09 '11 at 10:45

2 Answers2

1

You should declare ptr as volatile U_INT64 *ptr as the compiler could otherwise optimise away the assignment *ptr = pattern.

If it's important that the pattern is actually written to memory and not just the data cache (assuming there is one), then you should also flush the cache afterwards. Otherwise your code looks just fine.

Frederico
  • 101
  • 1
  • 1
  • 4
  • If the compiler sees that the stored values are not subsequently used, then it could optimise it away if the volatile qualifier is not used. In this case it is probably unlikely, as the function is not declared static. – Frederico Mar 15 '11 at 21:47
0

It should work as long as address is properly aligned to allow storing 64-bit words on your architecture.

I'm curious: Why do you write

for(i = 0; i< size; i++)
{
    *ptr = pattern;
    ptr++;
}

when

for(i = 0; i < size; i++)
    *ptr++ = pattern;

is simpler and easier to write and read?

Jim Balter
  • 16,163
  • 3
  • 43
  • 66