Languages and Compilers (SProg og Oversættere)

72
1 Languages and Compilers (SProg og Oversættere) Bent Thomsen Department of Computer Science Aalborg University nowledgement to John Mitchell whose slides this lecture is based on.

description

Languages and Compilers (SProg og Oversættere). Bent Thomsen Department of Computer Science Aalborg University. With acknowledgement to John Mitchell whose slides this lecture is based on. Concurrency, distributed computing, the Internet. Traditional view: Let the OS deal with this - PowerPoint PPT Presentation

Transcript of Languages and Compilers (SProg og Oversættere)

Page 1: Languages and Compilers (SProg og Oversættere)

1

Languages and Compilers(SProg og Oversættere)

Bent Thomsen

Department of Computer Science

Aalborg University

With acknowledgement to John Mitchell whose slides this lecture is based on.

Page 2: Languages and Compilers (SProg og Oversættere)

2

Concurrency, distributed computing, the Internet

• Traditional view:• Let the OS deal with this• => It is not a programming language issue!• End of Lecture• Wait-a-minute …• Maybe “the traditional view” is getting out of date?

Page 3: Languages and Compilers (SProg og Oversættere)

3

Languages with concurrency constructs

• Maybe the “traditional view” was always out of date?• Simula• Modula3• Occam• Concurrent Pascal• ADA• Linda• CML• Facile• Jo-Caml• Java• C#• …

Page 4: Languages and Compilers (SProg og Oversættere)

4

Possibilities for Concurrency

Architecture: Architecture:

Uniprocessor with:-I/O channel- I/o processor- DMA

Multiprogramming, multiple process system Programs

Network of uniprocessors

Distributed programming

Multiple CPU’s Parallel programming

Page 5: Languages and Compilers (SProg og Oversættere)

5

The promise of concurrency

• Speed– If a task takes time t on one processor, shouldn’t it take time

t/n on n processors?

• Availability– If one process is busy, another may be ready to help

• Distribution– Processors in different locations can collaborate to solve a

problem or work together

• Humans do it so why can’t computers?– Vision, cognition appear to be highly parallel activities

Page 6: Languages and Compilers (SProg og Oversættere)

6

Challenges

• Concurrent programs are harder to get right– Folklore: Need an order of magnitude speedup (or more) to be

worth the effort

• Some problems are inherently sequential– Theory – circuit evaluation is P-complete

– Practice – many problems need coordination and communication among sub-problems

• Specific issues– Communication – send or receive information

– Synchronization – wait for another process to act

– Atomicity – do not stop in the middle and leave a mess

Page 7: Languages and Compilers (SProg og Oversættere)

7

Why is concurrent programming hard?• Nondeterminism

– Deterministic: two executions on the same input it always produce the same output

– Nondeterministic: two executions on the same input may produce different output

• Why does this cause difficulty?– May be many possible executions of one system

– Hard to think of all the possibilities

– Hard to test program since some may occur infrequently

Page 8: Languages and Compilers (SProg og Oversættere)

8

Concurrency and programming Languages

• Library view– All(most all) concurrency constructs are packaged as library

functions/methods– FORTRAN, C, Lisp, CML, Java (except for a few keywords

like synchronized)

• Language view– Syntactic manifestation in the language– Concurrent Pascal– Occam– ADA– Facile– Erlang– …

Page 9: Languages and Compilers (SProg og Oversættere)

9

Library view in C

System Calls

- fork( )

- wait( )

- pipe( )

- write( )

- read( )

Examples

Page 10: Languages and Compilers (SProg og Oversættere)

10

Process Creation

Fork( )NAME

fork() – create a new processSYNOPSIS

# include <sys/types.h># include <unistd.h>pid_t fork(void)

RETURN VALUEsuccess

parent- child pidchild- 0

failure-1

Page 11: Languages and Compilers (SProg og Oversættere)

11

Fork() system call- example

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

Main()

{

printf(“[%ld] parent process id: %ld\n”, getpid(), getppid());

fork();

printf(“\n[%ld] parent process id: %ld\n”, getpid(), getppid());

}

Page 12: Languages and Compilers (SProg og Oversættere)

12

Fork() system call- example

[17619] parent process id: 12729

[17619] parent process id: 12729

