ownership types for safe programming: preventing data races and deadlocks

54
Ownership Types for Safe Ownership Types for Safe Programming: Programming: Preventing Data Races and Preventing Data Races and Deadlocks Deadlocks Chandrasekhar Boyapati Chandrasekhar Boyapati Robert Lee Robert Lee Martin Rinard Martin Rinard Laboratory for Computer Science Laboratory for Computer Science Massachusetts Institute of Massachusetts Institute of Technology Technology {chandra, rhlee, rinard}@lcs.mit.edu {chandra, rhlee, rinard}@lcs.mit.edu

Upload: roanna-cox

Post on 30-Dec-2015

11 views

Category:

Documents


0 download

DESCRIPTION

Ownership Types for Safe Programming: Preventing Data Races and Deadlocks. Laboratory for Computer Science Massachusetts Institute of Technology {chandra, rhlee, rinard}@lcs.mit.edu. Chandrasekhar Boyapati Robert Lee Martin Rinard. Data Races in Multithreaded Programs. - PowerPoint PPT Presentation

TRANSCRIPT

Ownership Types for Safe Programming:Ownership Types for Safe Programming:Preventing Data Races and DeadlocksPreventing Data Races and Deadlocks

Chandrasekhar BoyapatiChandrasekhar BoyapatiRobert LeeRobert Lee

Martin RinardMartin Rinard

Laboratory for Computer ScienceLaboratory for Computer ScienceMassachusetts Institute of TechnologyMassachusetts Institute of Technology

{chandra, rhlee, rinard}@lcs.mit.edu{chandra, rhlee, rinard}@lcs.mit.edu

Thread 1:Thread 1:

x = x + 1; x = x + 1;

Thread 2:Thread 2:

x = x + 2; x = x + 2;

Two threads access same dataTwo threads access same data At least one access is a writeAt least one access is a write No synchronization to separate accessesNo synchronization to separate accesses

Data Races in Multithreaded ProgramsData Races in Multithreaded Programs

Avoiding Data RacesAvoiding Data Races

Thread 1:Thread 1:

x = x + 1; x = x + 1;

Thread 2:Thread 2:

x = x + 2; x = x + 2;

Avoiding Data RacesAvoiding Data Races

Associate locks with shared mutable dataAssociate locks with shared mutable data Acquire lock before data accessAcquire lock before data access Release lock after data accessRelease lock after data access

Thread 1:Thread 1:

lock(l);lock(l);

x = x + 1; x = x + 1;

unlock(l);unlock(l);

Thread 2:Thread 2:

lock(l); lock(l);

x = x + 2; x = x + 2;

unlock(l);unlock(l);

Thread 1Thread 1

Thread 2Thread 2

Thread nThread n

……

Lock 1Lock 1 Lock nLock n

Lock 2Lock 2 Lock 3Lock 3

Cycle of the formCycle of the form Thread 1 holds Lock 1, waits for Lock 2 Thread 1 holds Lock 1, waits for Lock 2 Thread 2 holds Lock 2, waits for Lock 3 …Thread 2 holds Lock 2, waits for Lock 3 … Thread n holds Lock n, waits for Lock 1Thread n holds Lock n, waits for Lock 1

Deadlocks in Multithreaded ProgramsDeadlocks in Multithreaded Programs

Avoiding DeadlocksAvoiding Deadlocks

Thread 1Thread 1

Thread 2Thread 2

Thread nThread n

……

Lock 1Lock 1 Lock nLock n

Lock 2Lock 2 Lock 3Lock 3

Avoiding DeadlocksAvoiding Deadlocks

Thread 1Thread 1

Thread 2Thread 2

Thread nThread n

……

Lock 1Lock 1 Lock nLock n

Lock 2Lock 2 Lock 3Lock 3

Associate a partial order among locksAssociate a partial order among locks Acquire locks in orderAcquire locks in order

~~~~

Problem With Current PracticeProblem With Current Practice

Locking discipline is not enforcedLocking discipline is not enforced

