  Given a multithreaded program written assuming a friendly, non-preemptive
scheduler, the goal of synchronization synthesis is to automatically insert
synchronization primitives to ensure that the modified program behaves
correctly, even with a preemptive scheduler. In this work, we focus on the
quality of the synthesized solution: we aim to infer synchronization placements
that not only ensure correctness, but also meet some quantitative objectives
such as optimal program performance on a given computing platform.
  The key step that enables solution optimization is the construction of a set
of global constraints over synchronization placements such that each model of
the constraints set corresponds to a correctness-ensuring synchronization
placement. We extract the global constraints from generalizations of
counterexample traces and the control-flow graph of the program. The global
constraints enable us to choose from among the encoded synchronization
solutions using an objective function. We consider two types of objective
functions: ones that are solely dependent on the program (e.g., minimizing the
size of critical sections) and ones that are also dependent on the computing
platform. For the latter, given a program and a computing platform, we
construct a performance model based on measuring average contention for
critical sections and the average time taken to acquire and release a lock
under a given average contention.
  We empirically evaluated that our approach scales to typical module sizes of
many real world concurrent programs such as device drivers and multithreaded
servers, and that the performance predictions match reality. To the best of our
knowledge, this is the first comprehensive approach for optimizing the
placement of synthesized synchronization.
