-
Notifications
You must be signed in to change notification settings - Fork 918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net: enable native golang linux networking #4498
Open
leongross
wants to merge
14
commits into
tinygo-org:dev
Choose a base branch
from
leongross:net-linux-nonlinux
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
baf7e4f
link
leongross 329fef6
linux support for net.Dial by stubbing out runtime polling
leongross 3c34bbd
remove print statements for cleaner execution
leongross facd62e
fix uncommited net exclusion
leongross 90532f1
bring back old net
leongross 8224b0e
switch net via build tags
leongross 82f1b96
adjust target os specific build tags
leongross 46394c1
chnage macos build
leongross 42348c8
add integration tests for net
leongross a695ab6
further restrict net package usage
leongross a39597c
add preliminary semaphore implementation
leongross 2e04cc2
remove old forklock stub and replace it with sync.RWMutex
leongross da0f694
wip
leongross c16ff80
implement semrealse and semacquire using futex
leongross File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright 2024 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
//go:build linux | ||
|
||
package runtime | ||
|
||
// For debugging purposes this is used for all target architectures, but this is only valid for linux systems. | ||
// TODO: add linux specific build tags | ||
type pollDesc struct { | ||
runtimeCtx uintptr | ||
} | ||
|
||
func (pd *pollDesc) wait(mode int, isFile bool) error { | ||
return nil | ||
} | ||
|
||
const ( | ||
pollNoError = 0 // no error | ||
pollErrClosing = 1 // descriptor is closed | ||
pollErrTimeout = 2 // I/O timeout | ||
pollErrNotPollable = 3 // general error polling descriptor | ||
) | ||
|
||
//go:linkname poll_runtime_pollReset internal/poll.runtime_pollReset | ||
func poll_runtime_pollReset(pd *pollDesc, mode int) int { | ||
// println("poll_runtime_pollReset not implemented", pd, mode) | ||
return pollNoError | ||
} | ||
|
||
//go:linkname poll_runtime_pollWait internal/poll.runtime_pollWait | ||
func poll_runtime_pollWait(pd *pollDesc, mode int) int { | ||
// println("poll_runtime_pollWait not implemented", pd, mode) | ||
return pollNoError | ||
} | ||
|
||
//go:linkname poll_runtime_pollSetDeadline internal/poll.runtime_pollSetDeadline | ||
func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) { | ||
// println("poll_runtime_pollSetDeadline not implemented", pd, d, mode) | ||
} | ||
|
||
//go:linkname poll_runtime_pollOpen internal/poll.runtime_pollOpen | ||
func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) { | ||
// println("poll_runtime_pollOpen not implemented", fd) | ||
return &pollDesc{runtimeCtx: uintptr(0x1337)}, pollNoError | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright 2024 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
//go:build !linux | ||
|
||
package runtime | ||
|
||
const ( | ||
pollNoError = 0 // no error | ||
pollErrClosing = 1 // descriptor is closed | ||
pollErrTimeout = 2 // I/O timeout | ||
pollErrNotPollable = 3 // general error polling descriptor | ||
) | ||
|
||
// Network poller descriptor. | ||
// | ||
// No heap pointers. | ||
// For linux to call create Fds with a pollDesc, it needs a ctxRuntime pointer, so use the original pollDesc struct. | ||
// On linux we have a heap. | ||
type pollDesc struct{} | ||
|
||
//go:linkname poll_runtime_pollReset internal/poll.runtime_pollReset | ||
func poll_runtime_pollReset(pd *pollDesc, mode int) int { | ||
println("poll_runtime_pollReset not implemented", pd, mode) | ||
return pollErrClosing | ||
} | ||
|
||
//go:linkname poll_runtime_pollWait internal/poll.runtime_pollWait | ||
func poll_runtime_pollWait(pd *pollDesc, mode int) int { | ||
println("poll_runtime_pollWait not implemented", pd, mode) | ||
return pollErrClosing | ||
} | ||
|
||
//go:linkname poll_runtime_pollSetDeadline internal/poll.runtime_pollSetDeadline | ||
func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) { | ||
println("poll_runtime_pollSetDeadline not implemented", pd, d, mode) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,52 @@ | ||
// Copyright 2009 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package runtime | ||
|
||
import ( | ||
"internal/futex" | ||
) | ||
|
||
// This file contains stub implementations for internal/poll. | ||
// The official golang implementation states: | ||
// | ||
// "That is, don't think of these as semaphores. | ||
// Think of them as a way to implement sleep and wakeup | ||
// such that every sleep is paired with a single wakeup, | ||
// even if, due to races, the wakeup happens before the sleep." | ||
leongross marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// | ||
// This is an experimental and probably incomplete implementation of the | ||
// semaphore system, tailed to the network use case. That means, that it does not | ||
// implement the modularity that the semacquire/semacquire1 implementation model | ||
// offers, which in fact is emitted here entirely. | ||
// This means we assume the following constant settings from the golang standard | ||
// library: lifo=false,profile=semaBlock,skipframe=0,reason=waitReasonSemaquire | ||
|
||
//go:linkname semacquire internal/poll.runtime_Semacquire | ||
func semacquire(sema *uint32) { | ||
panic("todo: semacquire") | ||
var semaBlock futex.Futex | ||
semaBlock.Store(*sema) | ||
|
||
// check if we can acquire the semaphore | ||
semaBlock.Wait(1) | ||
|
||
// the semaphore is free to use so we can acquire it | ||
if semaBlock.Swap(0) != 1 { | ||
panic("semaphore is already acquired, racy") | ||
} | ||
} | ||
|
||
//go:linkname semrelease internal/poll.runtime_Semrelease | ||
func semrelease(sema *uint32) { | ||
panic("todo: semrelease") | ||
var semaBlock futex.Futex | ||
semaBlock.Store(*sema) | ||
|
||
// check if we can release the semaphore | ||
if semaBlock.Swap(1) != 0 { | ||
panic("semaphore is not acquired, racy") | ||
} | ||
|
||
// wake up the next waiter | ||
semaBlock.Wake() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
//go:build tinygo && linux && !wasip1 && !wasip2 && tinygo.wasm && !wasm_unknown && !darwin && !baremetal && !nintendoswitch | ||
|
||
package syscall | ||
|
||
import ( | ||
"sync" | ||
) | ||
|
||
var ForkLock sync.RWMutex | ||
|
||
func CloseOnExec(fd int) { | ||
system.CloseOnExec(fd) | ||
} | ||
|
||
func SetNonblock(fd int, nonblocking bool) (err error) { | ||
return system.SetNonblock(fd, nonblocking) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package main | ||
|
||
import ( | ||
"io" | ||
"net" | ||
"strconv" | ||
) | ||
|
||
// Test golang network package integration for tinygo. | ||
// This test is not exhaustive and only tests the basic functionality of the package. | ||
|
||
var ( | ||
testsPassed uint | ||
lnPort int | ||
err error | ||
recvBuf []byte | ||
) | ||
|
||
var ( | ||
testDialListenData = []byte("Hello tinygo :)") | ||
) | ||
|
||
func TestDialListen() { | ||
// listen thread | ||
listenReady := make(chan bool, 1) | ||
go func() { | ||
ln, err := net.Listen("tcp4", ":0") | ||
if err != nil { | ||
println("error listening: ", err) | ||
return | ||
} | ||
lnPort = ln.Addr().(*net.TCPAddr).Port | ||
|
||
listenReady <- true | ||
conn, err := ln.Accept() | ||
if err != nil { | ||
println("error accepting:", err) | ||
return | ||
} | ||
|
||
recvBuf = make([]byte, len(testDialListenData)) | ||
if _, err := io.ReadFull(conn, recvBuf); err != nil { | ||
println("error reading: ", err) | ||
return | ||
} | ||
|
||
if string(recvBuf) != string(testDialListenData) { | ||
println("error: received data does not match sent data", string(recvBuf), " != ", string(testDialListenData)) | ||
return | ||
} | ||
conn.Close() | ||
|
||
return | ||
}() | ||
|
||
<-listenReady | ||
conn, err := net.Dial("tcp4", "127.0.0.1:"+strconv.FormatInt(int64(lnPort), 10)) | ||
if err != nil { | ||
println("error dialing: ", err) | ||
return | ||
} | ||
|
||
if _, err = conn.Write(testDialListenData); err != nil { | ||
println("error writing: ", err) | ||
return | ||
} | ||
} | ||
|
||
func main() { | ||
println("test: net start") | ||
TestDialListen() | ||
println("test: net end") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
test: net start | ||
test: net end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you put in debugging code, please remove it before sending in a PR. It makes the diff bigger and more work to review.
Generally, take a look at the PR diff and see if there's any part of it that is not necessary and can be removed (such as the changes to
.gitmodules
and the signal changes that are still part of this PR).(Also, how do you know that you can just remove this panic?)