Cooperative Task management =========================== What are advantages/disadvantages of threads vs. events Advantages of threads: - Multiprocessor support - Easier to read code - Easier to examine call stack in debugger - Can work across disk I/O and page faults more easily Advantages of events: - More portable (no machine-specific context-switch code) - Works with legacy functions (e.g., strtok, gethostbyname, ...) - Fewer concurrency issues (no fine-grained/coarse grained locking issues) - Easier to debug non-deterministic behavior - Long-running events make application non-responsive (but easier to debug slow callbacks than data races) - "Stack ripping" makes code very ugly - Uses less memory - Callback harness usually adds less overhead than thread switching Digression: Callback coloring One take: Threads create too much concurrency -- any two LoC can race Can create callback harness that works on multiprocessors Most callbacks have color 0, but can allocate new colors Harness can schedule differently colored events concurrently Have concurrency where you want it, not where you don't What is goal of Adya et. al? Have the best of both worlds Idea: Events vs. Threads debate conflates a number of issues task management - preemptive vs. cooperative vs. serial stack management - manual ("stack ripping") vs. automatic I/O response management - synchronous vs. asynchronous conflict management - optimistic vs. pessimistic data partitioning - shared vs. task-specific How does old-style uniprocessor Unix kernel fit above categories? non-preemptive (mostly) automatic stack management mix of asynchronous and (at higher layers) synchronous I/O mostly pessimistic conflict management (disable interrupts w. splhigh) data partitioning - many things not accessible at interrupt level How does stack management affect other languages? Upwards funargs makes automatic stack management much easier E.g., in C: use (do_sync_thing (arg)); In Lisp: (use (do-sync-thing arg)); Async: (do-async-thing arg (lambda (result) Function currying: Like wrap from slides, but languages like ML do this more cleanly What data point are the authors advocating? Automatic stack management + cooperative task management How is does this differ from non-preemptive threads? - They address issue of hidden preemption. How? startAtomic(), endAtomic() functions fatal error to call yield() from within these This is a dynamic check? Could you do static? Why/why not? - They integrate thread scheduler with callback harness/event dispatch means automatic and manual stack code can coexist! How does coexistence work? Through fibers. What's a fiber? essentially like a thread stack, w. interface for restart, etc. always directed yield one Main fiber is event harness + callback-based code one fiber for each task currently in procedure-oriented code What is "pinning Pattern"? Acquire all necessary resources in a loop "Pin" them, so won't need another async call to use them If you are ever preempted, restart the loop from the beginning Is paper convincing? How is evaluation? Achieve their goals? Not much evaluation -- mostly Experience (sec. 5) and a few numbers in sec 6 How well did they achieve best of both worlds? Don't address memory usage by threads (so might still need stack ripping) Don't address multi-processor support Don't address long-running functions Don't address legacy functions like gethostbyname But address most of the other benefits of one approach or the other So maybe "some of the best of best worlds" more accurate Ability to switch between procedure-oriented and callbacks useful startAtomic/endAtomic seems like a very good idea