Inadvertent programming errorsInadvertent programming errors Can cause data races and deadlocksCan cause data races and deadlocks

Consequences can be severeConsequences can be severe Non-deterministic, timing dependent bugsNon-deterministic, timing dependent bugs Difficult to detect, reproduce, eliminateDifficult to detect, reproduce, eliminate

Our SolutionOur Solution

Static type systemStatic type system Prevents both data races and deadlocks Prevents both data races and deadlocks

Our SolutionOur Solution

Static type systemStatic type system Prevents both data races and deadlocks Prevents both data races and deadlocks

Programmers specifyProgrammers specify How each object is protected from racesHow each object is protected from races Partial order among locksPartial order among locks

Type checker statically verifiesType checker statically verifies Objects are used only as specifiedObjects are used only as specified Locks are acquired in orderLocks are acquired in order

Talk OutlineTalk Outline

MotivationMotivation Type systemType system

Preventing data racesPreventing data races Preventing deadlocksPreventing deadlocks

ExperienceExperience Related workRelated work ConclusionsConclusions

Preventing Data RacesPreventing Data Races

Programmers specify for every objectProgrammers specify for every object

Lock protecting the object, orLock protecting the object, or

That the object needs no locks becauseThat the object needs no locks because Object is immutable Object is immutable Object is thread-localObject is thread-local Object has a unique pointerObject has a unique pointer

Preventing DeadlocksPreventing Deadlocks Programmers specify lock ordering usingProgrammers specify lock ordering using

Static lock levelsStatic lock levels Recursive data structuresRecursive data structures

Mutable treesMutable trees Monotonic DAGsMonotonic DAGs

Runtime orderingRuntime ordering

Type checker statically verifiesType checker statically verifies Locks are acquired in descending orderLocks are acquired in descending order Specified order is a partial orderSpecified order is a partial order

Lock Level Based Partial OrdersLock Level Based Partial Orders

Lock levels are partially orderedLock levels are partially ordered Locks belong to lock levelsLocks belong to lock levels Threads must acquire locks in descending Threads must acquire locks in descending

order of lock levelsorder of lock levels

Lock Level Based Partial OrdersLock Level Based Partial Orders

class CombinedAccount {class CombinedAccount {

final Account savingsAccount = new Account();final Account savingsAccount = new Account();

final Accountfinal Account checkingAccount = new Account();checkingAccount = new Account();

int balance() {int balance() {

synchronized (savingsAccount) { synchronized (savingsAccount) {

synchronized (checkingAccount) {synchronized (checkingAccount) {

return savingsAccount.balance + checkingAccount.balance; return savingsAccount.balance + checkingAccount.balance;

}}}}}}

}}

class CombinedAccountclass CombinedAccount {{

LockLevel savingsLevel;LockLevel savingsLevel;

LockLevel checkingLevel < savingsLevel;LockLevel checkingLevel < savingsLevel;

final Accountfinal Accountself : savingsLevelself : savingsLevel savingsAccount = new Account(); savingsAccount = new Account();

final Accountfinal Accountself : checkingLevelself : checkingLevel checkingAccount = new Account(); checkingAccount = new Account();

int balance() int balance() locks (savingsLevel) locks (savingsLevel) {{

synchronized (savingsAccount) { synchronized (savingsAccount) {

synchronized (checkingAccount) {synchronized (checkingAccount) {

return savingsAccount.balance + checkingAccount.balance; return savingsAccount.balance + checkingAccount.balance;

}}}}}}

}}

Lock Level Based Partial OrdersLock Level Based Partial Orders

class CombinedAccountclass CombinedAccount {{

LockLevel savingsLevel;LockLevel savingsLevel;

LockLevel checkingLevel < savingsLevel;LockLevel checkingLevel < savingsLevel;

final Accountfinal Accountself : savingsLevelself : savingsLevel savingsAccount = new Account(); savingsAccount = new Account();

final Accountfinal Accountself : checkingLevelself : checkingLevel checkingAccount = new Account(); checkingAccount = new Account();

int balance() int balance() locks (savingsLevel) locks (savingsLevel) {{

synchronized (savingsAccount) { synchronized (savingsAccount) {

synchronized (checkingAccount) {synchronized (checkingAccount) {

return savingsAccount.balance + checkingAccount.balance; return savingsAccount.balance + checkingAccount.balance;

}}}}}}

}}

