Skip to content

Commit

Permalink
stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
renan061 committed May 21, 2024
1 parent c8ae071 commit c9ac8d1
Show file tree
Hide file tree
Showing 26 changed files with 1,448 additions and 637 deletions.
44 changes: 27 additions & 17 deletions cmd/cartesi-machine/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,34 @@ func main() {
var machine *emulator.Machine
defer machine.Delete()
var mgr *emulator.RemoteMachineManager
defer mgr.Free()
defer mgr.Delete()
var err error
runtimeConfig := &emulator.MachineRuntimeConfig{}

// Parse command line arguments
loadDir := flag.String("load", "", "load machine previously stored in <directory>")
storeDir := flag.String("store", "", "store machine to <directory>, where \"%h\" is substituted by the state hash in the directory name")
remoteAddress := flag.String("remote-address", "", "use a remote cartesi machine listening to <address> instead of running a local cartesi machine")
remoteShutdown := flag.Bool("remote-shutdown", false, "shutdown the remote cartesi machine after the execution")
noRemoteCreate := flag.Bool("no-remote-create", false, "use existing cartesi machine in the remote server instead of creating a new one")
noRemoteDestroy := flag.Bool("no-remote-destroy", false, "do not destroy the cartesi machine in the remote server after the execution")
ramImage := flag.String("ram-image", "", "name of file containing RAM image")
dtbImage := flag.String("dtb-image", "", "name of file containing DTB image (default: auto generated flattened device tree)")
maxMcycle := flag.Uint64("max-mcycle", math.MaxUint64, "stop at a given mcycle")
initialHash := flag.Bool("initial-hash", false, "print initial state hash before running machine")
finalHash := flag.Bool("final-hash", false, "print final state hash when done")
commandLine := flag.String("command", "", "command to run in the machine")
storeDir := flag.String("store", "",
"store machine to <directory>, where \"%h\" is substituted by the state hash in the directory name")
remoteAddress := flag.String("remote-address", "",
"use a remote cartesi machine listening to <address> instead of running a local cartesi machine")
remoteShutdown := flag.Bool("remote-shutdown", false,
"shutdown the remote cartesi machine after the execution")
noRemoteCreate := flag.Bool("no-remote-create", false,
"use existing cartesi machine in the remote server instead of creating a new one")
noRemoteDestroy := flag.Bool("no-remote-destroy", false,
"do not destroy the cartesi machine in the remote server after the execution")
ramImage := flag.String("ram-image", "",
"name of file containing RAM image")
dtbImage := flag.String("dtb-image", "",
"name of file containing DTB image (default: auto generated flattened device tree)")
maxMcycle := flag.Uint64("max-mcycle", math.MaxUint64,
"stop at a given mcycle")
initialHash := flag.Bool("initial-hash", false,
"print initial state hash before running machine")
finalHash := flag.Bool("final-hash", false,
"print final state hash when done")
commandLine := flag.String("command", "",
"command to run in the machine")
flag.Parse()

// Connect to remote server and load/get machine
Expand Down Expand Up @@ -124,12 +135,12 @@ func main() {

// Print initial hash
if initialHash != nil && *initialHash {
var hash *emulator.MerkleTreeHash
if hash, err = machine.GetRootHash(); err != nil {
if hash, err := machine.GetRootHash(); err != nil {
fmt.Fprintln(os.Stderr, "****** Error getting root hash: ", err)
os.Exit(1)
} else {
fmt.Println("Initial hash: ", hash.String())
}
fmt.Println("Initial hash: ", hash.String())
}

// Run machine
Expand Down Expand Up @@ -160,8 +171,7 @@ func main() {

// Print final hash
if finalHash != nil && *finalHash {
var hash *emulator.MerkleTreeHash
if hash, err = machine.GetRootHash(); err == nil {
if hash, err := machine.GetRootHash(); err == nil {
fmt.Println("Final hash: ", hash.String())
}
}
Expand Down
35 changes: 35 additions & 0 deletions internal/node/machineadvancer/advancer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package machineadvancer

import "github.com/cartesi/rollups-node/internal/node/nodemachine"

type Input = []byte
type Output = []byte
type Report = []byte
type Hash = [32]byte

func GetInputs() []Input {
return []Input{}
}

func Store(outputs []Output, reports []Report, outputsHash Hash, machineHash Hash) error {
return nil
}

func StartAdvanceServer(machine *nodemachine.NodeMachine) {
for {
for _, input := range GetInputs() {
outputs, reports, outputsHash, machineHash, err := machine.Advance(input)
if err != nil {
panic("TODO")
}

err = Store(outputs, reports, outputsHash, machineHash)
if err != nil {
panic("TODO")
}
}
}
}
108 changes: 108 additions & 0 deletions internal/node/nodemachine/machine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package nodemachine

import (
"context"

"github.com/cartesi/rollups-node/internal/node/nodemachine/pmutex"
"github.com/cartesi/rollups-node/pkg/model"
"github.com/cartesi/rollups-node/pkg/rollupsmachine"

"golang.org/x/sync/semaphore"
)

type NodeMachine struct {
*rollupsmachine.RollupsMachine

// Ensures advance/inspect mutual exclusion when accessing the inner RollupsMachine.
// Advances have a higher priority than Inspects to acquire the lock.
mutex *pmutex.PMutex

// Controls how many inspects can be concurrently active.
inspects *semaphore.Weighted
}

func New(machine *rollupsmachine.RollupsMachine, maxConcurrentInspects int8) *NodeMachine {
return &NodeMachine{
RollupsMachine: machine,
mutex: pmutex.New(),
inspects: semaphore.NewWeighted(int64(maxConcurrentInspects)),
}
}

func (machine *NodeMachine) Advance(input []byte) (
outputs []rollupsmachine.Output,
reports []rollupsmachine.Report,
outputsHash model.Hash,
machineHash model.Hash,
err error) {

var fork *rollupsmachine.RollupsMachine

{ // Forks the machine.
machine.mutex.HLock()
defer machine.mutex.Unlock()
fork, err = machine.Fork()
if err != nil {
return outputs, reports, outputsHash, machineHash, err
}
}

// Sends the advance-state request.
outputs, reports, outputsHash, err = fork.Advance(input)
if err != nil {
return outputs, reports, outputsHash, machineHash, err
}

// Gets the post-advance machine hash.
machineHash, err = fork.Hash()
if err != nil {
return outputs, reports, outputsHash, machineHash, err
}

{ // Destroys the old machine and updates the current one.
machine.mutex.HLock()
defer machine.mutex.Unlock()
err = machine.Destroy()
if err != nil {
return outputs, reports, outputsHash, machineHash, err
}
machine.RollupsMachine = fork
}

return outputs, reports, outputsHash, machineHash, err
}

func (machine *NodeMachine) Inspect(ctx context.Context, query []byte) (
[]rollupsmachine.Report,
error) {

// Controls how many inspects can be concurrently active.
err := machine.inspects.Acquire(ctx, 1)
if err != nil {
return nil, err
}
defer machine.inspects.Release(1)

// Forks the machine.
var forkedMachine *rollupsmachine.RollupsMachine
{
machine.mutex.LLock()
defer machine.mutex.Unlock()
forkedMachine, err = machine.Fork()
if err != nil {
return nil, err
}
}

// Sends the inspect-state request.
reports, err := forkedMachine.Inspect(query)
if err != nil {
return nil, err
}

// Destroys the forked machine and returns the reports.
return reports, forkedMachine.Destroy()
}
56 changes: 56 additions & 0 deletions internal/node/nodemachine/pmutex/pmutex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package pmutex

import (
"sync"
"sync/atomic"
)

// A PMutex is a mutual exclusion lock with priority capabilities.
// A call to HLock always acquires the mutex before LLock.
type PMutex struct {
// Main mutex.
mutex *sync.Mutex

// Condition variable for the waiting low-priority threads.
waitingLow *sync.Cond

// Quantity of high-priority threads waiting to acquire the lock.
waitingHigh *atomic.Int32
}

// New creates a new PMutex.
func New() *PMutex {
mutex := &sync.Mutex{}
return &PMutex{
mutex: mutex,
waitingLow: sync.NewCond(mutex),
waitingHigh: &atomic.Int32{},
}
}

// HLock acquires the mutex for the high-priority threads.
func (lock *PMutex) HLock() {
lock.waitingHigh.Add(1)
lock.mutex.Lock()
lock.waitingHigh.Add(-1)
}

// LLock acquires the mutex for the low-priority threads.
// It waits until there are no high-priority threads trying to acquire the lock.
func (lock *PMutex) LLock() {
lock.mutex.Lock()
for lock.waitingHigh.Load() != 0 {
// NOTE: a cond.Wait() releases the lock uppon being called
// and tries to acquire it after being awakened.
lock.waitingLow.Wait()
}
}

// Unlock releases the mutex for both types of threads.
func (lock *PMutex) Unlock() {
lock.waitingLow.Broadcast()
lock.mutex.Unlock()
}
6 changes: 4 additions & 2 deletions internal/services/server-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"strings"
"syscall"
"time"

"github.com/cartesi/rollups-node/internal/linewriter"
)

// ServerManager is a variation of CommandService used to manually stop
Expand Down Expand Up @@ -48,8 +50,8 @@ func (s ServerManager) Start(ctx context.Context, ready chan<- struct{}) error {
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
} else {
cmd.Stderr = newLineWriter(commandLogger{s.Name})
cmd.Stdout = newLineWriter(commandLogger{s.Name})
cmd.Stderr = linewriter.New(commandLogger{s.Name})
cmd.Stdout = linewriter.New(commandLogger{s.Name})
}
// Without a delay, cmd.Wait() will block forever waiting for the I/O pipes
// to be closed
Expand Down
45 changes: 30 additions & 15 deletions pkg/emulator/emulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@ const (
BreakReasonReachedTargetMcycle BreakReason = C.CM_BREAK_REASON_REACHED_TARGET_MCYCLE
)

func (reason BreakReason) String() (s string) {
switch reason {
case BreakReasonFailed:
s = "failed"
case BreakReasonHalted:
s = "halted"
case BreakReasonYieldedManually:
s = "yielded manually"
case BreakReasonYieldedAutomatically:
s = "yielded automatically"
case BreakReasonYieldedSoftly:
s = "yielded softly"
case BreakReasonReachedTargetMcycle:
s = "reached target mcycle"
default:
return "invalid break reason"
}
return "break reason: " + s

}

type ProcessorCSR int32

const (
Expand Down Expand Up @@ -226,10 +247,14 @@ type HtifConfig struct {
YieldAutomatic bool
}

type CmioBufferConfig struct {
Shared bool
ImageFilename string
}

type CmioConfig struct {
HsaValue bool
RxBuffer MemoryRangeConfig
TxBuffer MemoryRangeConfig
RxBuffer CmioBufferConfig
TxBuffer CmioBufferConfig
}

type UarchRamConfig struct {
Expand Down Expand Up @@ -433,13 +458,8 @@ func (config *MachineConfig) makeCRef() (ref *ourMachineConfigCRef) {

cCmio := &ref.cref.cmio
cmio := &config.Cmio
cCmio.has_value = (C.bool)(cmio.HsaValue)
cCmio.rx_buffer.start = (C.uint64_t)(cmio.RxBuffer.Start)
cCmio.rx_buffer.length = (C.uint64_t)(cmio.RxBuffer.Length)
cCmio.rx_buffer.shared = (C.bool)(cmio.RxBuffer.Shared)
cCmio.rx_buffer.image_filename = makeCString(&cmio.RxBuffer.ImageFilename)
cCmio.tx_buffer.start = (C.uint64_t)(cmio.TxBuffer.Start)
cCmio.tx_buffer.length = (C.uint64_t)(cmio.TxBuffer.Length)
cCmio.tx_buffer.shared = (C.bool)(cmio.TxBuffer.Shared)
cCmio.tx_buffer.image_filename = makeCString(&cmio.TxBuffer.ImageFilename)

Expand Down Expand Up @@ -578,16 +598,11 @@ func (configCRef *theirMachineConfigCRef) makeGoRef() (cfg *MachineConfig) {

// CMIO
cmio := &cfg.Cmio
cmio.HsaValue = (bool)(c.cmio.has_value)
cmio.RxBuffer = MemoryRangeConfig{
Start: (uint64)(c.cmio.rx_buffer.start),
Length: (uint64)(c.cmio.rx_buffer.length),
cmio.RxBuffer = CmioBufferConfig{
Shared: (bool)(c.cmio.rx_buffer.shared),
ImageFilename: C.GoString(c.cmio.rx_buffer.image_filename),
}
cmio.TxBuffer = MemoryRangeConfig{
Start: (uint64)(c.cmio.tx_buffer.start),
Length: (uint64)(c.cmio.tx_buffer.length),
cmio.TxBuffer = CmioBufferConfig{
Shared: (bool)(c.cmio.tx_buffer.shared),
ImageFilename: C.GoString(c.cmio.tx_buffer.image_filename),
}
Expand Down
Loading

0 comments on commit c9ac8d1

Please sign in to comment.