text: /* **********************************************************
   * Copyright (c) 2000-2008 VMware, Inc.  All rights reserved.
   * **********************************************************/
  
  /*
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   * 
   * * Redistributions of source code must retain the above copyright notice,
   *   this list of conditions and the following disclaimer.
   * 
   * * Redistributions in binary form must reproduce the above copyright notice,
   *   this list of conditions and the following disclaimer in the documentation
   *   and/or other materials provided with the distribution.
   * 
   * * Neither the name of VMware, Inc. nor the names of its contributors may be
   *   used to endorse or promote products derived from this software without
   *   specific prior written permission.
   * 
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
   * DAMAGE.
   */
  
  /* Copyright (c) 2003-2007 Determina Corp. */
  /* Copyright (c) 2001-2003 Massachusetts Institute of Technology */
  /* Copyright (c) 2000-2001 Hewlett-Packard Company */
  
  /*
   * fcache.h - fcache exports
   */
  
  #ifndef _FCACHE_H_
  #define _FCACHE_H_ 1
  
  /* who's in the "trace" cache? 
   * when we have private traces we put temp-private bbs there (to avoid
   * perf hit in speccpu of having separate priv bb cache that's not
   * normally used)
   */
  #define IN_TRACE_CACHE(flags) \
      (TEST(FRAG_IS_TRACE, (flags)) || \
       (!DYNAMO_OPTION(shared_traces) && TEST(FRAG_TEMP_PRIVATE, (flags))))
  
  /* Case 8647: we don't need to pad jmps for coarse-grain bbs */
  #define PAD_FRAGMENT_JMPS(flags) \
      (TEST(FRAG_COARSE_GRAIN, (flags)) ? false : DYNAMO_OPTION(pad_jmps))
  
  #define PAD_JMPS_SHIFT_START(flags) \
      (PAD_FRAGMENT_JMPS(flags) ? \
       (TEST(FRAG_IS_TRACE, (flags)) ? INTERNAL_OPTION(pad_jmps_shift_trace) : \
        INTERNAL_OPTION(pad_jmps_shift_bb)) : false)
  
  /* control over what to reset */
  enum {
      /* everything, separate since more than sum of others */
      RESET_ALL              = 0x001,
      /* NYI (case 6335): just bb caches + heap */
      RESET_BASIC_BLOCKS     = 0x002,
      /* NYI (case 6335): just trace caches + heap */
      RESET_TRACES           = 0x004,
      /* just pending deletion entries (-reset_every_nth_pending)
       * TODO OPTIMIZATION (case 7147): we could avoid suspending
       * everyone and only suspend those threads w/ low flushtimes.
       */
      RESET_PENDING_DELETION = 0x008,
  };
  
  /* protects all reset triggers: reset_pending and reset_at_nth_thread_triggered 
   * resets are not queued up -- one wins and the rest are canceled
   */
  extern mutex_t reset_pending_lock;
  /* indicates a call to fcache_reset_all_caches_proactively() is pending from dispatch */
  extern uint reset_pending;
  
  void fcache_init(void);
  void fcache_exit(void);
  
  bool fcache_check_option_compatibility(void);
  
  #if defined(WINDOWS_PC_SAMPLE) && !defined(DEBUG)
  /* for fast exit path */
  void fcache_profile_exit(void);
  #endif
  
  #ifdef DEBUG
  void fcache_stats_exit(void);
  #endif
  
  bool in_fcache(void *pc);
  
  void fcache_thread_init(dcontext_t *dcontext);
  #ifdef DEBUG
  void fcache_thread_exit_stats(dcontext_t *dcontext);
  #endif
  void fcache_thread_exit(dcontext_t *dcontext);
  
  void fcache_add_fragment(dcontext_t *dcontext, fragment_t *f);
  void fcache_shift_start_pc(dcontext_t *dcontext, fragment_t *f, uint space);
  void fcache_return_extra_space(dcontext_t *dcontext, fragment_t *f, size_t space);
  void fcache_remove_fragment(dcontext_t *dcontext, fragment_t *f);
  
  bool fcache_is_flush_pending(dcontext_t *dcontext);
  bool fcache_flush_pending_units(dcontext_t *dcontext, fragment_t *was_I_flushed);
  void fcache_free_pending_units(dcontext_t *dcontext, uint flushtime);
  void fcache_flush_all_caches(void);
  
  void fcache_reset_all_caches_proactively(uint target);
  bool schedule_reset(uint target);
  
  void fcache_low_on_memory(void);
  
  /* macros to put mask check outside of function, for efficiency */
  /* when NULL is passed for f then the entire fcache will be affected */
  #define SELF_PROTECT_CACHE(dc, f, w) do {                    \
      if (TEST(SELFPROT_CACHE, dynamo_options.protect_mask) && \
          ((f) == NULL || (fcache_is_writable(f) != (w))))     \
          fcache_change_fragment_protection(dc, f, w);         \
  } while (0);
  
  bool fcache_is_writable(fragment_t *f);
  void fcache_change_fragment_protection(dcontext_t *dcontext,
                                         fragment_t *f, bool writable);
  
  #ifdef SIDELINE
  dcontext_t * get_dcontext_for_fragment(fragment_t *f);
  #endif
  
  /* for adaptive working set */
  bool fragment_lookup_deleted(dcontext_t *dcontext, app_pc tag);
  
  /* Returns the fragment_t whose body (not cache slot) contains lookup_pc */  
  fragment_t *
  fcache_fragment_pclookup(dcontext_t *dcontext, cache_pc lookup_pc, fragment_t *wrapper);
  
  void
  fcache_coarse_cache_delete(dcontext_t *dcontext, coarse_info_t *info);
  
  /* Returns the coarse info for the cache unit containing pc; if that unit
   * is not coarse, returns NULL.
   */
  coarse_info_t *
  get_fcache_coarse_info(cache_pc pc);
  
  /* Returns the total size needed for the cache if info is frozen. */
  size_t
  coarse_frozen_cache_size(dcontext_t *dcontext, coarse_info_t *info);
  
  void
  fcache_coarse_init_frozen(dcontext_t *dcontext, coarse_info_t *info,
                            cache_pc start_pc, size_t size);
  
  void
  fcache_coarse_set_info(dcontext_t *dcontext, coarse_info_t *info);
  
  #endif /* _FCACHE_H_ */
  