KDB: a multi-threaded debugger for multi-threaded applications

Concurrent programs contain both sequential and concurrent errors. While deadlock and race conditions are unique to concunent programs, there also exist algorithmic design errors, such as inhibiting concurrency, which are unknown in the sequential domain. Recently, there has been a large effort in debugging race conditions [16], both statically [8] and dynamically [7], and to a lesser extent, deadlock [13]. Our experience shows that concurrent errors occur with diminishing frequency in the order: traditional sequential errors, algorithmic design errors, deadlock, race conditions. However, the difficulty in determining and fixing these errors grows exponentially from sequential errors to race conditions. Our experience also shows that the frequency of deadlock and race-conditions diminishes significantly when high-level concurrency constructs (e.g., task, monitor, actor, etc.) are used, versus thread and lock programming. We believe the best way to improve concurrent debugging capabilities and significantly reduce debugging time is to use high-level concurrency constructs with a symbolic debugger that truly understands it is debugging a concurrent program coupled with a cooperative concurrent run-time system that actively participates in the debugging process. Additionally, the debugger must provide independent and concurrent access to every thread of control in the target program. Such a debugger handles a large set of errors in concurrent programs? leaving esoteric errors to specialized debugging tools. Ultimately, a debugger and specialized tools must complement each other. Our experience comes from designing high-level concurrent extensions for C+I-~ called IN++ [5], using IL++ to build itself, a debugger and visualization toolkit [4], a database toolkit [3], and using @I-+ to teach concurrency to undergraduate students. &++ is a shared-memory userlevel thread library that runs on symmetric multiprocessor architectures (e.g., SUN, DEC, SGI, Sequent); user-level threads are executed by multiple kernel threads associated with shared memory, which provides true parallelism when appropriate hardware is available. Furthermore, p+ provides several high-level concurrency constructs, e.g. ~ coroutines, monitors and tasks, for composing an application; hence, programmers do not work at the level of threads