Skip to content

Commit

Permalink
fix: reset goroutine id on each program execution
Browse files Browse the repository at this point in the history
Previously, ids are generated using a static `Counter` held by
the `GoRoutine` class which does not reset when a new program is being
ran. Now we shift the task of generating routine ids to the `Scheduler`
and have it maintain a instance level `Counter`.
  • Loading branch information
shenyih0ng committed Apr 7, 2024
1 parent f66271e commit b21a21f
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 19 deletions.
14 changes: 5 additions & 9 deletions src/go-slang/ece.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { Context as SlangContext } from '..'
import { Stack } from '../cse-machine/utils'
import { Value } from '../types'
import { Context, GoRoutine } from './goroutine'
import { Context } from './goroutine'
import { AstMap } from './lib/astMap'
import { Environment } from './lib/env'
import { Heap, HeapAddress } from './lib/heap'
import { PREDECLARED_FUNCTIONS, PREDECLARED_IDENTIFIERS } from './lib/predeclared'
import { Scheduler } from './scheduler'
import { BuiltinOp, CallExpression, Instruction, NodeType, SourceFile } from './types'

function initMainGoRoutine(
program: SourceFile,
slangContext: SlangContext,
scheduler: Scheduler
): GoRoutine {
function initMainGoRoutineCtx(program: SourceFile, slangContext: SlangContext): Context {
const C = new Stack<Instruction | HeapAddress>()
const S = new Stack<any>()
const E = new Environment({ ...PREDECLARED_IDENTIFIERS })
Expand Down Expand Up @@ -45,14 +41,14 @@ function initMainGoRoutine(
}
C.pushR(H.alloc(program), H.alloc(CALL_MAIN))

return new GoRoutine({ C, S, E, B, H, A } as Context, scheduler, true)
return { C, S, E, B, H, A } as Context
}

export function evaluate(program: SourceFile, slangContext: SlangContext): Value {
const scheduler = new Scheduler(slangContext)
const mainR = initMainGoRoutine(program, slangContext, scheduler)
const mainRoutineCtx = initMainGoRoutineCtx(program, slangContext)

scheduler.schedule(mainR)
scheduler.spawn(mainRoutineCtx, true)
scheduler.run()

return 'Program exited'
Expand Down
10 changes: 4 additions & 6 deletions src/go-slang/goroutine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { AstMap } from './lib/astMap'
import { evaluateBinaryOp } from './lib/binaryOp'
import { Environment } from './lib/env'
import { Heap, HeapAddress } from './lib/heap'
import { Counter, Result, isAny } from './lib/utils'
import { Result, isAny } from './lib/utils'
import {
AssignOp,
Assignment,
Expand Down Expand Up @@ -83,8 +83,6 @@ export enum GoRoutineState {
}

export class GoRoutine {
static idCounter: Counter = new Counter()

private id: number
private context: Context
private scheduler: Scheduler
Expand All @@ -96,8 +94,8 @@ export class GoRoutine {
public state: GoRoutineState
public isMain: boolean

constructor(context: Context, scheduler: Scheduler, isMain: boolean = false) {
this.id = GoRoutine.idCounter.next()
constructor(id: number, context: Context, scheduler: Scheduler, isMain: boolean = false) {
this.id = id
this.state = GoRoutineState.Running
this.context = context
this.scheduler = scheduler
Expand Down Expand Up @@ -339,7 +337,7 @@ const Interpreter: {
.setId(envId)
.extend(Object.fromEntries(zip(paramNames, values)))

return void sched.schedule(new GoRoutine({ C: _C, S: _S, E: _E, B, H, A }, sched))
return void sched.spawn({ C: _C, S: _S, E: _E, B, H, A } as Context)
},

ChanRecvOp: (_inst, { C, S, H }, _sched, routineId: number) => {
Expand Down
14 changes: 10 additions & 4 deletions src/go-slang/scheduler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Context as SlangContext } from '..'
import { GoRoutine, GoRoutineState } from './goroutine'
import { GoRoutine, GoRoutineState, Context } from './goroutine'
import { RuntimeSourceError } from '../errors/runtimeSourceError'
import { benchmark } from './lib/utils'
import { Counter, benchmark } from './lib/utils'
import { DeadLockError } from './error'

type TimeQuanta = number
Expand All @@ -10,9 +10,11 @@ export class Scheduler {
static MIN_TIME_QUANTA = 10
static MAX_TIME_QUANTA = 20

// counter to generate unique routine ids
private rIdCounter = new Counter()

private slangContext: SlangContext
private routines: Array<[GoRoutine, TimeQuanta]> = []

constructor(slangContext: SlangContext) {
this.slangContext = slangContext
}
Expand All @@ -22,10 +24,14 @@ export class Scheduler {
return Math.floor(Math.random() * (maxTQ - minTQ) + minTQ)
}

public schedule(routine: GoRoutine): void {
private schedule(routine: GoRoutine): void {
this.routines.push([routine, Scheduler.randTimeQuanta()])
}

public spawn(goRoutineCtx: Context, isMain: boolean = false) {
this.schedule(new GoRoutine(this.rIdCounter.next(), goRoutineCtx, this, isMain))
}

@benchmark('Scheduler::run')
public run(): void {
// the number of consecutive time quanta where all routines made no progress
Expand Down

0 comments on commit b21a21f

Please sign in to comment.