A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing...

33
A Scheme for native threads R. Kent Dybvig Indiana University Mitchfest / August 2009 1

Transcript of A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing...

Page 1: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

A Scheme for native threads

R. Kent DybvigIndiana University

Mitchfest / August 2009

1

Page 2: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

What are Native Threads?

Each thread is a separate O/S thread

Each may run on own processor or core

All threads share same heap, file descriptors, etc.

2

Page 3: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Why Native Threads?

Express multithreaded computations

Handle blocking operations

Take advantage of multiple processors and cores

Interoperate with existing threaded applications

3

Page 4: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Outline

Features / Examples

Thread safety

Suspending and killing threads

Implementation

Conclusion

4

Page 5: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Model

Based on Posix Threads

Fork threads dynamically

Use mutexes for mutual exclusion

Use conditions to avoid polling

5

Page 6: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Creation

(fork-thread thunk)

6

Page 7: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Mutexes

(make-mutex)

(mutex-acquire mutex)

(mutex-release mutex)

(with-mutex exprm body)

7

Page 8: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Conditions

(make-condition)

(condition-wait condition mutex)

(condition-signal condition)

(condition-broadcast condition)

8

Page 9: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Example

(let ([m (make-mutex)] [c (make-condition)])(with-mutex m

(fork-thread(lambda ()

(with-mutex m(display "hello\n"))(condition-signal c)))

(condition-wait c m)(display "goodbye\n")))

prints:

hellogoodbye

9

Page 10: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Example: pcall

(define-syntax pcall(syntax-rules ()

[(_ e0 e1 . . .)(let ([m (make-mutex)]

[c (make-condition)][ls (list (lambda () e0) (lambda () e1) . . .)][n (length ’(e0 e1 . . .))])

(with-mutex m(do ([ls ls (cdr ls)])

((null? ls))(fork-thread

(lambda ()(set-car! ls ((car ls)))(with-mutex m

(set! n (- n 1))(when (= n 0) (condition-signal c))))))

(condition-wait c m))(apply (car ls) (cdr ls)))]))

10

Page 11: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Activation

Thread activated by make-thread

Thread can also be activated in C

Should deactivate thread before blocking

Deactivation implicit for I/O operations

11

Page 12: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Parameters

Thread parameters ≡ thread-local storage

(make-thread-parameter value)(make-thread-parameter value filter)

(parameterize ([exprp exprv] ...) body)

Setting/parameterizing affects only current thread

Child inherits parameter values, not locations

Can still create global parameters:

(make-parameter value)(make-parameter value filter)

12

Page 13: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Parameters

Example thread parameters:

• current-input-port

• current-output-port

• printer controls• compiler controls

Example global parameters:

• current-directory

• command-line

• collector controls

13

Page 14: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Continuations

Continuations are per-thread

Can invoke continuation created in another thread

Should not be used to exit from thread

14

Page 15: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Safety

Most primitives are thread-safe . . .

• car, cons, +, =, list-sort, map, etc.

. . . including many destructive operations

• set-car!, vector-set!

15

Page 16: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Safety

Some primitives are “relatively” unsafe . . .

• put-char, get-char• hashtable-set!, hashtable-ref

. . . relative, that is, to a given object

• okay to read/write different ports/hashtables concurrently

Improper synchronization is bad:

• lost data• corrupted heap

Caveat emptor

16

Page 17: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Safety

Remainder are “safety preserving”

• apply, map, for-each• eval, compile-file (!)

17

Page 18: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Suspendable Threads

Threads cannot be suspended, interrupted, or killed

Justification:

• asynchronous interrupts ≡ indeterminate state• keep the mechanism simple

18

Page 19: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Suspendable Threads

Threads cannot be suspended, interrupted, or killed

Solution: ask thread politely

• please suspend yourself

• please interrupt yourself• please die

But, will it listen?

19

Page 20: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Suspendable Threads

Represent “suspendable thread” as a record

conditionmutexsuspend flag

Thread object

Set suspend flag #t to request suspension

Thread polls flag via lightweight threads, timer interrupts, etc.

• if suspension requested, waits on condition

Set flag #f and signal condition to resume

20

Page 21: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Suspendable Threads

(define-record-type sthread(fields (mutable suspend)

(immutable mutex)(immutable cond))

(protocol(lambda (new)(lambda ()

(new #f (make-mutex) (make-condition))))))

conditionmutexsuspend flag

Thread object

21

Page 22: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Suspendable Threads

(define fork-sthread(lambda (thunk)

(define ticks 1000)(let ([sthr (make-sthread)])(fork-thread

(lambda ()(timer-interrupt-handler

(lambda ()(with-mutex (sthread-mutex sthr)

(when (sthread-suspend sthr)(condition-wait

(sthread-cond sthr)(sthread-mutex sthr))))

(set-timer ticks)))(set-timer ticks)(thunk)))

sthr)))

22

Page 23: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Suspendable Threads

(define suspend-sthread(lambda (sthr)

(with-mutex (sthread-mutex sthr)(set-sthread-suspend! sthr #t))))

(define restart-sthread(lambda (sthr)

(with-mutex (sthread-mutex sthr)(set-sthread-suspend! sthr #f)(condition-signal (sthread-cond sthr)))))

23

Page 24: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Implementation

Thread context

Stack management

Heap management

Parameters

Challenges

24

Page 25: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Thread Implementation

fp

thread context

local stack segment local heap segment

esp eap

parameter block

ap

25

Page 26: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Garbage Collection

Collection is presently single-threaded

All active threads must rendezvous

Last thread collects, then releases others . . .

. . . or before deactivating, last thread wakes proxy

26

Page 27: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Challenges

Surprisingly few . . .

• segmented stack, heap essential• mostly stateless compiler helped

. . . but there were some:

• setting dirty bits

• finding uses of state

• dealing with state• bugs

27

Page 28: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Dealing with State

Some state is inherently per-thread

• e.g., compiler’s variable records• no worries

Other state can be made per-thread

• e.g., random seed, bignum temps• embed in thread context . . .• . . . or make into thread parameters

Other state requires synchronization

• e.g., system symbol table• try to minimize synchronization window

28

Page 29: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

The Bug from Hell

Some bad bugs:

• thread bugs (nonreproducible)

• collector bugs (indirect effects)

• multiple bugs (conflicting effects)

Worst case senario:

• multiple thread bugs involving the collector

Required eight (!) days to track

29

Page 30: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Dazzit!

Specialized database engine

• serves queries through web interface• run-time code provided as shared library

• adaptors for Apache, FastCGI, IIS, .NET, Java• each supports native threads

• Linux, Mac, Windows, Solaris

To reduce synchronization overhead:

• shared data is read-only

• modifications in per-thread caches

Interesting features:

• each query is compiled on the fly• html generated to communicate results

30

Page 31: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Future Work

Safer ports and hashtables

Parallel garbage collection

Parallel garbage collection

Lighter weight synchronization

Higher-level abstractions

31

Page 32: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Conclusions

Not for the faint of heart

A good starting point is helpful

• segmented stacks and heaps

• few uses of global state

Posix Threads also helpful

• reduced implementation time

• simplified portability• worth additional overhead

32

Page 33: A Scheme for native threads - guenchi.github.io Scheme for native threads.pdfSetting/parameterizing affects only current thread Child inherits parameter values, not locations Can still

Acknowledments

Oscar Waddell

Al Reich, Robert Boone at Motorola SPS

Michael Lenaghan at Dazzit!

33