]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: document special memmove requirements
authorAustin Clements <austin@google.com>
Mon, 6 Jan 2020 16:10:26 +0000 (11:10 -0500)
committerAustin Clements <austin@google.com>
Wed, 22 Jan 2020 18:54:48 +0000 (18:54 +0000)
Unlike C's memmove, Go's memmove must be careful to do indivisible
writes of pointer values because it may be racing with the garbage
collector reading the heap.

We've had various bugs related to this over the years (#36101, #13160,
 #12552). Indeed, memmove is a great target for optimization and it's
easy to forget the special requirements of Go's memmove.

The CL documents these (currently unwritten!) requirements. We're also
adding a test that should hopefully keep everyone honest going
forward, though it's hard to be sure we're hitting all cases of
memmove.

Change-Id: I2f59f8d8d6fb42d2f10006b55d605b5efd8ddc24
Reviewed-on: https://go-review.googlesource.com/c/go/+/213418
Reviewed-by: Cherry Zhang <cherryyz@google.com>
13 files changed:
src/runtime/memmove_386.s
src/runtime/memmove_amd64.s
src/runtime/memmove_arm.s
src/runtime/memmove_arm64.s
src/runtime/memmove_mips64x.s
src/runtime/memmove_mipsx.s
src/runtime/memmove_plan9_386.s
src/runtime/memmove_plan9_amd64.s
src/runtime/memmove_ppc64x.s
src/runtime/memmove_riscv64.s
src/runtime/memmove_s390x.s
src/runtime/memmove_wasm.s
src/runtime/stubs.go

index 7b54070f595cc0696ff37b3b3d7e5ec9ca3cb38f..ecadee39af0df034917b0c685ecdbd79cad00c50 100644 (file)
@@ -28,6 +28,8 @@
 #include "go_asm.h"
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT, $0-12
        MOVL    to+0(FP), DI
index b4243a833b6e6293051e444dfedebe62aa6223a2..9458351fec7aa0117f4dbafe0cafdd4d30a61f82 100644 (file)
@@ -28,6 +28,8 @@
 #include "go_asm.h"
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT, $0-24
 
index 8352fb7860979351db243323dcd7b563701c4c88..7bad8d224960ab6b4022f0e4285120e385365cc8 100644 (file)
@@ -58,6 +58,8 @@
 #define FW3    R4
 #define FR3    R8                                      /* shared with TE */
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT, $4-12
 _memmove:
index cedb0180051f0fe5c82914fed9e4f67db0d42b72..dbb7e9a28a03f0ebc099cf9f96747b5759450f49 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24
        MOVD    to+0(FP), R3
index a4cb7dc81e8800b094ebaf48fb6a6b2342aab88e..8a1b88afba749de29456e130ae4b92cd4b0208bf 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24
        MOVV    to+0(FP), R1
index 13544a3598d4dbe1c75620a27d333d26542f36b6..6c86558f8d2a1a47a99c90bad47a4a7615cb9246 100644 (file)
@@ -14,6 +14,8 @@
 #define MOVWLO  MOVWL
 #endif
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB),NOSPLIT,$-0-12
        MOVW    n+8(FP), R3
index 65dec93f6bba72b7333785c93754bf737dbc792e..1b2f8470ae26d4aac601db879767674cc3436daa 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT, $0-12
        MOVL    to+0(FP), DI
index b729c7c0e7d94ab3833970b86f035a44d6056b6f..68e11d59fd3685227a5cbe1560da65fb11c7f0b0 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT, $0-24
 
index 60cbcc41ec569b654b4e87a2802c8cb457697ba7..dbb3b90fcfeafad84b7d675dcdf405b1438c2151 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24
        MOVD    to+0(FP), R3
index 34e513cda78343d091fe4d51e1f0e93d5e394b70..5dec8d0a33fcca7a1542f8feb261fbef35edbd3a 100755 (executable)
@@ -4,6 +4,8 @@
 
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // void runtime·memmove(void*, void*, uintptr)
 TEXT runtime·memmove(SB),NOSPLIT,$-0-24
        MOV     to+0(FP), T0
index 4ce98b0a95274a0143f5097ecbdeaf6e2b9d0327..f4c2b87d9297d48083370e2b9ed770ad89511158 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB),NOSPLIT|NOFRAME,$0-24
        MOVD    to+0(FP), R6
index d5e20169301659b24842d7cb381e068a80d90420..8525fea35ef4d558d67cf478444f7991b40861fb 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "textflag.h"
 
+// See memmove Go doc for important implementation constraints.
+
 // func memmove(to, from unsafe.Pointer, n uintptr)
 TEXT runtime·memmove(SB), NOSPLIT, $0-24
        MOVD to+0(FP), R0
index a58f267e7f9abcbf54a33187804e49aa00716fd8..b8d4d6b30aa165079c6a6b9a961e72795a403f10 100644 (file)
@@ -83,7 +83,17 @@ func reflect_memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) {
 }
 
 // memmove copies n bytes from "from" to "to".
-// in memmove_*.s
+//
+// memmove ensures that any pointer in "from" is written to "to" with
+// an indivisible write, so that racy reads cannot observe a
+// half-written pointer. This is necessary to prevent the garbage
+// collector from observing invalid pointers, and differs from memmove
+// in unmanaged languages. However, memmove is only required to do
+// this if "from" and "to" may contain pointers, which can only be the
+// case if "from", "to", and "n" are all be word-aligned.
+//
+// Implementations are in memmove_*.s.
+//
 //go:noescape
 func memmove(to, from unsafe.Pointer, n uintptr)