aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/runtime/chan.go
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-06-08 16:12:30 +0200
committerRon Evans <[email protected]>2019-06-12 18:26:52 +0200
commit8890a0f3c845154d54d1f41a00daf9f626865aa0 (patch)
tree9363a0c26d98d9bd343649d2977f34f6dd555c8d /src/runtime/chan.go
parent5be412dabea213d7279c738ea2791fc52bf885fd (diff)
downloadtinygo-8890a0f3c845154d54d1f41a00daf9f626865aa0.tar.gz
tinygo-8890a0f3c845154d54d1f41a00daf9f626865aa0.zip
compiler,runtime: store channel size in the channel itself
This may have a small effect on code size sometimes, but will simplify the implementation of the select statement.
Diffstat (limited to 'src/runtime/chan.go')
-rw-r--r--src/runtime/chan.go19
1 files changed, 10 insertions, 9 deletions
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
index 60c690507..d9851df4c 100644
--- a/src/runtime/chan.go
+++ b/src/runtime/chan.go
@@ -28,8 +28,9 @@ import (
)
type channel struct {
- state uint8
- blocked *coroutine
+ elementSize uint16 // the size of one value in this channel
+ state uint8
+ blocked *coroutine
}
const (
@@ -45,7 +46,7 @@ func deadlockStub()
// complete immediately (there is a goroutine waiting for a value), it sends the
// value and re-activates both goroutines. If not, it sets itself as waiting on
// a value.
-func chanSend(sender *coroutine, ch *channel, value unsafe.Pointer, size uintptr) {
+func chanSend(sender *coroutine, ch *channel, value unsafe.Pointer) {
if ch == nil {
// A nil channel blocks forever. Do not scheduler this goroutine again.
return
@@ -58,7 +59,7 @@ func chanSend(sender *coroutine, ch *channel, value unsafe.Pointer, size uintptr
case chanStateRecv:
receiver := ch.blocked
receiverPromise := receiver.promise()
- memcpy(receiverPromise.ptr, value, size)
+ memcpy(receiverPromise.ptr, value, uintptr(ch.elementSize))
receiverPromise.data = 1 // commaOk = true
ch.blocked = receiverPromise.next
receiverPromise.next = nil
@@ -80,7 +81,7 @@ func chanSend(sender *coroutine, ch *channel, value unsafe.Pointer, size uintptr
// sender, it receives the value immediately and re-activates both coroutines.
// If not, it sets itself as available for receiving. If the channel is closed,
// it immediately activates itself with a zero value as the result.
-func chanRecv(receiver *coroutine, ch *channel, value unsafe.Pointer, size uintptr) {
+func chanRecv(receiver *coroutine, ch *channel, value unsafe.Pointer) {
if ch == nil {
// A nil channel blocks forever. Do not scheduler this goroutine again.
return
@@ -89,7 +90,7 @@ func chanRecv(receiver *coroutine, ch *channel, value unsafe.Pointer, size uintp
case chanStateSend:
sender := ch.blocked
senderPromise := sender.promise()
- memcpy(value, senderPromise.ptr, size)
+ memcpy(value, senderPromise.ptr, uintptr(ch.elementSize))
receiver.promise().data = 1 // commaOk = true
ch.blocked = senderPromise.next
senderPromise.next = nil
@@ -103,7 +104,7 @@ func chanRecv(receiver *coroutine, ch *channel, value unsafe.Pointer, size uintp
ch.state = chanStateRecv
ch.blocked = receiver
case chanStateClosed:
- memzero(value, size)
+ memzero(value, uintptr(ch.elementSize))
receiver.promise().data = 0 // commaOk = false
activateTask(receiver)
case chanStateRecv:
@@ -115,7 +116,7 @@ func chanRecv(receiver *coroutine, ch *channel, value unsafe.Pointer, size uintp
// chanClose closes the given channel. If this channel has a receiver or is
// empty, it closes the channel. Else, it panics.
-func chanClose(ch *channel, size uintptr) {
+func chanClose(ch *channel) {
if ch == nil {
// Not allowed by the language spec.
runtimePanic("close of nil channel")
@@ -133,7 +134,7 @@ func chanClose(ch *channel, size uintptr) {
case chanStateRecv:
// The receiver must be re-activated with a zero value.
receiverPromise := ch.blocked.promise()
- memzero(receiverPromise.ptr, size)
+ memzero(receiverPromise.ptr, uintptr(ch.elementSize))
receiverPromise.data = 0 // commaOk = false
activateTask(ch.blocked)
ch.state = chanStateClosed