// // Copyright (C) 2012 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.vm; /** * a thread tracking policy that uses path local ThreadInfoSets. Each object allocation * gets a new ThreadInfo set which initially contains the allocating thread. * * This policy uses PersistentTids, i.e. it does not modify existing ThreadInfoSet * instances but replaces upon add/remove with new ones. This ensures that ThreadInfoSets * are path local, but it also means that operations that add/remove ThreadInfos * have to be aware of the associated ElementInfo cloning and don't keep/use references * to old ElementInfos. The upside is that sharedness should be the same along any * given path, regardless of which paths were executed before. The downside is that all * callers of ThreadInfoSet updates have to be aware of that the ElementInfo might change. * * Note that without additional transition breaks this can miss races due * to non-overlapping thread execution along all paths. Most real world systems * have enough scheduling points (sync, field access within loops etc.) to avoid this, * but short living threads that only have single field access interaction points can * run into this effect: T1 creates O, starts T2, accesses O and * terminates before T2 runs. When T2 runs, it only sees access to O from an already * terminated thread and therefore treats this as a clean handover. Even if * T2 would break at its O access, there is no CG that would bring T1 back * into a state between creation and access of O, hence races caused by the O access * of T1 are missed (see .test.mc.threads.MissedPathTest). * Two additional scheduling points help to prevent this case: thread start CGs and * object exposure CGs (/after/ assignment in reference field PUTs where the owning * object is shared, but the referenced object isn't yet). Both are conservative by * nature, i.e. might introduce superfluous states for the sake of not missing paths to * race points. Both can be controlled by configuration options ('cg.threads.break_start' * and 'vm.por.break_on_exposure'). * * Note also that shared-ness is not the same along all paths, because our goal * is just to find potential data races. As long as JPF explores /one/ path that * leads into a race we are fine - we don't care how many paths don't detect a race. */ public class OverlappingContenderPolicy extends SharedObjectPolicy { @Override public ThreadInfoSet getThreadInfoSet(ThreadInfo allocThread, DynamicElementInfo ei) { return new PersistentTidSet(allocThread); } @Override public ThreadInfoSet getThreadInfoSet(ThreadInfo allocThread, StaticElementInfo ei) { return new PersistentTidSet(allocThread); } @Override public boolean isShared (ThreadInfo ti, ElementInfo ei, ThreadInfoSet set) { return set.hasMultipleLiveThreads(); } @Override public Memento<ThreadInfoSet> getMemento(ThreadInfoSet set) { return set.getMemento(); } @Override public void cleanupThreadTermination(ThreadInfo ti) { // nothing, we keep the thread id in the set. Note this requires // ids to NOT being reused } }