co-authors: Scola Davide and Maia Nicoletta
Small workshop on Inferno, Limbo and the Dis virtual machine.
Inferno is a new operative system developped for creation and support of network systems and distribuited services.
There are three fundamental programming principles: all resources are files in a hierarchic file system, the network is a unic namespace like a file system hierarchic, it uses Styx that is a standard protocol of comunication for local and remote resources.
Limbo is the programming language for the Inferno OS.
The language is Object Based, you can compile it or interpret it with the Dis virtual machine (like Java virtual machine with a JIT compiler).
Limbo has a native support for: array, string, int, float, tuple (like record), channel (linda-like), and other...
The Limbo's channels are used to comunicate with other processes or with thread.
The Dis virtual machine is an environment for Limbo programs and it has important features: CISC architecture, memory-to-memory, many high level types, just in time compiler, ecc...
In the end of presentation there is a comparison between Dis, Java VM and C# .Net VM.
LinuxDay 2004 - Linux - Storia e caratteristiche vincenti - slides
Inferno Limbo Italian
1. Inferno, Limbo e la Dis Virtual Machine Minetti Scola Maia Alberto Davide Nicoletta
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22. Limbo: chan particolarità L’operatore <- può prendere come argomento un array di canali. Limbo fornisce l’ alt statement, la sua struttura è simile a quella di un case . a: array [2] of chan of string; a[0] = chan of string; a[1] = chan of string; . . . ( i , s) := <- a; # s has now the string from channel a[ i ] array di chan in Limbo outchan := chan of string; inchan := chan of int; ciclo: while(){ alt { i := <-inchan => if(i==0) break ciclo; sys->print("Received %d", i); outchan <- = "message" => sys->print("Sent the message"); } } alt in Limbo
23. Limbo: alt statement Utilizzando * il programma non viene bloccato, se nessun canale è ready viene eseguito lo statement corrispondente a * . Lo statement alt testa la possibilità di leggere o scrivere (dipende dall’operatore) su ogni canale al suo interno, se nessun canale è pronto il programma si blocca e aspetta che un canale sia pronto, poi viene scelto casualmente un canale che è ready e il controllo viene associato al suo statement. Questo statement è simile a select() e a poll() in Unix. alt { (a, b) = <- ch1 => …; (a, b, c) = <- ch2 => …; k = <- ch3 => …; * => …; } alt in Limbo
24.
25.
26.
27. Limbo: modulo di esempio implement Tennis; include "sys.m"; sys: Sys; include "rand.m"; rand: Rand; include "draw.m"; Tennis: module { init: fn (nil: ref Draw->Context, argv: list of string); }; init(nil: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; rand = load Rand Rand->PATH; field:= chan of int; gpid := sys->pctl(Sys->NEWPGRP, nil); rand->init( sys->millisec() ); spawn opponent(field, gpid); while( 1 ) { serve("Nadal", gpid, field); receive("Nadal", gpid, field); } } serve(who: string, gpid: int, field: chan of int) { ball := rand->rand(100); sys->print("%s[%d]: servo %d", who, gpid, ball); field <-= ball; } receive(who: string, gpid: int, field: chan of int) { ball := <-field; sys->print("%s[%d] ricevo %d ", who, gpid, ball); if( ball > 80 ) { sys->print("HO PERSO!"); killpgroup(gpid); } sys->print(""); } killpgroup(gpid: int) { sys->fprint( sys->open("/prog/" + string gpid + "/ctl", Sys->OWRITE), “killgrp"); exit; } opponent(field: chan of int, gpid: int) { while( 1 ) { receive("Federer", gpid, field); serve("Federer", gpid, field); } } Due thread che giocano a tennis in Limbo
28. Limbo: modulo Monitor # Mon.m – Interfaccia al modulo Monitor Mon: module { PATH: con "/dis/lib/Mon.dis"; Monitor: adt { create: fn(): Monitor; lock: fn(m: self Monitor); unlock: fn(m: self Monitor); ch: chan of int; }; }; # Mon.b – Implementazione del Monitor implement Mon; include "Mon.m"; Monitor.create(): Monitor { m := Monitor(chan of int); spawn lockproc(m.ch); return m; } Monitor.lock(m: self Monitor) { m.ch <- = 0; } Monitor.unlock(m: self Monitor) { <- m.ch; } lockproc(ch: chan of int) { for (;;) { <- ch; # wait for someone to lock ch <- = 0; # wait for someone to unlock } } Implementazione di un Monitor per la concorrenza in Limbo
29.
30.
31. Limbo: approfondimento ref Non fa quello che ci si aspetta A: adt {n: int;}; f(a: ref A){ a.n = 100; } init(){ a: A; a.n=50; f(ref a); sys->print("%d", a.n); } Questo codice non stampa “100”! Equivale a questo codice C: a = malloc(sizeof(A)); b = malloc(sizeof(A)); memcpy(b, a, sizeof(A)); f(b); Questo codice è giusto A: adt {n: int;}; f(a: ref A){ a.n = 100; } init(){ a:= ref A; a.n = 50; b:= a; f(b); sys->print("%d", a.n); } Questo codice stampa “100”! Implementazione di una semplicissima bash in Limbo
32.
33.
34. Limbo: Codice e sintassi importazione di moduli Definizione dell’interfaccia del modulo Hello Contesto grafico command-line arguments Impl del metodo Per convenzione ogni dichiarazione di modulo include un Pathname costante che punta al codice per il modulo implement Hello; include "sys.m"; sys: Sys; include "draw.m"; Hello: module { init: fn(ctxt: ref Draw->Context, argv: list of string); }; init(ctxt: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; sys->print("hello, world"); } File .b => “Hello World” Limbo di esempio
35. Limbo: Hello World grafico implement Hello2; include "sys.m"; sys: Sys; include "draw.m"; draw: Draw; include "tk.m"; tk: Tk; Hello2: module{ init: fn(ctxt: ref Draw->Context, argv: list of string);}; init(ctxt: ref Draw->Context, argv: list of string){ sys = load Sys Sys->PATH; draw = load Draw Draw->PATH; tk = load Tk Tk->PATH; t := tk->toplevel(ctxt.screen, ""); tk->cmd(t, "button .b -text {hello, world}"); tk->cmd(t, "pack .b"); tk->cmd(t, "update"); sys->sleep(10000); # wait 10 seconds} File .b => “Hello World” grafico Limbo
36.
37.
38.
39.
40. Esempio: memory-to-memory PC = 17 old_WP = 0x03 FP = 0x95 MP = 0xB0 0x1C 0x1B 0x1A 0x19 0x18 0x17 0x16 0x15 0x14 0x13 0x12 0x11 0x10 CPU 0x1C WP: PC = 86 old_WP = 0x1C FP = 0x88 MP = 0xB0 0x18 PC = 95 PC = 18 ... 17: a:= function(x, y, z); 18: ... ... 85: function(x, y, z: int): Point { 86: if(...) ... ... 95: return p; } Adt in Limbo WP
41.
42.
43.
44.
45.
46. Dis: dimensione degli operandi La dimensione e il tipo degli operandi sono specificati dall’ultimo carattere dell’istruzione. carattere dimensione W Word (32 bit) B Byte (8 bit) F Float (64 bit) L LongInt (64 bit) P puntatore addx - Add Syntax: addb src1, src2, dst addf src1, src2, dst addw src1, src2, dst addl src1, src2, dst Function: dst = src1 + src2 Istruzione ADD in Dis
47.
48.
49.
50.
51.
52.
53. Bytecode RB vs Bytecode SB High-level linguage: c = a + b; d = a + 4; e = b * 3; 5 variabili e 3 statement REG-BASED 1:getvar R1, "a" 2:getvar R2, "b" 3:getvar R3, "c" 4:getvar R4, "d" 5:getvar R5, "e" 6:add R3, R1, R2 7:add R4, R1, 4 8:mul R5, R2, 3 8 ops, 9 parameters 11:add 12:push 'd' 13:storevar 14:push 'b' 15:getvar 16:push 3 17:multiply 18:push 'e' 19:storevar BYTECODE register-based e BYTECODE stack-based STACK-BASED 1:push 'a' 2:getvar 3:push b' 4:getvar 5:add 6:push 'c' 7:storevar 8:push 'a' 9:getvar 10:push 4 19 ops, 9 parameters
54.
55. Dis: Elementi della symbol table Header File table PC table Adt table Fn table Data table