Skip to content

Commit

Permalink
add semaphore
Browse files Browse the repository at this point in the history
  • Loading branch information
JothamWong committed Apr 19, 2024
1 parent f764a46 commit 6b416e4
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 30 deletions.
97 changes: 70 additions & 27 deletions src/tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,7 @@ func (v *Vertex) Add(w Vertex) {
v := Vertex{1}
w := Vertex{2}
wg := WaitGroup{1}
wg := sync.NewWaitGroup(1);
go func() {
v.Add(w)
wg.Done()
Expand Down Expand Up @@ -880,7 +880,7 @@ func (v *Vertex) Add(w Vertex) {
v := Vertex{1};
w := Vertex{2};
wg := WaitGroup{1};
wg := sync.NewWaitGroup(1);
go func() {
Expand Down Expand Up @@ -1774,7 +1774,7 @@ x[6]; // still garbage data
testProgram(
`
var x int = 0;
wg := WaitGroup{10};
wg := sync.NewWaitGroup(3);
func goo(i int, m Mutex) {
print(i + " just started");
Expand All @@ -1787,16 +1787,16 @@ func goo(i int, m Mutex) {
wg.Done();
}
m := NewMutex();
m := sync.NewMutex();
for i := 0; i < 10; i++ {
for i := 0; i < 3; i++ {
go goo(i, m);
}
wg.Wait();
print(x);
`,
50,
15,
'"0 just started"\n' +
'"0 is locking"\n' +
'"1 just started"\n' +
Expand All @@ -1805,28 +1805,8 @@ print(x);
'"2 just started"\n' +
'"1 is incrementing"\n' +
'"2 is locking"\n' +
'"3 just started"\n' +
'"2 is incrementing"\n' +
'"3 is locking"\n' +
'"4 just started"\n' +
'"3 is incrementing"\n' +
'"4 is locking"\n' +
'"5 just started"\n' +
'"4 is incrementing"\n' +
'"5 is locking"\n' +
'"6 just started"\n' +
'"5 is incrementing"\n' +
'"6 is locking"\n' +
'"7 just started"\n' +
'"6 is incrementing"\n' +
'"7 is locking"\n' +
'"8 just started"\n' +
'"7 is incrementing"\n' +
'"8 is locking"\n' +
'"9 just started"\n' +
'"8 is incrementing"\n' +
'"9 is locking"\n' +
'"9 is incrementing"\n50',
'15',
defaultNumWords
);

Expand Down Expand Up @@ -2022,3 +2002,66 @@ for i := 0; i < 100; i++ {
}
10;
`, 10, '"Print once"', defaultNumWords);


// Test binary sync.Semaphore
testProgram(`
s := sync.NewSemaphore(1);
x := 0;
go func() {
s.Down();
yieldThread();
x = x + 1;
fmt.Println("x in Thread 1 is " + x); // this should be 1 because goroutine in T2 Blocks
s.Up();
}();
go func() {
s.Down(); // this should block
x = x + 1;
fmt.Println("x in Thread 2 is " + x); // this should be 2
s.Up();
}();
for i := 0; i < 100; i++ {
}
10;
`, 10, '"x in Thread 1 is 1"\n"x in Thread 2 is 2"', defaultNumWords);


// Test sync.Semaphore with more than 1 count
testProgram(`
s := sync.NewSemaphore(2);
x := 0;
go func() {
s.Down();
x = x + 1;
fmt.Println("x in Thread 1 is " + x); // this should be 1
}();
go func() {
s.Down();
x = x + 1;
fmt.Println("x in Thread 2 is " + x); // this should be 2 because goroutine in T1 sleeps
}();
go func() {
s.Down();
x = x + 1;
fmt.Println("x in Thread 3 is " + x); // this should be 4 because main wakes up
s.Up();
}();
x = x + 1;
s.Up();
for i := 0; i < 100; i++ {
}
10;
`, 10, '"x in Thread 1 is 1"\n"x in Thread 2 is 2"\n"x in Thread 3 is 4"', defaultNumWords);
4 changes: 2 additions & 2 deletions src/vm/oogavm-machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,11 @@ export const builtinMappings = {
},
blockThread: () => {
blockedThreadState = true;
return null;
return True;
},
yieldThread: () => {
yieldThreadState = true;
return null;
return True;
},
oogaError: () => {
throw new OogaError('Attempt to unlock locked mutex');
Expand Down
41 changes: 40 additions & 1 deletion std/ooga-std.ooga
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ func (f *format) Println(x any) {
}

// Concurrency

type Sync struct {}

type WaitGroup struct {
counter int
}

func (s *Sync) NewWaitGroup(counter int) WaitGroup {
wg := WaitGroup{counter};
return wg;
}

func (wg *WaitGroup) Add(delta int) {
wg.counter += delta
}
Expand All @@ -25,14 +33,15 @@ func (wg *WaitGroup) Done() {
func (wg *WaitGroup) Wait() {
for wg.counter > 0 {
yieldThread(); // yield to avoid wasteful loop
"YIELD";
}
}

type Mutex struct {
currentThread int
}

func NewMutex() Mutex {
func (s *Sync) NewMutex() Mutex {
m := Mutex{-1};
return m;
}
Expand Down Expand Up @@ -62,6 +71,34 @@ func (m *Mutex) Unlock() {
endAtomic();
}

type Semaphore struct {
count int
}

func (s *Sync) NewSemaphore(count int) Semaphore {
s := Semaphore{count};
return s;
}

func (s *Semaphore) Down() {
for {
startAtomic();
if (s.count > 0) {
s.count = s.count - 1;
break;
}
endAtomic();
blockThread();
}
endAtomic();
}

func (s *Semaphore) Up() {
startAtomic();
s.count = s.count + 1;
endAtomic();
}

var fmt format = format{}


Expand All @@ -79,3 +116,5 @@ func (t *Time) Sleep(duration int) {
}

var time Time = Time{};

var sync Sync = Sync{};

0 comments on commit 6b416e4

Please sign in to comment.