checkingLevel < savingsLevelcheckingLevel < savingsLevel

Lock Level Based Partial OrdersLock Level Based Partial Orders

class CombinedAccountclass CombinedAccount {{

LockLevel savingsLevel;LockLevel savingsLevel;

LockLevel checkingLevel < savingsLevel;LockLevel checkingLevel < savingsLevel;

final Accountfinal Accountself : savingsLevelself : savingsLevel savingsAccount = new Account(); savingsAccount = new Account();

final Accountfinal Accountself : checkingLevelself : checkingLevel checkingAccount = new Account(); checkingAccount = new Account();

int balance() int balance() locks (savingsLevel) locks (savingsLevel) {{

synchronized (savingsAccount) { synchronized (savingsAccount) {

synchronized (checkingAccount) {synchronized (checkingAccount) {

return savingsAccount.balance + checkingAccount.balance; return savingsAccount.balance + checkingAccount.balance;

}}}}}}

}}

savingsAccount belongs to savingsLevel savingsAccount belongs to savingsLevel checkingAccount belongs to checkingLevelcheckingAccount belongs to checkingLevel

Lock Level Based Partial OrdersLock Level Based Partial Orders

class CombinedAccountclass CombinedAccount {{

LockLevel savingsLevel;LockLevel savingsLevel;

LockLevel checkingLevel < savingsLevel;LockLevel checkingLevel < savingsLevel;

final Accountfinal Accountself : savingsLevelself : savingsLevel savingsAccount = new Account(); savingsAccount = new Account();

final Accountfinal Accountself : checkingLevelself : checkingLevel checkingAccount = new Account(); checkingAccount = new Account();

int balance() int balance() locks (savingsLevel) locks (savingsLevel) {{

synchronized (savingsAccount) { synchronized (savingsAccount) {

synchronized (checkingAccount) {synchronized (checkingAccount) {

return savingsAccount.balance + checkingAccount.balance; return savingsAccount.balance + checkingAccount.balance;

}}}}}}

}}

locks are acquired in descending orderlocks are acquired in descending order

Lock Level Based Partial OrdersLock Level Based Partial Orders

class CombinedAccountclass CombinedAccount {{

LockLevel savingsLevel;LockLevel savingsLevel;

LockLevel checkingLevel < savingsLevel;LockLevel checkingLevel < savingsLevel;

final Accountfinal Accountself : savingsLevelself : savingsLevel savingsAccount = new Account(); savingsAccount = new Account();

final Accountfinal Accountself : checkingLevelself : checkingLevel checkingAccount = new Account(); checkingAccount = new Account();

int balance() int balance() locks (savingsLevel) locks (savingsLevel) {{

synchronized (savingsAccount) { synchronized (savingsAccount) {

synchronized (checkingAccount) {synchronized (checkingAccount) {

return savingsAccount.balance + checkingAccount.balance; return savingsAccount.balance + checkingAccount.balance;

}}}}}}

}}

locks held by callers > savingsLevellocks held by callers > savingsLevel

Lock Level Based Partial OrdersLock Level Based Partial Orders

class CombinedAccountclass CombinedAccount {{

LockLevel savingsLevel;LockLevel savingsLevel;

LockLevel checkingLevel < savingsLevel;LockLevel checkingLevel < savingsLevel;

final Accountfinal Accountself : savingsLevelself : savingsLevel savingsAccount = new Account(); savingsAccount = new Account();

final Accountfinal Accountself : checkingLevelself : checkingLevel checkingAccount = new Account(); checkingAccount = new Account();

int balance() int balance() locks (savingsLevel) locks (savingsLevel) {{

synchronized (savingsAccount) { synchronized (savingsAccount) {

synchronized (checkingAccount) {synchronized (checkingAccount) {

return savingsAccount.balance + checkingAccount.balance; return savingsAccount.balance + checkingAccount.balance;

}}}}}}

}}