[2372] parent process id: 17619

Page 13: Languages and Compilers (SProg og Oversættere)

13

Fork()- program structure

#include <sys/types.h>#include <unistd.h>#include <stdio.h>Main(){

pid_t pid;if((pid = fork())>0){/* parent */}else if ((pid==0){/*child*/}else {

/* cannot fork*}exit(0);

}

Page 14: Languages and Compilers (SProg og Oversættere)

14

Wait() system call

Wait()- wait for the process whose pid reference is passed to finish executing

SYNOPSIS

#include<sys/types.h>

#include<sys/wait.h>

pid_t wait(int *stat)loc)

The unsigned decimal integer process ID for which to wait

RETURN VALUE

success- child pid

failure- -1 and errno is set

Page 15: Languages and Compilers (SProg og Oversættere)

15

Wait()- program structure

#include <sys/types.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>Main(int argc, char* argv[]){

pid_t childPID;if((childPID = fork())==0){/*child*/}else {

/* parent*wait(0);

}exit(0);

}

Page 16: Languages and Compilers (SProg og Oversættere)

16

Pipe() system call

Pipe()- to create a read-write pipe that may later be used to communicate with a process we’ll fork off.

SYNOPSIS

Int pipe(pfd)

int pfd[2];

PARAMETERPfd is an array of 2 integers, which that will be used to save the two file descriptors used to access the pipe

RETURN VALUE:0 – success;-1 – error.

Page 17: Languages and Compilers (SProg og Oversættere)

17

Pipe() - structure

/* first, define an array to store the two file descriptors*/Int pipe[2];

/* now, create the pipe*/int rc = pipe (pipes); if(rc = = -1) {

/* pipe() failed*/Perror(“pipe”);exit(1);

}

If the call to pipe() succeeded, a pipe will be created, pipes[0] will contain the number of its read file descriptor, and pipes[1] will contain the number of its write file descriptor.

Page 18: Languages and Compilers (SProg og Oversættere)

18

Write() system call

Write() – used to write data to a file or other object identified by a file descriptor.

SYNOPSIS#include <sys/types.h>Size_t write(int fildes, const void * buf, size_t nbyte);

PARAMETERfildes is the file descriptor,buf is the base address of area of memory that data is copied from,nbyte is the amount of data to copy

RETURN VALUEThe return value is the actual amount of data written, if this differs from nbyte then something has gone wrong

Page 19: Languages and Compilers (SProg og Oversættere)

19

Read() system call

Read() – read data from a file or other object identified by a file descriptor

SYNOPSIS

#include <sys/types.h>

Size_t read(int fildes, void *buf, size_t nbyte);

ARGUMENTfildes is the file descriptor,buf is the base address of the memory area into which the data is read, nbyte is the maximum amount of data to read.

RETURN VALUEThe actual amount of data read from the file. The pointer is incremented by the amount of data read.

Page 20: Languages and Compilers (SProg og Oversættere)

20

Solaris 2 Synchronization

• Implements a variety of locks to support multitasking, multithreading (including real-time threads), and multiprocessing.

• Uses adaptive mutexes for efficiency when protecting data from short code segments.

• Uses condition variables and readers-writers locks when longer sections of code need access to data.

• Uses turnstiles to order the list of threads waiting to acquire either an adaptive mutex or reader-writer lock.

Page 21: Languages and Compilers (SProg og Oversættere)

21

Windows 2000 Synchronization

• Uses interrupt masks to protect access to global resources on uniprocessor systems.

• Uses spinlocks on multiprocessor systems.• Also provides dispatcher objects which may act as

wither mutexes and semaphores.• Dispatcher objects may also provide events. An event

acts much like a condition variable.

Page 22: Languages and Compilers (SProg og Oversættere)

22

Basic question

• Maybe the library approach is not such a good idea?

• How can programming languages make concurrent and distributed programming easier?

Page 23: Languages and Compilers (SProg og Oversættere)

23

Language support for concurrency

• Make invariants and intentions more apparent (part of the interface)

• Good software engineering• Allows the compiler much more freedom to choose

different implementations• Also helps other tools

Page 24: Languages and Compilers (SProg og Oversættere)

24

What could languages provide?

• Abstract model of system – abstract machine => abstract system

• Example high-level constructs– Process as the value of an expression

• Pass processes to functions

• Create processes at the result of function call

– Communication abstractions

• Synchronous communication

• Buffered asynchronous channels that preserve msg order

– Mutual exclusion, atomicity primitives

• Most concurrent languages provide some form of locking

• Atomicity is more complicated, less commonly provided

Page 25: Languages and Compilers (SProg og Oversættere)

25

Basic issue: conflict between processes• Critical section

– Two processes may access shared resource

– Inconsistent behavior if two actions are interleaved

– Allow only one process in critical section

• Deadlock– Process may hold some locks while awaiting others

– Deadlock occurs when no process can proceed

Page 26: Languages and Compilers (SProg og Oversættere)

26

Cobegin/coend

• Limited concurrency primitive• Example

x := 0;cobegin

begin x := 1; x := x+1 end; begin x := 2; x := x+1 end;coend;print(x);

execute sequentialblocks in parallel

x := 0x := 2

x := 1

print(x)

x := x+1

x := x+1

Atomicity at level of assignment statement

Page 27: Languages and Compilers (SProg og Oversættere)

27

Mutual exclusion

• Sample actionprocedure sign_up(person)

beginnumber := number + 1;list[number] := person;

end;

• Problem with parallel executioncobegin

sign_up(fred);sign_up(bill);

end; bob fredbillfred

Page 28: Languages and Compilers (SProg og Oversættere)

28

Locks and Waiting

<initialze concurrency control>cobegin

begin <wait> sign_up(fred); // critical section<signal>

end;begin

<wait>sign_up(bill); // critical section<signal>

end;end;

Need atomic operations to implement wait

Page 29: Languages and Compilers (SProg og Oversættere)

29

Mutual exclusion primitives

• Atomic test-and-set– Instruction atomically reads and writes some location

– Common hardware instruction

– Combine with busy-waiting loop to implement mutex

• Semaphore– Avoid busy-waiting loop

– Keep queue of waiting processes

– Scheduler has access to semaphore; process sleeps

– Disable interrupts during semaphore operations

• OK since operations are short

Page 30: Languages and Compilers (SProg og Oversættere)

30

Monitor Brinch-Hansen, Dahl, Dijkstra, Hoare

• Synchronized access to private data. Combines:– private data

– set of procedures (methods)

– synchronization policy

• At most one process may execute a monitor procedure at a time; this process is said to be in the monitor.

• If one process is in the monitor, any other process that calls a monitor procedure will be delayed.

• Modern terminology: synchronized object

Page 31: Languages and Compilers (SProg og Oversættere)

31

OCCAM

• Program consists of processes and channels

• Process is code containing channel operations• Channel is a data object• All synchronization is via channels• Formal foundation based on CSP

Page 32: Languages and Compilers (SProg og Oversættere)

32

Channel Operations in OCCAM

• Read data item D from channel C– D ? C

• Write data item Q to channel C– Q ! C

• If reader accesses channel first, wait for writer, and then both proceed after transfer.

• If writer accesses channel first, wait for reader, and both proceed after transfer.

Page 33: Languages and Compilers (SProg og Oversættere)

33

Tasking in Ada

• Declare a task type

• The specification gives the entries– task type T is

entry Put (data : in Integer); entry Get (result : out Integer);end T;

• The entries are used to access the task

Page 34: Languages and Compilers (SProg og Oversættere)

34

Declaring Task Body

• Task body gives actual code of task• task body T is

x : integer; -- local per thread declarationbegin

…accept Put (M : Integer) do

…end Put;…

end T;

Page 35: Languages and Compilers (SProg og Oversættere)

35

Creating an Instance of a Task

• Declare a single task• X : T;

• or an array of tasks• P : array (1 .. 50) of T;

• or a dynamically allocated task• type AT is access T;

• P : AT;…P := new T;

Page 36: Languages and Compilers (SProg og Oversættere)

36

Task execution

• Each task executes independently, until– an accept call

• wait for someone to call entry, then proceed with rendezvous code, then both tasks go on their way

– an entry call

• wait for addressed task to reach corresponding accept statement, then proceed with rendezvous, then both tasks go on their way.

Page 37: Languages and Compilers (SProg og Oversættere)

37

More on the Rendezvous

• During the Rendezvous, only the called task executes, and data can be safely exchanged via the entry parameters

• If accept does a simple assignment, we have the equivalent of a simple CSP channel operation, but there is no restriction on what can be done within a rendezvous

Page 38: Languages and Compilers (SProg og Oversættere)

38

Termination of Tasks

• A task terminates when it reaches the end of the begin-end code of its body.

• Tasks may either be very static (create at start of execution and never terminate)

• Or very dynamic, e.g. create a new task for each new radar trace in a radar system.

Page 39: Languages and Compilers (SProg og Oversættere)

39

The Delay Statement

• Delay statements temporarily pause a task– Delay xyz

• where xyz is an expression of type duration causes execution of the thread to be delayed for (at least) the given amount of time

– Delay until tim

• where tim is an expression of type time, causes execution of the thread to be delayed until (at the earliest) the given tim

Page 40: Languages and Compilers (SProg og Oversættere)

40

Selective Accept

• Select statement allows a choice of actions• select

entry1 (…) do .. end;or when bla entry2 (…);or

delay ...ddd...;end select;

– Take whichever open entry arrives first, or if none arrives by end of delay, do …ddd…stmts.

Page 41: Languages and Compilers (SProg og Oversættere)

41

Timed Entry Call

• Timed Entry call allows timeout to be set• select

entry-call-statement or

delay xxx;…

end select

– We try to do the entry call, but if the task won’t accept in xxx time, then do the delay stmts.

Page 42: Languages and Compilers (SProg og Oversættere)

42

Conditional Entry Call

• Make a call only if it will be accepted• select

entry-call ..else

statementsend select;

– If entry call is accepted immediately, fine, otherwise execute the else statements.

Page 43: Languages and Compilers (SProg og Oversættere)

43

Task Abort

• Unconditionally terminate a task• abort taskname;

– task is immediately terminated

– (it is allowed to do finalization actions)

– but whatever it was doing remains incomplete

– code that can be aborted must be careful to leave things in a coherent state if that is important!

Page 44: Languages and Compilers (SProg og Oversættere)

44

Java Concurrency• Threads

– Create process by creating thread object

• Communication– shared variables

– method calls

• Mutual exclusion and synchronization– Every object has a lock (inherited from class Object)

• synchronized methods and blocks– Synchronization operations (inherited from class Object)

• wait : pause current thread until another thread calls notify

• notify : wake up waiting threads

Page 45: Languages and Compilers (SProg og Oversættere)

45

Java Threads

• Thread– Set of instructions to be executed one at a time, in a specified

order

• Java thread objects– Object of class Thread

– Methods inherited from Thread:

• start : method called to spawn a new thread of control; causes VM to call run method

• suspend : freeze execution

• interrupt : freeze execution and throw exception to thread

• stop : forcibly cause thread to halt

Page 46: Languages and Compilers (SProg og Oversættere)

46

Example subclass of Thread

class PrintMany extends Thread {

private String msg;

public PrintMany (String m) {msg = m;}

public void run() {

try { for (;;){ System.out.print(msg + “ “);

sleep(10);

}

} catch (InterruptedException e) {

return;

}

} (inherits start from Thread)

Page 47: Languages and Compilers (SProg og Oversættere)

47

Interaction between threads

• Shared variables– Two threads may assign/read the same variable

– Programmer responsibility

• Avoid race conditions by explicit synchronization!!

• Method calls– Two threads may call methods on the same object

• Synchronization primitives– Each object has internal lock, inherited from Object

– Synchronization primitives based on object locking

Page 48: Languages and Compilers (SProg og Oversættere)

48

Synchronization example

• Objects may have synchronized methods• Can be used for mutual exclusion

– Two threads may share an object.

– If one calls a synchronized method, this locks object.

– If the other calls a synchronized method on same object, this thread blocks until object is unlocked.

Page 49: Languages and Compilers (SProg og Oversættere)

49

Synchronized methods

• Marked by keywordpublic synchronized void commitTransaction(…) {…}

• Provides mutual exclusion– At most one synchronized method can be active

– Unsynchronized methods can still be called

• Programmer must be careful

• Not part of method signature– sync method equivalent to unsync method with body

consisting of a synchronized block

– subclass may replace a synchronized method with unsynchronized method

Page 50: Languages and Compilers (SProg og Oversættere)

50

Join, another form of synchronization

• Wait for thread to terminateclass Future extends Thread {

private int result;

public void run() { result = f(…); }

public int getResult() { return result;}

}…

Future t = new future;

t.start() // start new thread…

t.join(); x = t.getResult(); // wait and get result

Page 51: Languages and Compilers (SProg og Oversættere)

51

Aspects of Java Threads

• Portable since part of language– Easier to use in basic libraries than C system calls

– Example: garbage collector is separate thread

• General difficulty combining serial/concur code– Serial to concurrent

• Code for serial execution may not work in concurrent sys

– Concurrent to serial• Code with synchronization may be inefficient in serial

programs (10-20% unnecessary overhead)

• Abstract memory model– Shared variables can be problematic on some implementations

Page 52: Languages and Compilers (SProg og Oversættere)

52

Concurrent garbage collector

• How much concurrency?– Need to stop thread while mark and sweep

– Other GC: may not need to stop all program threads

• Problem– Program thread may change objects during collection

• Solution– Prevent read/write to memory area

– Details are subtle; generational, copying GC

• Modern GC distinguishes short-lived from long-lived objects

• Copying allows read to old area if writes are blocked …

• Relatively efficient methods for read barrier, write barrier

Page 53: Languages and Compilers (SProg og Oversættere)

53

Java memory model

• Main ideas– Threads have local memory (cache)

– Threads fill/flush from main memory

• Interaction restricted by constraints on actions– Use/assign are local thread memory actions

– Load/store fill or flush local memory

– Read/write are main memory actions

Page 54: Languages and Compilers (SProg og Oversættere)

54

Thread

Memory Hierarchy

Thread Cache

Shared Memory

Cache

code

code

use/assignload/store

read/write

Page 55: Languages and Compilers (SProg og Oversættere)

55

Example

• Programr.i = r.i+1

load r.i

store r.i

use r.i

assign r.i

write r.i

read r.i

• The value of field i of object i is– read from main memory

– loaded into the local cache of the thread– used in the addition r.i+1

• Similar steps to place the value of r.i in shared memory

Page 56: Languages and Compilers (SProg og Oversættere)

56

Java Memory Model [Java Lang Spec]

• Example constraints on use, assign, load, store:– use and assign actions by thread must occur in the order specified by the

program

– Thread is not permitted to lose its most recent assign

– Thread is not permitted to write data from its working memory to main memory for no reason

– New thread starts with an empty working memory

– New variable created only in main memory, not thread working memory

• “Provided that all the constraints are obeyed, a load or store action may be issued at any time by any thread on any variable, at the whim of the implementation.”

Page 57: Languages and Compilers (SProg og Oversættere)

57

Access to Main Memory

• Constraints on load, store, read ,write– For every load, must be a preceding read action

– For every store, must be a following write action

– Actions on master copy of a variable are performed by the main memory in order requested by thread

Page 58: Languages and Compilers (SProg og Oversættere)

58

Prescient stores

• Under certain conditions …– Store actions (from cache to shared memory) may occur

earlier than you would otherwise expect

– Purpose:

• Allow optimizations that make properly synchronized programs run faster

• These optimizations may allow out-of-order operations for programs that are not properly synchronized

Details are complicated. Main point: there’s more to designing a good memory model than you might think!

Page 59: Languages and Compilers (SProg og Oversættere)

59

Criticism [Pugh]

• Model is hard to interpret and poorly understood

• Constraints – prohibit common compiler optimizations

– expensive to implement on existing hardware

• Not commonly followed– Java Programs

• Sun Java Development Kit not guaranteed valid by the existing Java memory model

– Implementations not compliant

• Sun Classic Wintel JVM, Sun Hotspot Wintel JVM, IBM 1.1.7b Wintel JVM, Sun production Sparc Solaris JVM, Microsoft JVM

Page 60: Languages and Compilers (SProg og Oversættere)

60

Thread States

born

ready

running

blocked

dead

sleepingwaiting

start()

sleep()

yield()

wait()

notify() tim

eout

terminate

I/O started

I/O completed

Page 61: Languages and Compilers (SProg og Oversættere)

61

What the Language Spec. Says

• From The Java Language Specification

• Vague enough for you?

Every thread has a priority. When there is competition for processing resources, threads with higher priority are generally executed in preference to threads with lower priority. Such preference is not, however, a guarantee that the highest priority thread will always be running, and thread priorities cannot be used to reliably implement mutual exclusion.

Page 62: Languages and Compilers (SProg og Oversættere)

62

Multiple threads at same priority?

• Language gives implementer freedom

• Calling yield() suspends current thread to allow other at same priority to run … maybe

• Solaris implementation runs threads until they stop themselves (wait(), yield(), etc.)

• Windows implementation timeslices

Page 63: Languages and Compilers (SProg og Oversættere)

63

Concurrent ML

• Threads– New type of entity

• Communication– Synchronous channels

• Synchronization– Channels

– Events

• Atomicity– No specific language support

Page 64: Languages and Compilers (SProg og Oversættere)

64

Threads

• Thread creation– spawn : (unit unit) thread_id

• Example code CIO.print "begin parent\n";

spawn (fn () => (CIO.print "child 1\n";));

spawn (fn () => (CIO.print "child 2\n";));

CIO.print "end parent\n“

• Result

end parent

child 2

child 1

begin parent

Page 65: Languages and Compilers (SProg og Oversættere)

65

Channels

• Channel creation– channel : unit ‘a chan

• Communication– recv : ‘a chan ‘a– send : ( ‘a chan * ‘a ) unit

• Example ch = channel(); spawn (fn()=> … <A> … send(ch,0); … <B> …); spawn (fn()=> … <C> … recv ch; … <D> …);

• Resultsend/recv

<C>

<A>

<D>

<B>

Page 66: Languages and Compilers (SProg og Oversættere)

66

CML programming

• Functions– Can write functions : channels threads

– Build concurrent system by declaring channels and “wiring together” sets of threads

• Events– Delayed action that can be used for synchronization

– Powerful concept for concurrent programming

• Sample Application– eXene – concurrent uniprocessor window system

Page 67: Languages and Compilers (SProg og Oversættere)

67

CML from continuations

• Continuation primitives– callcc : ('a cont 'a) 'a

Call function argument with current continuation

– throw : 'a cont -> 'a -> 'b

– Curried function to invoke continuation with arg

• Example fun f(x,k) = throw k(x+3);

fun g(y,k) = f(y+2,k) + 10;

fun h(z) = z + callcc(fn k => g(z+1,k));

h(1);

Page 68: Languages and Compilers (SProg og Oversættere)

68

A CML implementation (simplified)

• Use queues with side-effecting functionsdatatype 'a queue = Q of {front: 'a list ref, rear: 'a list ref}

fun queueIns (Q(…)) = (* insert into queue *)

fun queueRem (Q(…)) = (* remove from queue *)

• And continuationsval enqueue = queueIns rdyQ

fun dispatch () = throw (queueRem rdyQ) ()

fun spawn f = callcc (fn parent_k =>

( enqueue parent_k; f (); dispatch()))

Source: Appel, Reppy

Page 69: Languages and Compilers (SProg og Oversættere)

69

Facile Programming Language

• Integration of Multiple Paradigms– Functions

– Types/complex data types

– Concurrency

– Distribution/soft real-time

– Dynamic connectivity

• Implemented as extension to SML• Syntax for concurrency similar to CML

Page 70: Languages and Compilers (SProg og Oversættere)

70

Page 71: Languages and Compilers (SProg og Oversættere)

71

Facile implementation

• Pre-emptive scheduler implemented at the lowest level– Exploiting CPS translation => state characterised by the set of

registers

• Garbage collector used for linearizing data structures• Lambda level code used as intermediate language when

shipping data (including code) in heterogeneous networks

• Native representation is shipped when possible– i.e. same architecture and within same trust domain

• Possibility to mix between interpretation or JIT depending on usage

Page 72: Languages and Compilers (SProg og Oversættere)

72

Conclusion

• Concurrency may be an order of magnitude more difficult to handle

• Programming language support for concurrency may help make the task easier

• Which concurrency constructs to add to the language is still a very active research area