Exemplo n.º 1
0
static void
GuestInfoLegacy(GuestInfoCollector *current,  // IN: current collection
                GuestMemInfo *legacy)         // OUT: data filled out
{
   GuestInfoStat *stat;

   memset(legacy, 0, sizeof *legacy);

   legacy->version = GUESTMEMINFO_V5;
   legacy->flags   = 0;

   stat = NULL;
   HashTable_Lookup(current->reportMap,
                    INT_AS_HASHKEY(GuestStatID_MemPhysUsable),
                    (void **) &stat);

   if ((stat != NULL) && (stat->err == 0)) {
      legacy->memTotal = stat->value;
      legacy->flags |= MEMINFO_MEMTOTAL;
   }

   stat = NULL;
   HashTable_Lookup(current->reportMap,
                    INT_AS_HASHKEY(GuestStatID_Linux_HugePagesTotal),
                    (void **) &stat);

   if ((stat != NULL) && (stat->err == 0)) {
      legacy->hugePagesTotal = stat->value;
      legacy->flags |= MEMINFO_HUGEPAGESTOTAL;
   }
}
Exemplo n.º 2
0
static void
GuestInfoDeriveSwapData(GuestInfoCollector *collector)  // IN: current collection
{
   uint64 swapFree = 0;
   uint64 swapTotal = 0;
   uint64 swapUsed = 0;
   GuestInfoStat *swapSpaceRemaining = NULL;
   GuestInfoStat *swapSpaceUsed = NULL;
   GuestInfoStat *swapFilesCurrent = NULL;
   GuestInfoStat *swapFilesMax = NULL;

   HashTable_Lookup(collector->reportMap,
                    INT_AS_HASHKEY(GuestStatID_SwapFilesMax),
                    (void **) &swapFilesMax);

   HashTable_Lookup(collector->reportMap,
                    INT_AS_HASHKEY(GuestStatID_SwapFilesCurrent),
                    (void **) &swapFilesCurrent);

   HashTable_Lookup(collector->reportMap,
                    INT_AS_HASHKEY(GuestStatID_SwapSpaceUsed),
                    (void **) &swapSpaceUsed);

   HashTable_Lookup(collector->reportMap,
                    INT_AS_HASHKEY(GuestStatID_SwapSpaceRemaining),
                    (void **) &swapSpaceRemaining);

   /*
    * Start by getting SwapTotal (from Id_SwapFilesCurrent).
    * Set Id_SwapFilesMax to that if it doesn't have its own opinion.
    */
   if ((swapFilesCurrent != NULL) && (swapFilesCurrent->err == 0)) {
      swapTotal = swapFilesCurrent->value;

      if ((swapFilesMax != NULL) && (swapFilesMax->err != 0)) {
         swapFilesMax->value = swapTotal;
         swapFilesMax->count = 1;
         swapFilesMax->err = 0;
      }

      /*
       * Get SwapFree (from Id_SwapSpaceRemaining)
       * Set Id_SwapSpaceUsed to SwapTotal-SwapFree if it doesn't have its
       * own opinion.
       */
      if ((swapSpaceRemaining != NULL) && (swapSpaceRemaining->err == 0)) {
         swapFree = swapSpaceRemaining->value;

         ASSERT(swapTotal >= swapFree);
         swapUsed = (swapTotal >= swapFree) ? swapTotal - swapFree : 0;

         if ((swapSpaceUsed != NULL) && (swapSpaceUsed->err != 0)) {
            swapSpaceUsed->value = swapUsed;
            swapSpaceUsed->count = 1;
            swapSpaceUsed->err = 0;
         }
      }
   }
}
Exemplo n.º 3
0
static void
GuestInfoAppendRate(Bool emitNameSpace,             // IN:
                    GuestStatToolsID reportID,      // IN: Id of the stat
                    GuestInfoCollector *current,    // IN: current collection
                    GuestInfoCollector *previous,   // IN: previous collection
                    DynBuf *statBuf)                // IN/OUT: stat data
{
   double valueDouble = 0.0;
   int errnoValue = ENOENT;
   GuestInfoStat *currentStat = NULL;
   GuestInfoStat *previousStat = NULL;

   HashTable_Lookup(current->reportMap,
                    INT_AS_HASHKEY(reportID),
                    (void **) &currentStat);

   HashTable_Lookup(previous->reportMap,
                    INT_AS_HASHKEY(reportID),
                    (void **) &previousStat);

   if (current->timeData &&
       previous->timeData &&
       ((currentStat != NULL) && (currentStat->err == 0)) &&
       ((previousStat != NULL) && (previousStat->err == 0))) {
      double timeDelta = current->timeStamp - previous->timeStamp;
      double valueDelta = currentStat->value - previousStat->value;

      valueDouble = valueDelta / timeDelta;
      errnoValue = 0;
   }

   if (currentStat != NULL) {
      float valueFloat;
      void *valuePointer;
      size_t valueSize;

      if (valueDouble == 0) {
         valuePointer = NULL;
         valueSize = 0;
      } else {
         valueFloat = (float)valueDouble;
         if ((double)valueFloat == valueDouble) {
            valuePointer = &valueFloat;
            valueSize = sizeof valueFloat;
         } else {
            valuePointer = &valueDouble;
            valueSize = sizeof valueDouble;
         }
      }

      GuestInfoAppendStat(errnoValue, emitNameSpace, reportID,
                          currentStat->query->units, GuestTypeDouble,
                          valuePointer, valueSize, statBuf);
   }
}
Exemplo n.º 4
0
Err_Number
Err_String2Errno(const char *string) // IN
{
   HashTable *ptrTable = PTRTABLE();
   ErrInfo *info;

   if (!HashTable_Lookup(ptrTable, string, (void **) &info)) {
      return ERR_INVALID;
   }

   ASSERT(info->string == string);
   ASSERT(info->number != ERR_INVALID);
   return info->number;
}
Exemplo n.º 5
0
static INLINE MsgCatalog *
MsgGetCatalog(const char *domain)
{
   MsgState *state = MsgGetState();
   MsgCatalog *catalog = NULL;

   ASSERT(domain != NULL);

   if (state->domains != NULL) {
      MsgCatalog *domaincat;
      if (HashTable_Lookup(state->domains, domain, (void **) &domaincat)) {
         catalog = domaincat;
      }
   }

   return catalog;
}
Exemplo n.º 6
0
ConstUnicode
Unicode_GetStatic(const char *asciiBytes, // IN
                  Bool unescape)          // IN
{
   Unicode result = NULL;
   HashTable *stringTable;

   if (unescape) {
      stringTable = HashTable_AllocOnce(&UnicodeUnescapedStringTable, 4096, 
                                        HASH_FLAG_ATOMIC | HASH_STRING_KEY,
                                        UnicodeHashFree);
   } else {
      stringTable = HashTable_AllocOnce(&UnicodeStringTable, 4096, 
                                        HASH_FLAG_ATOMIC | HASH_STRING_KEY,
                                        UnicodeHashFree);
   }

   /*
    * Attempt a lookup for the key value; if it is found things are easy and
    * fine. Otherwise HashTable_LookupOrInsert is used to attempt to enter
    * the data in a racey manner. Should multiple threads attempt to enter
    * the same key concurrently one thread will get the entered data and the
    * other threads will detect that their entries were rejected; they
    * discard their copies of the data and use the entered data (values
    * will be stable).
    */

   if (!HashTable_Lookup(stringTable, asciiBytes, (void **) &result)) {
      Unicode newData = UnicodeAllocStatic(asciiBytes, unescape);

      if (newData) {
         result = HashTable_LookupOrInsert(stringTable, asciiBytes, newData);

         if (result != newData) {
            Unicode_Free(newData);
         }
      }
   }

   return result;
}
Exemplo n.º 7
0
Err_Number
Err_String2ErrnoDebug(const char *string) // IN
{
#ifdef __linux__
   HashTable *strTable = STRTABLE();
   ErrInfo *info;

   if (!HashTable_Lookup(strTable, string, (void **) &info)) {
      return ERR_INVALID;
   }

   ASSERT(Str_Strcmp(info->string, string) == 0);
   ASSERT(info->number != ERR_INVALID);
   if (info->string != string) {
      Log("%s: errno %d, string \"%s\" at %p, originally at %p.\n",
	  __FUNCTION__, info->number, string, string, info->string);
   }
   return info->number;
#else
   return ERR_INVALID;
#endif
}
Exemplo n.º 8
0
static void
GuestInfoCollectStat(const char *pathName,           // IN:
                     GuestInfoCollector *collector,  // IN/OUT:
                     const char *fieldName,          // IN:
                     uint64 value)                   // IN:
{
   GuestInfoStat *stat = NULL;

   if (!HashTable_Lookup(collector->exactMatches, fieldName, (void **) &stat)) {
      uint32 i;

      for (i = 0; i < collector->numRegExps; i++) {
         GuestInfoStat *thisOne = collector->regExps[i];

         if (StrUtil_StartsWith(fieldName, thisOne->query->locatorString)) {
            stat = thisOne;
         }
      }
   }

   if (stat != NULL) {
      GuestInfoStoreStat(pathName, stat, value);
   }
}
Exemplo n.º 9
0
static HolderContext *
MXUserGetHolderContext(MXUserRWLock *lock)  // IN:
{
   HolderContext *result;
   void *threadID = MXUserCastedThreadID();

   ASSERT(lock->holderTable);

   if (!HashTable_Lookup(lock->holderTable, threadID, (void **) &result)) {
      HolderContext *newContext = Util_SafeMalloc(sizeof(HolderContext));

      newContext->holdStart = 0;
      newContext->state = RW_UNLOCKED;

      result = HashTable_LookupOrInsert(lock->holderTable, threadID,
                                        (void *) newContext);

      if (result != newContext) {
         free(newContext);
      }
   }

   return result;
}
Exemplo n.º 10
0
static void
GuestInfoAppendMemNeeded(GuestInfoCollector *current,  // IN: current collection
                         Bool emitNameSpace,           // IN:
                         DynBuf *statBuf)              // IN/OUT: stats data
{
   uint64 memNeeded;
   uint64 memNeededReservation;
   uint64 memAvailable = 0;
   GuestInfoStat *memAvail = NULL;
   GuestInfoStat *memPhysUsable = NULL;

   HashTable_Lookup(current->reportMap,
                    INT_AS_HASHKEY(GuestStatID_MemPhysUsable),
                    (void **) &memPhysUsable);

   ASSERT(memPhysUsable != NULL);

   HashTable_Lookup(current->reportMap,
                    INT_AS_HASHKEY(GuestStatID_Linux_MemAvailable),
                    (void **) &memAvail);

   if ((memAvail != NULL) && (memAvail->err == 0)) {
      memAvailable = memAvail->value;
   } else {
      GuestInfoStat *memFree = NULL;
      GuestInfoStat *memCache = NULL;
      GuestInfoStat *memBuffers = NULL;
      GuestInfoStat *memActiveFile = NULL;
      GuestInfoStat *memSlabReclaim = NULL;
      GuestInfoStat *memInactiveFile = NULL;
      GuestInfoStat *lowWaterMark = NULL;

      HashTable_Lookup(current->reportMap,
                       INT_AS_HASHKEY(GuestStatID_MemFree),
                       (void **) &memFree);
      HashTable_Lookup(current->reportMap,
                       INT_AS_HASHKEY(GuestStatID_Linux_MemCached),
                       (void **) &memCache);
      HashTable_Lookup(current->reportMap,
                       INT_AS_HASHKEY(GuestStatID_Linux_MemBuffers),
                       (void **) &memBuffers);
      HashTable_Lookup(current->reportMap,
                       INT_AS_HASHKEY(GuestStatID_MemActiveFileCache),
                       (void **) &memActiveFile);
      HashTable_Lookup(current->reportMap,
                       INT_AS_HASHKEY(GuestStatID_Linux_MemSlabReclaim),
                       (void **) &memSlabReclaim);
      HashTable_Lookup(current->reportMap,
                       INT_AS_HASHKEY(GuestStatID_Linux_MemInactiveFile),
                       (void **) &memInactiveFile);
      HashTable_Lookup(current->reportMap,
                       INT_AS_HASHKEY(GuestStatID_Linux_LowWaterMark),
                       (void **) &lowWaterMark);

      if (((memFree != NULL) && (memFree->err == 0)) &&
          ((memCache != NULL) && (memCache->err == 0)) &&
          ((memBuffers != NULL) && (memBuffers->err == 0)) &&
          (memActiveFile != NULL) &&
          (memSlabReclaim != NULL) &&
          (memInactiveFile != NULL) &&
          ((lowWaterMark != NULL) && (lowWaterMark->err == 0))) {
         uint64 pageCache;
         unsigned long kbPerPage = sysconf(_SC_PAGESIZE) / 1024UL;
         uint64 lowWaterMarkValue = lowWaterMark->value * kbPerPage;

         memAvailable = memFree->value - lowWaterMarkValue;

         if ((memActiveFile->err == 0) && (memInactiveFile->err == 0)) {
            pageCache = memActiveFile->value + memInactiveFile->value;
         } else {
            /*
             * If the kernel is too old to expose Active/Inactive file,
             * this is the best approxmation for pageCache.
             */
            pageCache = memCache->value + memBuffers->value;
         }

         pageCache -= MIN(pageCache / 2, lowWaterMarkValue);
         memAvailable += pageCache;

         if (memSlabReclaim->err == 0) {
            memAvailable += memSlabReclaim->value -
                            MIN(memSlabReclaim->value / 2, lowWaterMarkValue);
         }

         if ((int64)memAvailable < 0) {
            memAvailable = 0;
         }
      }
   }

   if (memPhysUsable->err == 0) {
      /*
       * Reserve 5% of physical RAM for surges.
       */
      memNeededReservation = memPhysUsable->value / 20;

      if (memAvailable > memNeededReservation) {
         memAvailable -= memNeededReservation;
      } else {
         memAvailable = 0;
      }

      /*
       * We got these values from one read of /proc/meminfo. Everything should
       * really be coherent.
       */
      ASSERT(memPhysUsable->value >= memAvailable);
      memNeeded = memPhysUsable->value - memAvailable;
   } else {
      memNeeded = 0;
      memNeededReservation = 0;
   }

   GuestInfoAppendStat(0,
                       emitNameSpace,
                       GuestStatID_MemNeeded,
                       GuestUnitsKiB, GuestTypeUint64,
                       &memNeeded,
                       GuestInfoBytesNeededUIntDatum(memNeeded),
                       statBuf);

   emitNameSpace = FALSE;
}
Exemplo n.º 11
0
static void
GuestInfoCollect(GuestInfoCollector *collector)  // IN:
{
   uint32 i;
   GuestInfoStat *stat;
   uint64 pageSize = sysconf(_SC_PAGESIZE);

   /* Reset all values */
   for (i = 0; i < collector->numStats; i++) {
      GuestInfoStat *stat = &collector->stats[i];

      stat->err = ENOENT;  // There is no data here
      stat->count = 0;
      stat->value = 0;
   }

   /* Collect new values */
   GuestInfoProcMemInfoData(collector);
   GuestInfoProcData(VMSTAT_FILE, collector);
   GuestInfoProcData(STAT_FILE, collector);
   GuestInfoProcData(ZONEINFO_FILE, collector);
   GuestInfoDeriveSwapData(collector);

   collector->timeData = GuestInfoGetUpTime(&collector->timeStamp);

   /*
    * We make sure physical page size is always present.
    */

   stat = NULL;
   HashTable_Lookup(collector->reportMap,
                    INT_AS_HASHKEY(GuestStatID_PhysicalPageSize),
                    (void **) &stat);

   if ((stat != NULL) && (stat->err != 0)) {
      stat->value = pageSize;
      stat->count = 1;
      stat->err = 0;
   }

   /*
    * Attempt to fix up memPhysUsable if it is not available.
    */

   stat = NULL;
   HashTable_Lookup(collector->reportMap,
                    INT_AS_HASHKEY(GuestStatID_MemPhysUsable),
                    (void **) &stat);

   ASSERT(stat != NULL);  // Must be in table

   if (stat->err == 0) {
      stat->value *= (pageSize / 1024); // Convert pages to KiB
   } else {
      GuestInfoStat *memTotal = NULL;

      HashTable_Lookup(collector->reportMap,
                       INT_AS_HASHKEY(GuestStatID_Linux_MemTotal),
                       (void **) &memTotal);

      if ((memTotal != NULL) && (memTotal->err == 0)) {
         stat->err = 0;
         stat->count = 1;
         stat->value = memTotal->value;
      }
   }
}
Exemplo n.º 12
0
const char *
Err_Errno2String(Err_Number errorNumber) // IN
{
   HashTable *numTable;
   HashTable *ptrTable;
   ErrInfo *info;
   ErrInfo *oldInfo;
   Err_Number oldErrno = Err_Errno();

   ASSERT(errorNumber != ERR_INVALID);

   /*
    * Look up the error in numTable.
    * Or insert it if it's not there.
    */

   numTable = NUMTABLE();
   if (!HashTable_Lookup(numTable, (void *) (uintptr_t) errorNumber,
			 (void **) &info)) {
      char buf[2048];
      const char *p;
      size_t n;

      /*
       * Convert number to string and build the info structure.
       */

      p = ErrErrno2String(errorNumber, buf, sizeof buf);

      info = Util_SafeMalloc(sizeof *info);
      info->number = errorNumber;
      info->string = Util_SafeStrdup(p);

      /*
       * To be safe, make sure the end of the string is at
       * a UTF-8 boundary, but we can only do this when the
       * string is in our buffer (it may not be).
       */

      n = strlen(info->string);
      n = CodeSet_Utf8FindCodePointBoundary(info->string, n);
      info->string[n] = '\0';

      /*
       * Try to insert new info into numTable.
       * If that fails, then we must have lost out to someone else.
       * Use theirs in that case.
       */

      oldInfo = HashTable_LookupOrInsert(numTable,
				         (void *) (uintptr_t) errorNumber,
				         info);
      if (oldInfo != info) {
	 ASSERT(oldInfo->number == info->number);
	 ASSERT(Str_Strcmp(oldInfo->string, info->string) == 0);
	 free(info->string);
	 free(info);
	 info = oldInfo;
      }
   }

   /*
    * Try to insert info into ptrTable.
    * We need to do it even if we didn't create this entry,
    * because we may get here before the other guy (who created
    * the entry and inserted it into numTable).
    */

   ptrTable = PTRTABLE();
   oldInfo = HashTable_LookupOrInsert(ptrTable, info->string, info);
   ASSERT(oldInfo == info);

#if defined VMX86_DEBUG && defined __linux__
   {
      HashTable *strTable = STRTABLE();
      ErrInfo *i = HashTable_LookupOrInsert(strTable, info->string, info);
      ASSERT(i == info);
   }
#endif

   Err_SetErrno(oldErrno);
   return info->string;
}
Exemplo n.º 13
0
static const void *
MsgGetString(const char *domain,
             const char *msgid,
             StringEncoding encoding)
{
   const char *idp;
   const char *strp;
   char idBuf[MSG_MAX_ID];
   size_t len;
   HashTable *source = NULL;
   MsgCatalog *catalog;
   MsgState *state = MsgGetState();

   /* All message strings must be prefixed by the message ID. */
   ASSERT(domain != NULL);
   ASSERT(msgid != NULL);
   ASSERT(MsgHasMsgID(msgid));
#if defined(_WIN32)
   ASSERT(encoding == STRING_ENCODING_UTF8 ||
          encoding == STRING_ENCODING_UTF16_LE);
#else
   ASSERT(encoding == STRING_ENCODING_UTF8);
#endif

   /*
    * Find the beginning of the ID (idp) and the string (strp).
    * The string should have the correct MSG_MAGIC(...)... form.
    */

   idp = msgid + MSG_MAGIC_LEN + 1;
   strp = strchr(idp, ')') + 1;

   len = strp - idp - 1;
   ASSERT_NOT_IMPLEMENTED(len <= MSG_MAX_ID - 1);
   memcpy(idBuf, idp, len);
   idBuf[len] = '\0';

   /*
    * This lock is pretty coarse-grained, but a lot of the code below just runs
    * in exceptional situations, so it should be OK.
    */
   g_static_mutex_lock(&state->lock);

   catalog = MsgGetCatalog(domain);
   if (catalog != NULL) {
      switch (encoding) {
      case STRING_ENCODING_UTF8:
         source = catalog->utf8;
         break;

#if defined(_WIN32)
      case STRING_ENCODING_UTF16_LE:
         source = catalog->utf16;
         break;
#endif

      default:
         NOT_IMPLEMENTED();
      }
   }

#if defined(_WIN32)
   /*
    * Lazily create the local and UTF-16 dictionaries. This may require also
    * registering an empty message catalog for the desired domain.
    */
   if (source == NULL && encoding == STRING_ENCODING_UTF16_LE) {
      catalog = MsgGetCatalog(domain);
      if (catalog == NULL) {
         if (domain == NULL) {
            g_error("Application did not set up a default text domain.");
         }
         catalog = g_new0(MsgCatalog, 1);
         MsgSetCatalog(domain, catalog);
      }

      catalog->utf16 = HashTable_Alloc(8, HASH_STRING_KEY, g_free);
      ASSERT_MEM_ALLOC(catalog->utf16);
      source = catalog->utf16;
   }
#endif

   /*
    * Look up the localized string, converting to requested encoding as needed.
    */

   if (source != NULL) {
      const void *retval = NULL;

      if (HashTable_Lookup(source, idBuf, (void **) &retval)) {
         strp = retval;
#if defined(_WIN32)
      } else if (encoding == STRING_ENCODING_UTF16_LE) {
         gchar *converted;
         Bool success;

         /*
          * Look up the string in UTF-8, convert it and cache it.
          */
         retval = MsgGetString(domain, msgid, STRING_ENCODING_UTF8);
         ASSERT(retval);

         converted = (gchar *) g_utf8_to_utf16(retval, -1, NULL, NULL, NULL);
         ASSERT(converted != NULL);

         success = HashTable_Insert(source, idBuf, converted);
         ASSERT(success);
         strp = converted;
#endif
      }
   }

   g_static_mutex_unlock(&state->lock);

   return strp;
}
Exemplo n.º 14
0
static void
VThreadBaseSimpleNoID(void)
{
   VThreadID newID;
   Bool reused = FALSE;
   Bool result;
   void *newNative = VThreadBaseGetNative();
   HashTable *ht = VThreadBaseGetNativeHash();
   VThreadBaseData *base;

   /* Require key allocation before TLS read */
   VThreadBaseGetKey();

   /* Before allocating a new ID, try to reclaim any old IDs. */
   for (newID = 0;
        newID < Atomic_Read(&vthreadBaseGlobals.dynamicID);
        newID++) {
      void *newKey = (void *)(uintptr_t)newID;

      /*
       * Windows: any entry that is found and not (alive or NULL)
       *    is reclaimable.  The check is slightly racy, but the race
       *    would only cause missing a reclaim which isn't a problem.
       * Posix: thread exit is hooked (via TLS destructor) and sets
       *    entries to NULL, so any entry that is NULL is reclaimable.
       */
#ifdef _WIN32
      void *oldNative;
      reused = HashTable_Lookup(ht, newKey, &oldNative) &&
               (oldNative == NULL ||
                !VThreadBaseNativeIsAlive(oldNative)) &&
               HashTable_ReplaceIfEqual(ht, newKey, oldNative, newNative);
#else
      reused = HashTable_ReplaceIfEqual(ht, newKey, NULL, newNative);
#endif
      if (reused) {
         break;
      }
   }

   if (!reused) {
      void *newKey;

      newID = Atomic_FetchAndInc(&vthreadBaseGlobals.dynamicID);
      /*
       * Detect VThreadID overflow (~0 is used as a sentinel).
       * Leave a space of ~10 IDs, since the increment and bounds-check
       * are not atomic.
       */
      ASSERT_NOT_IMPLEMENTED(newID < VTHREAD_INVALID_ID - 10);

      newKey = (void *)(uintptr_t)newID;
      result = HashTable_Insert(ht, newKey, newNative);
      ASSERT_NOT_IMPLEMENTED(result);
   }

   /* ID picked.  Now do the important stuff. */
   base = Util_SafeCalloc(1, sizeof *base);
   base->id = newID;
   Str_Sprintf(base->name, sizeof base->name, "vthread-%u", newID);

   result = VThreadBase_InitWithTLS(base);
   ASSERT(result);

   if (vmx86_debug && reused) {
      Log("VThreadBase reused VThreadID %d.\n", newID);
   }

   if (Atomic_Read(&vthreadBaseGlobals.numThreads) > 1) {
      LOG_ONCE(("VThreadBase detected multiple threads.\n"));
   }
}