balance can acquire these locksbalance can acquire these locks

Lock Level Based Partial OrdersLock Level Based Partial Orders

Types Impose No Dynamic OverheadTypes Impose No Dynamic Overhead

Type Type checkerchecker

TranslatorTranslator(Removes extra (Removes extra

types)types)

CompilerCompiler

JVMJVM

JavaJava

bytecodesbytecodes

+ Extra + Extra typestypes

JavaJava

Lock Level Based Partial OrdersLock Level Based Partial Orders

Bounded number of lock levelsBounded number of lock levels Unbounded number of locksUnbounded number of locks

Lock levels support programs where the Lock levels support programs where the maximum number of locks simultaneously maximum number of locks simultaneously held by a thread is boundedheld by a thread is bounded

We use other mechanisms for other casesWe use other mechanisms for other cases

Type SystemType System

Preventing data racesPreventing data races

Preventing deadlocks usingPreventing deadlocks using Static lock levelsStatic lock levels Recursive data structuresRecursive data structures

Mutable treesMutable trees Monotonic DAGsMonotonic DAGs

Runtime orderingRuntime ordering

Tree Based Partial OrdersTree Based Partial Orders

Locks in a level can be tree-orderedLocks in a level can be tree-ordered Using data structures with tree backbonesUsing data structures with tree backbones

Doubly linked listsDoubly linked lists Trees with parent/sibling pointersTrees with parent/sibling pointers Threaded trees…Threaded trees…

