Yuqi Guo
2024-Oct-08 12:24 UTC
Question: Is CAREFUL_ALIGNMENT=1 needed for rsync on RISC-V
Hello,
I'm using rsync on RISC-V machines. I notice that the developers of
rsync seem to assume that only x86 CPUs can handle memory misalignments:
```c
/* We know that the x86 can handle misalignment and has the same
?* byte order (LSB-first) as the 32-bit numbers we transmit. */
#if defined __i386__ || defined __i486__ || defined __i586__ || defined
__i686__ || __amd64
#define CAREFUL_ALIGNMENT 0
#endif
#ifndef CAREFUL_ALIGNMENT
#define CAREFUL_ALIGNMENT 1
#endif
```
Thus, when copying 4-bit integers (just an example), rsync uses direct
copies on x86:
```c
static inline uint32
IVALu(const uchar *buf, int pos)
{
?? ?union {
?? ???? const uchar *b;
?? ???? const uint32 *num;
?? ?} u;
?? ?u.b = buf + pos;
?? ?return *u.num;
}
```
On RISC-V (and any other architectures), it copies bytes one by one:
```c
static inline uint32
IVALu(const uchar *buf, int pos)
{
?? ?return UVAL(buf, pos)
?? ????? | UVAL(buf, pos + 1) << 8
?? ????? | UVAL(buf, pos + 2) << 16
?? ????? | UVAL(buf, pos + 3) << 24;
}
```
However, it seems that RISC-V supports misaligned memory accesses. I
tested the following code on a RISC-V machine. It worked well.
```c
#include <stdio.h>
int x;
int arr[2], out[2];
int main()
{
??????? arr[0]=0x11223344;
??????? arr[1]=0x55667788;
??????? out[0]=out[1]=0;
??????? x=*(arr);
??????? printf("x=%x\n",x);
??????? x= *(int*)((char *)arr +1);
??????? char *ptr=(char *)out+3;
??????? *(int*)ptr=*(int*)((char *)arr +3);
??????? printf("x2=%x\n",x);
??????? printf("out[0]=%x, out[1]=%x\n",out[0],out[1]);
??????? return 0;
}
```
So, my question is, is CAREFUL_ALIGNMENT=1 necessary for RISC-V?
Although misalignment accesses will suffer from a large time penalty on
RISC-V, I guess it can still run faster than four UVAL calls.
Best regards,
Yuqi Guo
