umovestr: speed up check for NUL byte in the fetched word
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/util.c b/util.c
index 34c1b62..00846a2 100644
--- a/util.c
+++ b/util.c
@@ -843,7 +843,10 @@
}
m = MIN(sizeof(long) - n, len);
memcpy(laddr, &u.x[n], m);
- addr += sizeof(long), laddr += m, len -= m, nread += m;
+ addr += sizeof(long);
+ laddr += m;
+ nread += m;
+ len -= m;
}
while (len) {
errno = 0;
@@ -869,7 +872,10 @@
}
m = MIN(sizeof(long), len);
memcpy(laddr, u.x, m);
- addr += sizeof(long), laddr += m, len -= m, nread += m;
+ addr += sizeof(long);
+ laddr += m;
+ nread += m;
+ len -= m;
}
return 0;
@@ -890,10 +896,20 @@
int
umovestr(struct tcb *tcp, long addr, int len, char *laddr)
{
+#if SIZEOF_LONG == 4
+ const unsigned long x01010101 = 0x01010101ul;
+ const unsigned long x80808080 = 0x80808080ul;
+#elif SIZEOF_LONG == 8
+ const unsigned long x01010101 = 0x0101010101010101ul;
+ const unsigned long x80808080 = 0x8080808080808080ul;
+#else
+# error SIZEOF_LONG > 8
+#endif
+
int pid = tcp->pid;
- int i, n, m, nread;
+ int n, m, nread;
union {
- long val;
+ unsigned long val;
char x[sizeof(long)];
} u;
@@ -989,8 +1005,12 @@
while (n & (sizeof(long) - 1))
if (u.x[n++] == '\0')
return 1;
- addr += sizeof(long), laddr += m, len -= m, nread += m;
+ addr += sizeof(long);
+ laddr += m;
+ nread += m;
+ len -= m;
}
+
while (len) {
errno = 0;
u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0);
@@ -1015,10 +1035,13 @@
}
m = MIN(sizeof(long), len);
memcpy(laddr, u.x, m);
- for (i = 0; i < sizeof(long); i++)
- if (u.x[i] == '\0')
- return 1;
- addr += sizeof(long), laddr += m, len -= m, nread += m;
+ /* "If a NUL char exists in this word" */
+ if ((u.val - x01010101) & ~u.val & x80808080)
+ return 1;
+ addr += sizeof(long);
+ laddr += m;
+ nread += m;
+ len -= m;
}
return 0;
}