class Node {class Node {

Node left;Node left;

Node right;Node right;

synchronized void rotateRight() {synchronized void rotateRight() {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

xx

thisthis

vv

ww yy

thisthis

vv

xx

yy

uu ww

uu

Tree Based Partial OrdersTree Based Partial Orders

class Nodeclass Nodeself : lself : l { { treetree Node Nodeself : lself : l left; left;

treetree Node Nodeself : lself : l right; right;

synchronized void rotateRight() synchronized void rotateRight() locks (this)locks (this) { {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

xx

thisthis

vv

ww yy

thisthis

vv

xx

yy

uu ww

uu

Tree Based Partial OrdersTree Based Partial Orders

nodes must be locked in tree ordernodes must be locked in tree order

class Nodeclass Nodeself : lself : l { { treetree Node Nodeself : lself : l left; left;

treetree Node Nodeself : lself : l right; right;

synchronized void rotateRight() synchronized void rotateRight() locks (this)locks (this) { {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

xx

thisthis

vv

ww yy

thisthis

vv

xx

yy

uu ww

uu

nodes are locked in tree ordernodes are locked in tree order

Tree Based Partial OrdersTree Based Partial Orders

Checking Tree MutationsChecking Tree Mutations

A tree edge may be deletedA tree edge may be deleted A tree edge from x to y may be added iffA tree edge from x to y may be added iff

y is a Rooty is a Root x is not in Tree(y)x is not in Tree(y)

For onstage nodes x & y, analysis tracksFor onstage nodes x & y, analysis tracks If y is a RootIf y is a Root If x is not in Tree(y)If x is not in Tree(y) If x has a tree edge to yIf x has a tree edge to y

Lightweight shape analysisLightweight shape analysis

class Nodeclass Nodeself : lself : l { { treetree Node Nodeself : lself : l left; left;

treetree Node Nodeself : lself : l right; right;

synchronized void rotateRight() synchronized void rotateRight() locks (this)locks (this) { {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

Checking Tree MutationsChecking Tree Mutations

xx

thisthis

vv

ww yy

thisthis

vv

xx

yy

uu ww

uu

class Nodeclass Nodeself : lself : l { { treetree Node Nodeself : lself : l left; left;

treetree Node Nodeself : lself : l right; right;

synchronized void rotateRight() synchronized void rotateRight() locks (this)locks (this) { {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

Checking Tree MutationsChecking Tree Mutations

thisthis

vv

xx

yy

uu ww

x = this.rightx = this.rightv = x.leftv = x.leftw = v.rightw = v.right

class Nodeclass Nodeself : lself : l { { treetree Node Nodeself : lself : l left; left;

treetree Node Nodeself : lself : l right; right;

synchronized void rotateRight() synchronized void rotateRight() locks (this)locks (this) { {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

Checking Tree MutationsChecking Tree Mutations

thisthis

vv

xx

yy

uu ww

x = this.rightx = this.rightv = x.leftv = x.left

w is Rootw is Root

v v not in Tree(w) not in Tree(w)x x not in Tree(w) not in Tree(w)this not in Tree(w)this not in Tree(w)

class Nodeclass Nodeself : lself : l { { treetree Node Nodeself : lself : l left; left;

treetree Node Nodeself : lself : l right; right;

synchronized void rotateRight() synchronized void rotateRight() locks (this)locks (this) { {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

Checking Tree MutationsChecking Tree Mutations

thisthis

ww

xx

yy

x = this.rightx = this.rightw = x.leftw = x.left

v is Rootv is Root

x x not in Tree(v) not in Tree(v)w w not in Tree(v) not in Tree(v)this not in Tree(v)this not in Tree(v)

vv

uu

class Nodeclass Nodeself : lself : l { { treetree Node Nodeself : lself : l left; left;

treetree Node Nodeself : lself : l right; right;

synchronized void rotateRight() synchronized void rotateRight() locks (this)locks (this) { {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

Checking Tree MutationsChecking Tree Mutations

thisthis

uu

vv

xx

v = this.rightv = this.rightw = x.leftw = x.left

x is Rootx is Root

this not in Tree(x)this not in Tree(x)v v not in Tree(x) not in Tree(x)

ww yy

class Nodeclass Nodeself : lself : l { { treetree Node Nodeself : lself : l left; left;

treetree Node Nodeself : lself : l right; right;

synchronized void rotateRight() synchronized void rotateRight() locks (this)locks (this) { {

Node x = this.right; synchronized (x) {Node x = this.right; synchronized (x) {

Node v = x.left; synchronized (v) {Node v = x.left; synchronized (v) {

Node w Node w = v.right; = v.right;

v.right = null;v.right = null;

x.left = w;x.left = w;

this.right = v;this.right = v;

v.right = x;v.right = x;

}}}}}}

} }

Checking Tree MutationsChecking Tree Mutations

thisthis

uu

vv

xx

v = this.rightv = this.rightw = x.leftw = x.leftx = v.rightx = v.right

ww yy

Type SystemType System

Preventing data racesPreventing data races

Preventing deadlocks usingPreventing deadlocks using Static lock levelsStatic lock levels Recursive data structuresRecursive data structures

Mutable treesMutable trees Monotonic DAGsMonotonic DAGs

Runtime orderingRuntime ordering

DAG Based Partial OrdersDAG Based Partial Orders

Locks in a level can be DAG-orderedLocks in a level can be DAG-ordered

DAGs cannot be arbitrarily modifiedDAGs cannot be arbitrarily modified DAGs can be built bottom-up byDAGs can be built bottom-up by

Allocating a new nodeAllocating a new node Initializing its DAG fieldsInitializing its DAG fields

class Nodeclass Nodeself : lself : l { { dagdag Node Nodeself : lself : l left; left;

dagdag Node Nodeself : lself : l right; right;

… …

} }

Type SystemType System

Preventing data racesPreventing data races

Preventing deadlocks usingPreventing deadlocks using Static lock levelsStatic lock levels Recursive data structuresRecursive data structures

Mutable treesMutable trees Monotonic DAGsMonotonic DAGs

Runtime orderingRuntime ordering

class Accountclass Account {{

int balance = 0;int balance = 0;

void deposit(int x) void deposit(int x) { balance += x; } { balance += x; }

void withdraw(int x) { balance -= x; }void withdraw(int x) { balance -= x; }

}}

void transfer(Account a1, Account a2, int x) {void transfer(Account a1, Account a2, int x) {

synchronized (a1, a2)synchronized (a1, a2) in { a1.withdraw(x); a2.deposit(x); } in { a1.withdraw(x); a2.deposit(x); }

}}

Runtime Ordering of LocksRuntime Ordering of Locks

class Accountclass Account implements Dynamic implements Dynamic {{

int balance = 0;int balance = 0;

void deposit(int x) void deposit(int x) requires (this) requires (this) { balance += x; }{ balance += x; }

void withdraw(int x) void withdraw(int x) requires (this) requires (this) { balance -= x; }{ balance -= x; }

}}

void transfer(Accountvoid transfer(Accountself : vself : v a1, Account a1, Accountself : vself : v a2, int x) a2, int x) locks(v)locks(v) { {

synchronized (a1, a2)synchronized (a1, a2) in { a1.withdraw(x); a2.deposit(x); } in { a1.withdraw(x); a2.deposit(x); }

}}

Runtime Ordering of LocksRuntime Ordering of Locks

class Accountclass Account implements Dynamic implements Dynamic {{

int balance = 0;int balance = 0;

void deposit(int x) void deposit(int x) requires (this) requires (this) { balance += x; }{ balance += x; }

void withdraw(int x) void withdraw(int x) requires (this) requires (this) { balance -= x; }{ balance -= x; }

}}

void transfer(Accountvoid transfer(Accountself : vself : v a1, Account a1, Accountself : vself : v a2, int x) a2, int x) locks(v)locks(v) { {

synchronized (a1, a2)synchronized (a1, a2) in { a1.withdraw(x); a2.deposit(x); } in { a1.withdraw(x); a2.deposit(x); }

}}

Runtime Ordering of LocksRuntime Ordering of Locks

Account objects are dynamically orderedAccount objects are dynamically ordered

class Accountclass Account implements Dynamic implements Dynamic {{

int balance = 0;int balance = 0;

void deposit(int x) void deposit(int x) requires (this) requires (this) { balance += x; }{ balance += x; }

void withdraw(int x) void withdraw(int x) requires (this) requires (this) { balance -= x; }{ balance -= x; }

}}

void transfer(Accountvoid transfer(Accountself : vself : v a1, Account a1, Accountself : vself : v a2, int x) a2, int x) locks(v)locks(v) { {

synchronized (a1, a2)synchronized (a1, a2) in { a1.withdraw(x); a2.deposit(x); } in { a1.withdraw(x); a2.deposit(x); }

}}

Runtime Ordering of LocksRuntime Ordering of Locks

locks are acquired in runtime orderlocks are acquired in runtime order

Reducing Programming OverheadReducing Programming Overhead

Type inference and default types significantly Type inference and default types significantly reduce programming overheadreduce programming overhead

Single threaded programs need no annotationsSingle threaded programs need no annotations

Our approach supports separate compilationOur approach supports separate compilation

ExperienceExperience

Multithreaded Server ProgramsMultithreaded Server Programs

ProgramProgram Lines of codeLines of code Lines changedLines changed

elevatorelevator 523523 1515

http serverhttp server 563563 2626

chat serverchat server 308308 2222

stock quote serverstock quote server 242242 1212

game servergame server 8787 1111

phone (database) serverphone (database) server 302302 1010

Java LibrariesJava Libraries

ProgramProgram Lines of codeLines of code Lines changedLines changed

java.util.Hashtablejava.util.Hashtable 10111011 5353

java.util.HashMapjava.util.HashMap 852852 4646

java.util.Vectorjava.util.Vector 992992 3535

java.util.ArrayListjava.util.ArrayList 533533 1818

Java LibrariesJava Libraries

ProgramProgram Lines of codeLines of code Lines changedLines changed

java.io.OutputStreamjava.io.OutputStream 134134 33

java.io.BufferedWriterjava.io.BufferedWriter 253253 99

java.io.OutputStreamWriterjava.io.OutputStreamWriter 266266 1111

java.io.Writerjava.io.Writer 177177 66

java.io.PrintStreamjava.io.PrintStream 568568 1414

java.io.FilterOutputStreamjava.io.FilterOutputStream 148148 55

Related WorkRelated Work

Static toolsStatic tools Korty (Korty (USENIX ’89USENIX ’89)) Sterling (Sterling (USENIX ’93USENIX ’93)) Detlefs, Leino, Nelson, Saxe (Detlefs, Leino, Nelson, Saxe (SRC ’98SRC ’98)) Engler, Chen, Hallem, Chou, Chelf (Engler, Chen, Hallem, Chou, Chelf (SOSP ’01SOSP ’01))

Dynamic toolsDynamic tools Steele (Steele (POPL ’90POPL ’90)) Dinning, Schonberg (Dinning, Schonberg (PPoPP ’90PPoPP ’90)) Savage,Burrows,Nelson,Sobalvarro,Anderson (Savage,Burrows,Nelson,Sobalvarro,Anderson (SOSP ’97SOSP ’97)) Praun, Gross (Praun, Gross (OOPSLA ’01OOPSLA ’01) ) Choi,Lee,Loginov,O’Callahan,Sarkar,Sridharan (Choi,Lee,Loginov,O’Callahan,Sarkar,Sridharan (PLDI ’02PLDI ’02) )

Related WorkRelated Work

Type systemsType systems Flanagan, Freund (Flanagan, Freund (PLDI ’00PLDI ’00)) Bacon, Strom, Tarafdar (Bacon, Strom, Tarafdar (OOPSLA ’00OOPSLA ’00))

Related WorkRelated Work

Ownership typesOwnership types Clarke, Potter, Noble (Clarke, Potter, Noble (OOPSLA ’98OOPSLA ’98), (), (ECOOP ’01ECOOP ’01)) Clarke, Drossopoulou (Clarke, Drossopoulou (OOPSLA ’02OOPSLA ’02)) Aldrich, Kostadinov, Chambers (Aldrich, Kostadinov, Chambers (OOPSLA ’02OOPSLA ’02))

Boyapati, Rinard (Boyapati, Rinard (OOPSLA ’01OOPSLA ’01)) Boyapati, Lee, Rinard (Boyapati, Lee, Rinard (OOPSLA ’02OOPSLA ’02)) Boyapati, Liskov, Shrira (Boyapati, Liskov, Shrira (MIT ’02MIT ’02)) Boyapati, Salcianu, Beebee, Rinard (Boyapati, Salcianu, Beebee, Rinard (MIT ’02MIT ’02))

Related WorkRelated Work

Ownership TypesOwnership Types

We have used ownership types forWe have used ownership types for Object encapsulationObject encapsulation Constraining heap aliasingConstraining heap aliasing Modular effects clauses with subtypingModular effects clauses with subtyping Preventing data races and deadlocksPreventing data races and deadlocks Safe lazy upgrades in OODBsSafe lazy upgrades in OODBs Safe region-based memory managementSafe region-based memory management

Ownership types can serve as a Ownership types can serve as a foundation for future OO languagesfoundation for future OO languages

ConclusionsConclusions

Data races and deadlocks make Data races and deadlocks make multithreaded programming difficultmultithreaded programming difficult

We presented a static type system that We presented a static type system that prevents data races and deadlocksprevents data races and deadlocks

Our type system is expressiveOur type system is expressive Programs can be efficient and reliablePrograms can be efficient and reliable

Ownership Types for Safe Programming:Ownership Types for Safe Programming:Preventing Data Races and DeadlocksPreventing Data Races and Deadlocks

Chandrasekhar BoyapatiChandrasekhar BoyapatiRobert LeeRobert Lee

Martin RinardMartin Rinard

Laboratory for Computer ScienceLaboratory for Computer ScienceMassachusetts Institute of TechnologyMassachusetts Institute of Technology

{chandra, rhlee, rinard}@lcs.mit.edu{chandra, rhlee, rinard}@lcs.mit.edu