9
9
"internal/race"
10
10
"internal/syscall/windows"
11
11
"io"
12
+ "runtime"
12
13
"sync"
13
14
"sync/atomic"
14
15
"syscall"
@@ -75,9 +76,6 @@ type operation struct {
75
76
// fields used by runtime.netpoll
76
77
runtimeCtx uintptr
77
78
mode int32
78
-
79
- // fields used only by net package
80
- buf syscall.WSABuf
81
79
}
82
80
83
81
func (o * operation ) setEvent () {
@@ -107,9 +105,8 @@ func (fd *FD) overlapped(o *operation) *syscall.Overlapped {
107
105
return & o .o
108
106
}
109
107
110
- func (o * operation ) InitBuf (buf []byte ) {
111
- o .buf .Len = uint32 (len (buf ))
112
- o .buf .Buf = unsafe .SliceData (buf )
108
+ func newWsaBuf (b []byte ) * syscall.WSABuf {
109
+ return & syscall.WSABuf {Buf : unsafe .SliceData (b ), Len : uint32 (len (b ))}
113
110
}
114
111
115
112
var wsaBufsPool = sync.Pool {
@@ -362,6 +359,9 @@ type FD struct {
362
359
isBlocking bool
363
360
364
361
disassociated atomic.Bool
362
+
363
+ readPinner runtime.Pinner
364
+ writePinner runtime.Pinner
365
365
}
366
366
367
367
// setOffset sets the offset fields of the overlapped object
@@ -537,6 +537,11 @@ func (fd *FD) Read(buf []byte) (int, error) {
537
537
defer fd .readUnlock ()
538
538
}
539
539
540
+ if len (buf ) > 0 && ! fd .isBlocking {
541
+ fd .readPinner .Pin (& buf [0 ])
542
+ defer fd .readPinner .Unpin ()
543
+ }
544
+
540
545
if len (buf ) > maxRW {
541
546
buf = buf [:maxRW ]
542
547
}
@@ -547,10 +552,8 @@ func (fd *FD) Read(buf []byte) (int, error) {
547
552
case kindConsole :
548
553
n , err = fd .readConsole (buf )
549
554
case kindFile , kindPipe :
550
- o := & fd .rop
551
- o .InitBuf (buf )
552
- n , err = fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
553
- err = syscall .ReadFile (fd .Sysfd , unsafe .Slice (o .buf .Buf , o .buf .Len ), & qty , fd .overlapped (o ))
555
+ n , err = fd .execIO (& fd .rop , func (o * operation ) (qty uint32 , err error ) {
556
+ err = syscall .ReadFile (fd .Sysfd , buf , & qty , fd .overlapped (o ))
554
557
return qty , err
555
558
})
556
559
fd .addOffset (n )
@@ -564,11 +567,9 @@ func (fd *FD) Read(buf []byte) (int, error) {
564
567
}
565
568
}
566
569
case kindNet :
567
- o := & fd .rop
568
- o .InitBuf (buf )
569
- n , err = fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
570
+ n , err = fd .execIO (& fd .rop , func (o * operation ) (qty uint32 , err error ) {
570
571
var flags uint32
571
- err = syscall .WSARecv (fd .Sysfd , & o . buf , 1 , & qty , & flags , & o .o , nil )
572
+ err = syscall .WSARecv (fd .Sysfd , newWsaBuf ( buf ) , 1 , & qty , & flags , & o .o , nil )
572
573
return qty , err
573
574
})
574
575
if race .Enabled {
@@ -656,7 +657,7 @@ func (fd *FD) readConsole(b []byte) (int, error) {
656
657
}
657
658
658
659
// Pread emulates the Unix pread system call.
659
- func (fd * FD ) Pread (b []byte , off int64 ) (int , error ) {
660
+ func (fd * FD ) Pread (buf []byte , off int64 ) (int , error ) {
660
661
if fd .kind == kindPipe {
661
662
// Pread does not work with pipes
662
663
return 0 , syscall .ESPIPE
@@ -667,8 +668,13 @@ func (fd *FD) Pread(b []byte, off int64) (int, error) {
667
668
}
668
669
defer fd .readWriteUnlock ()
669
670
670
- if len (b ) > maxRW {
671
- b = b [:maxRW ]
671
+ if len (buf ) > 0 && ! fd .isBlocking {
672
+ fd .readPinner .Pin (& buf [0 ])
673
+ defer fd .readPinner .Unpin ()
674
+ }
675
+
676
+ if len (buf ) > maxRW {
677
+ buf = buf [:maxRW ]
672
678
}
673
679
674
680
if fd .isBlocking {
@@ -687,17 +693,15 @@ func (fd *FD) Pread(b []byte, off int64) (int, error) {
687
693
curoffset := fd .offset
688
694
defer fd .setOffset (curoffset )
689
695
}
690
- o := & fd .rop
691
- o .InitBuf (b )
692
696
fd .setOffset (off )
693
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
694
- err = syscall .ReadFile (fd .Sysfd , unsafe . Slice ( o . buf . Buf , o . buf . Len ) , & qty , & o .o )
697
+ n , err := fd .execIO (& fd . rop , func (o * operation ) (qty uint32 , err error ) {
698
+ err = syscall .ReadFile (fd .Sysfd , buf , & qty , & o .o )
695
699
return qty , err
696
700
})
697
701
if err == syscall .ERROR_HANDLE_EOF {
698
702
err = io .EOF
699
703
}
700
- if len (b ) != 0 {
704
+ if len (buf ) != 0 {
701
705
err = fd .eofError (n , err )
702
706
}
703
707
return n , err
@@ -715,14 +719,18 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
715
719
return 0 , nil , err
716
720
}
717
721
defer fd .readUnlock ()
718
- o := & fd .rop
719
- o .InitBuf (buf )
722
+
723
+ if ! fd .isBlocking {
724
+ fd .readPinner .Pin (& buf [0 ])
725
+ defer fd .readPinner .Unpin ()
726
+ }
727
+
720
728
rsa := wsaRsaPool .Get ().(* syscall.RawSockaddrAny )
721
729
defer wsaRsaPool .Put (rsa )
722
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
730
+ n , err := fd .execIO (& fd . rop , func (o * operation ) (qty uint32 , err error ) {
723
731
rsan := int32 (unsafe .Sizeof (* rsa ))
724
732
var flags uint32
725
- err = syscall .WSARecvFrom (fd .Sysfd , & o . buf , 1 , & qty , & flags , rsa , & rsan , & o .o , nil )
733
+ err = syscall .WSARecvFrom (fd .Sysfd , newWsaBuf ( buf ) , 1 , & qty , & flags , rsa , & rsan , & o .o , nil )
726
734
return qty , err
727
735
})
728
736
err = fd .eofError (n , err )
@@ -745,14 +753,18 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error)
745
753
return 0 , err
746
754
}
747
755
defer fd .readUnlock ()
748
- o := & fd .rop
749
- o .InitBuf (buf )
756
+
757
+ if ! fd .isBlocking {
758
+ fd .readPinner .Pin (& buf [0 ])
759
+ defer fd .readPinner .Unpin ()
760
+ }
761
+
750
762
rsa := wsaRsaPool .Get ().(* syscall.RawSockaddrAny )
751
763
defer wsaRsaPool .Put (rsa )
752
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
764
+ n , err := fd .execIO (& fd . rop , func (o * operation ) (qty uint32 , err error ) {
753
765
rsan := int32 (unsafe .Sizeof (* rsa ))
754
766
var flags uint32
755
- err = syscall .WSARecvFrom (fd .Sysfd , & o . buf , 1 , & qty , & flags , rsa , & rsan , & o .o , nil )
767
+ err = syscall .WSARecvFrom (fd .Sysfd , newWsaBuf ( buf ) , 1 , & qty , & flags , rsa , & rsan , & o .o , nil )
756
768
return qty , err
757
769
})
758
770
err = fd .eofError (n , err )
@@ -775,14 +787,18 @@ func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error)
775
787
return 0 , err
776
788
}
777
789
defer fd .readUnlock ()
778
- o := & fd .rop
779
- o .InitBuf (buf )
790
+
791
+ if ! fd .isBlocking {
792
+ fd .readPinner .Pin (& buf [0 ])
793
+ defer fd .readPinner .Unpin ()
794
+ }
795
+
780
796
rsa := wsaRsaPool .Get ().(* syscall.RawSockaddrAny )
781
797
defer wsaRsaPool .Put (rsa )
782
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
798
+ n , err := fd .execIO (& fd . rop , func (o * operation ) (qty uint32 , err error ) {
783
799
rsan := int32 (unsafe .Sizeof (* rsa ))
784
800
var flags uint32
785
- err = syscall .WSARecvFrom (fd .Sysfd , & o . buf , 1 , & qty , & flags , rsa , & rsan , & o .o , nil )
801
+ err = syscall .WSARecvFrom (fd .Sysfd , newWsaBuf ( buf ) , 1 , & qty , & flags , rsa , & rsan , & o .o , nil )
786
802
return qty , err
787
803
})
788
804
err = fd .eofError (n , err )
@@ -807,6 +823,11 @@ func (fd *FD) Write(buf []byte) (int, error) {
807
823
defer fd .writeUnlock ()
808
824
}
809
825
826
+ if len (buf ) > 0 && ! fd .isBlocking {
827
+ fd .writePinner .Pin (& buf [0 ])
828
+ defer fd .writePinner .Unpin ()
829
+ }
830
+
810
831
var ntotal int
811
832
for {
812
833
max := len (buf )
@@ -820,21 +841,17 @@ func (fd *FD) Write(buf []byte) (int, error) {
820
841
case kindConsole :
821
842
n , err = fd .writeConsole (b )
822
843
case kindPipe , kindFile :
823
- o := & fd .wop
824
- o .InitBuf (b )
825
- n , err = fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
826
- err = syscall .WriteFile (fd .Sysfd , unsafe .Slice (o .buf .Buf , o .buf .Len ), & qty , fd .overlapped (o ))
844
+ n , err = fd .execIO (& fd .wop , func (o * operation ) (qty uint32 , err error ) {
845
+ err = syscall .WriteFile (fd .Sysfd , b , & qty , fd .overlapped (o ))
827
846
return qty , err
828
847
})
829
848
fd .addOffset (n )
830
849
case kindNet :
831
850
if race .Enabled {
832
851
race .ReleaseMerge (unsafe .Pointer (& ioSync ))
833
852
}
834
- o := & fd .wop
835
- o .InitBuf (b )
836
- n , err = fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
837
- err = syscall .WSASend (fd .Sysfd , & o .buf , 1 , & qty , 0 , & o .o , nil )
853
+ n , err = fd .execIO (& fd .wop , func (o * operation ) (qty uint32 , err error ) {
854
+ err = syscall .WSASend (fd .Sysfd , newWsaBuf (b ), 1 , & qty , 0 , & o .o , nil )
838
855
return qty , err
839
856
})
840
857
}
@@ -903,6 +920,11 @@ func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
903
920
}
904
921
defer fd .readWriteUnlock ()
905
922
923
+ if len (buf ) > 0 && ! fd .isBlocking {
924
+ fd .writePinner .Pin (& buf [0 ])
925
+ defer fd .writePinner .Unpin ()
926
+ }
927
+
906
928
if fd .isBlocking {
907
929
curoffset , err := syscall .Seek (fd .Sysfd , 0 , io .SeekCurrent )
908
930
if err != nil {
@@ -926,12 +948,9 @@ func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
926
948
if max - ntotal > maxRW {
927
949
max = ntotal + maxRW
928
950
}
929
- b := buf [ntotal :max ]
930
- o := & fd .wop
931
- o .InitBuf (b )
932
951
fd .setOffset (off + int64 (ntotal ))
933
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
934
- err = syscall .WriteFile (fd .Sysfd , unsafe . Slice ( o . buf . Buf , o . buf . Len ) , & qty , & o .o )
952
+ n , err := fd .execIO (& fd . wop , func (o * operation ) (qty uint32 , err error ) {
953
+ err = syscall .WriteFile (fd .Sysfd , buf [ ntotal : max ] , & qty , & o .o )
935
954
return qty , err
936
955
})
937
956
if n > 0 {
@@ -978,25 +997,26 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
978
997
979
998
if len (buf ) == 0 {
980
999
// handle zero-byte payload
981
- o := & fd .wop
982
- o .InitBuf (buf )
983
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
984
- err = syscall .WSASendto (fd .Sysfd , & o .buf , 1 , & qty , 0 , sa , & o .o , nil )
1000
+ n , err := fd .execIO (& fd .wop , func (o * operation ) (qty uint32 , err error ) {
1001
+ err = syscall .WSASendto (fd .Sysfd , & syscall.WSABuf {}, 1 , & qty , 0 , sa , & o .o , nil )
985
1002
return qty , err
986
1003
})
987
1004
return n , err
988
1005
}
989
1006
1007
+ if ! fd .isBlocking {
1008
+ fd .writePinner .Pin (& buf [0 ])
1009
+ defer fd .writePinner .Unpin ()
1010
+ }
1011
+
990
1012
ntotal := 0
991
1013
for len (buf ) > 0 {
992
1014
b := buf
993
1015
if len (b ) > maxRW {
994
1016
b = b [:maxRW ]
995
1017
}
996
- o := & fd .wop
997
- o .InitBuf (b )
998
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
999
- err = syscall .WSASendto (fd .Sysfd , & o .buf , 1 , & qty , 0 , sa , & o .o , nil )
1018
+ n , err := fd .execIO (& fd .wop , func (o * operation ) (qty uint32 , err error ) {
1019
+ err = syscall .WSASendto (fd .Sysfd , newWsaBuf (b ), 1 , & qty , 0 , sa , & o .o , nil )
1000
1020
return qty , err
1001
1021
})
1002
1022
ntotal += int (n )
@@ -1017,25 +1037,26 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error)
1017
1037
1018
1038
if len (buf ) == 0 {
1019
1039
// handle zero-byte payload
1020
- o := & fd .wop
1021
- o .InitBuf (buf )
1022
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
1023
- err = windows .WSASendtoInet4 (fd .Sysfd , & o .buf , 1 , & qty , 0 , sa4 , & o .o , nil )
1040
+ n , err := fd .execIO (& fd .wop , func (o * operation ) (qty uint32 , err error ) {
1041
+ err = windows .WSASendtoInet4 (fd .Sysfd , & syscall.WSABuf {}, 1 , & qty , 0 , sa4 , & o .o , nil )
1024
1042
return qty , err
1025
1043
})
1026
1044
return n , err
1027
1045
}
1028
1046
1047
+ if ! fd .isBlocking {
1048
+ fd .writePinner .Pin (& buf [0 ])
1049
+ defer fd .writePinner .Unpin ()
1050
+ }
1051
+
1029
1052
ntotal := 0
1030
1053
for len (buf ) > 0 {
1031
1054
b := buf
1032
1055
if len (b ) > maxRW {
1033
1056
b = b [:maxRW ]
1034
1057
}
1035
- o := & fd .wop
1036
- o .InitBuf (b )
1037
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
1038
- err = windows .WSASendtoInet4 (fd .Sysfd , & o .buf , 1 , & qty , 0 , sa4 , & o .o , nil )
1058
+ n , err := fd .execIO (& fd .wop , func (o * operation ) (qty uint32 , err error ) {
1059
+ err = windows .WSASendtoInet4 (fd .Sysfd , newWsaBuf (b ), 1 , & qty , 0 , sa4 , & o .o , nil )
1039
1060
return qty , err
1040
1061
})
1041
1062
ntotal += int (n )
@@ -1056,25 +1077,26 @@ func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error)
1056
1077
1057
1078
if len (buf ) == 0 {
1058
1079
// handle zero-byte payload
1059
- o := & fd .wop
1060
- o .InitBuf (buf )
1061
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
1062
- err = windows .WSASendtoInet6 (fd .Sysfd , & o .buf , 1 , & qty , 0 , sa6 , & o .o , nil )
1080
+ n , err := fd .execIO (& fd .wop , func (o * operation ) (qty uint32 , err error ) {
1081
+ err = windows .WSASendtoInet6 (fd .Sysfd , & syscall.WSABuf {}, 1 , & qty , 0 , sa6 , & o .o , nil )
1063
1082
return qty , err
1064
1083
})
1065
1084
return n , err
1066
1085
}
1067
1086
1087
+ if ! fd .isBlocking {
1088
+ fd .writePinner .Pin (& buf [0 ])
1089
+ defer fd .writePinner .Unpin ()
1090
+ }
1091
+
1068
1092
ntotal := 0
1069
1093
for len (buf ) > 0 {
1070
1094
b := buf
1071
1095
if len (b ) > maxRW {
1072
1096
b = b [:maxRW ]
1073
1097
}
1074
- o := & fd .wop
1075
- o .InitBuf (b )
1076
- n , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
1077
- err = windows .WSASendtoInet6 (fd .Sysfd , & o .buf , 1 , & qty , 0 , sa6 , & o .o , nil )
1098
+ n , err := fd .execIO (& fd .wop , func (o * operation ) (qty uint32 , err error ) {
1099
+ err = windows .WSASendtoInet6 (fd .Sysfd , newWsaBuf (b ), 1 , & qty , 0 , sa6 , & o .o , nil )
1078
1100
return qty , err
1079
1101
})
1080
1102
ntotal += int (n )
@@ -1264,14 +1286,12 @@ func (fd *FD) RawRead(f func(uintptr) bool) error {
1264
1286
1265
1287
// Use a zero-byte read as a way to get notified when this
1266
1288
// socket is readable. h/t https://stackoverflow.com/a/42019668/332798
1267
- o := & fd .rop
1268
- o .InitBuf (nil )
1269
- _ , err := fd .execIO (o , func (o * operation ) (qty uint32 , err error ) {
1289
+ _ , err := fd .execIO (& fd .rop , func (o * operation ) (qty uint32 , err error ) {
1270
1290
var flags uint32
1271
1291
if ! fd .IsStream {
1272
1292
flags |= windows .MSG_PEEK
1273
1293
}
1274
- err = syscall .WSARecv (fd .Sysfd , & o . buf , 1 , & qty , & flags , & o .o , nil )
1294
+ err = syscall .WSARecv (fd .Sysfd , & syscall. WSABuf {} , 1 , & qty , & flags , & o .o , nil )
1275
1295
return qty , err
1276
1296
})
1277
1297
if err == windows .WSAEMSGSIZE {
0 commit comments