/*
  This file is part of drd, a thread error detector.

  Copyright (C) 2006-2013 Bart Van Assche <bvanassche@acm.org>.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License as
  published by the Free Software Foundation; either version 2 of the
  License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  02111-1307, USA.

  The GNU General Public License is contained in the file COPYING.
*/


#include "drd_clientobj.h"
#include "drd_error.h"
#include "drd_suppression.h"
#include "pub_tool_basics.h"
#include "pub_tool_libcassert.h"
#include "pub_tool_libcbase.h"
#include "pub_tool_libcprint.h"   // VG_(message)()
#include "pub_tool_mallocfree.h"
#include "pub_tool_options.h"     // VG_(clo_backtrace_size)
#include "pub_tool_oset.h"
#include "pub_tool_stacktrace.h"
#include "pub_tool_threadstate.h" // VG_(get_running_tid)()


/* Local variables. */

static OSet* s_clientobj_set;
static Bool s_trace_clientobj;


/* Local functions. */

static Bool clientobj_remove_obj(DrdClientobj* const p);


/* Function definitions. */

void DRD_(clientobj_set_trace)(const Bool trace)
{
   s_trace_clientobj = trace;
}

/** Initialize the client object set. */
void DRD_(clientobj_init)(void)
{
   tl_assert(s_clientobj_set == 0);
   s_clientobj_set = VG_(OSetGen_Create)(0, 0, VG_(malloc),
                                         "drd.clientobj.ci.1", VG_(free));
}

/**
 * Free the memory allocated for the client object set.
 *
 * @pre Client object set is empty.
 */
void DRD_(clientobj_cleanup)(void)
{
   tl_assert(s_clientobj_set);
   tl_assert(VG_(OSetGen_Size)(s_clientobj_set) == 0);
   VG_(OSetGen_Destroy)(s_clientobj_set);
   s_clientobj_set = 0;
}

/**
 * Return the data associated with the client object at client address addr.
 * Return 0 if there is no client object in the set with the specified start
 * address.
 */
DrdClientobj* DRD_(clientobj_get_any)(const Addr addr)
{
   return VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
}

/**
 * Return the data associated with the client object at client address addr
 * and that has object type t. Return 0 if there is no client object in the
 * set with the specified start address.
 */
DrdClientobj* DRD_(clientobj_get)(const Addr addr, const ObjType t)
{
   DrdClientobj* p;
   p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
   if (p && p->any.type == t)
      return p;
   return 0;
}

/** Return true if and only if the address range of any client object overlaps
 *  with the specified address range.
 */
Bool DRD_(clientobj_present)(const Addr a1, const Addr a2)
{
   DrdClientobj *p;

   tl_assert(a1 <= a2);
   VG_(OSetGen_ResetIter)(s_clientobj_set);
   for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; )
   {
      if (a1 <= p->any.a1 && p->any.a1 < a2)
      {
         return True;
      }
   }
   return False;
}

/**
 * Add state information for the client object at client address addr and
 * of type t. Suppress data race reports on the address range [addr,addr+size[.
 *
 * @pre No other client object is present in the address range [addr,addr+size[.
 */
DrdClientobj* DRD_(clientobj_add)(const Addr a1, const ObjType t)
{
   DrdClientobj* p;

   tl_assert(! DRD_(clientobj_present)(a1, a1 + 1));
   tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == 0);

   if (s_trace_clientobj)
      DRD_(trace_msg)("Adding client object 0x%lx of type %d", a1, t);

   p = VG_(OSetGen_AllocNode)(s_clientobj_set, sizeof(*p));
   VG_(memset)(p, 0, sizeof(*p));
   p->any.a1   = a1;
   p->any.type = t;
   p->any.first_observed_at = VG_(record_ExeContext)(VG_(get_running_tid)(), 0);
   VG_(OSetGen_Insert)(s_clientobj_set, p);
   tl_assert(VG_(OSetGen_Lookup)(s_clientobj_set, &a1) == p);
   if (t == ClientHbvar)
      DRD_(mark_hbvar)(a1);
   else
      DRD_(start_suppression)(a1, a1 + 1, "clientobj");
   return p;
}

/**
 * Remove the information that was stored about the client object.
 *
 * @param[in] addr Address of the client object in the client address space.
 * @param[in] t    Type of the client object.
 */
Bool DRD_(clientobj_remove)(const Addr addr, const ObjType t)
{
   DrdClientobj* p;

   p = VG_(OSetGen_Lookup)(s_clientobj_set, &addr);
   tl_assert(p);
   tl_assert(p->any.type == t);
   return clientobj_remove_obj(p);
}

/**
 * Remove the information that was stored about the client object p.
 *
 * @note The order of operations below is important. The client object is
 *   removed from the client object set after the cleanup function has been
 *   called such that if the cleanup function can still use the function
 *   DRD_(clientobj_get_any)(). This happens e.g. in the function
 *   first_observed() in drd_error.c.
 */
static Bool clientobj_remove_obj(DrdClientobj* const p)
{
   tl_assert(p);

   if (s_trace_clientobj) {
      DRD_(trace_msg)("Removing client object 0x%lx of type %d", p->any.a1,
                      p->any.type);
#if 0
      VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
                                 VG_(clo_backtrace_size));
#endif
   }

   tl_assert(p->any.cleanup);
   (*p->any.cleanup)(p);
   VG_(OSetGen_Remove)(s_clientobj_set, &p->any.a1);
   VG_(OSetGen_FreeNode)(s_clientobj_set, p);
   return True;
}

/**
 * Clean up all client objects p for which their start address p->any.a1 fits
 * inside the address range [ a1, a2 [.
 *
 * @note The implementation of this function relies on the fact that the
 *   data in s_clientobj_set is sorted on the start address of client objects.
 */
void DRD_(clientobj_stop_using_mem)(const Addr a1, const Addr a2)
{
   Addr removed_at;
   DrdClientobj* p;

   tl_assert(s_clientobj_set);

   if (! DRD_(range_contains_suppression_or_hbvar)(a1, a2))
      return;

   VG_(OSetGen_ResetIterAt)(s_clientobj_set, &a1);
   for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0 && p->any.a1 < a2; )
   {
      tl_assert(a1 <= p->any.a1);
      removed_at = p->any.a1;
      clientobj_remove_obj(p);
      /*
       * The above call removes an element from the oset and hence
       * invalidates the iterator. Restore the iterator.
       */
      VG_(OSetGen_ResetIterAt)(s_clientobj_set, &removed_at);
   }
}

/**
 * Delete the per-thread information stored in client objects for the
 * specified thread.
 */
void DRD_(clientobj_delete_thread)(const DrdThreadId tid)
{
   DrdClientobj *p;

   VG_(OSetGen_ResetIter)(s_clientobj_set);
   for ( ; (p = VG_(OSetGen_Next)(s_clientobj_set)) != 0; )
   {
      if (p->any.delete_thread)
      {
         (*p->any.delete_thread)(p, tid);
      }
   }
}

const HChar* DRD_(clientobj_type_name)(const ObjType t)
{
   switch (t)
   {
   case ClientMutex:     return "mutex";
   case ClientCondvar:   return "cond";
   case ClientHbvar:     return "order annotation";
   case ClientSemaphore: return "semaphore";
   case ClientBarrier:   return "barrier";
   case ClientRwlock:    return "rwlock";
   }
   return "(unknown)";
}
