Blame source/vdo/base/threadConfig.c

Packit Service d40955
/*
Packit Service d40955
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service d40955
 *
Packit Service d40955
 * This program is free software; you can redistribute it and/or
Packit Service d40955
 * modify it under the terms of the GNU General Public License
Packit Service d40955
 * as published by the Free Software Foundation; either version 2
Packit Service d40955
 * of the License, or (at your option) any later version.
Packit Service d40955
 * 
Packit Service d40955
 * This program is distributed in the hope that it will be useful,
Packit Service d40955
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service d40955
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service d40955
 * GNU General Public License for more details.
Packit Service d40955
 * 
Packit Service d40955
 * You should have received a copy of the GNU General Public License
Packit Service d40955
 * along with this program; if not, write to the Free Software
Packit Service d40955
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service d40955
 * 02110-1301, USA. 
Packit Service d40955
 *
Packit Service d40955
 * $Id: //eng/vdo-releases/aluminum/src/c++/vdo/base/threadConfig.c#2 $
Packit Service d40955
 */
Packit Service d40955
Packit Service d40955
#include "threadConfig.h"
Packit Service d40955
Packit Service d40955
#include "logger.h"
Packit Service d40955
#include "memoryAlloc.h"
Packit Service d40955
Packit Service d40955
#include "constants.h"
Packit Service d40955
#include "types.h"
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static int allocateThreadConfig(ZoneCount      logicalZoneCount,
Packit Service d40955
                                ZoneCount      physicalZoneCount,
Packit Service d40955
                                ZoneCount      hashZoneCount,
Packit Service d40955
                                ZoneCount      baseThreadCount,
Packit Service d40955
                                ThreadConfig **configPtr)
Packit Service d40955
{
Packit Service d40955
  ThreadConfig *config;
Packit Service d40955
  int result = ALLOCATE(1, ThreadConfig, "thread config", &config);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  result = ALLOCATE(logicalZoneCount, ThreadID, "logical thread array",
Packit Service d40955
                    &config->logicalThreads);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    freeThreadConfig(&config);
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  result = ALLOCATE(physicalZoneCount, ThreadID, "physical thread array",
Packit Service d40955
                    &config->physicalThreads);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    freeThreadConfig(&config);
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  result = ALLOCATE(hashZoneCount, ThreadID, "hash thread array",
Packit Service d40955
                    &config->hashZoneThreads);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    freeThreadConfig(&config);
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  config->logicalZoneCount  = logicalZoneCount;
Packit Service d40955
  config->physicalZoneCount = physicalZoneCount;
Packit Service d40955
  config->hashZoneCount     = hashZoneCount;
Packit Service d40955
  config->baseThreadCount   = baseThreadCount;
Packit Service d40955
Packit Service d40955
  *configPtr = config;
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static void assignThreadIDs(ThreadID   threadIDs[],
Packit Service d40955
                            ZoneCount  count,
Packit Service d40955
                            ThreadID  *idPtr)
Packit Service d40955
{
Packit Service d40955
  for (ZoneCount zone = 0; zone < count; zone++) {
Packit Service d40955
    threadIDs[zone] = (*idPtr)++;
Packit Service d40955
  }
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int makeThreadConfig(ZoneCount      logicalZoneCount,
Packit Service d40955
                     ZoneCount      physicalZoneCount,
Packit Service d40955
                     ZoneCount      hashZoneCount,
Packit Service d40955
                     ThreadConfig **configPtr)
Packit Service d40955
{
Packit Service d40955
  if ((logicalZoneCount == 0)
Packit Service d40955
      && (physicalZoneCount == 0)
Packit Service d40955
      && (hashZoneCount == 0)) {
Packit Service d40955
    return makeOneThreadConfig(configPtr);
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  if (physicalZoneCount > MAX_PHYSICAL_ZONES) {
Packit Service d40955
    return logErrorWithStringError(VDO_BAD_CONFIGURATION,
Packit Service d40955
                                   "Physical zone count %u exceeds maximum "
Packit Service d40955
                                   "(%u)",
Packit Service d40955
                                   physicalZoneCount, MAX_PHYSICAL_ZONES);
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  if (logicalZoneCount > MAX_LOGICAL_ZONES) {
Packit Service d40955
    return logErrorWithStringError(VDO_BAD_CONFIGURATION,
Packit Service d40955
                                   "Logical zone count %u exceeds maximum "
Packit Service d40955
                                   "(%u)",
Packit Service d40955
                                   logicalZoneCount, MAX_LOGICAL_ZONES);
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  ThreadConfig *config;
Packit Service d40955
  ThreadCount total = logicalZoneCount + physicalZoneCount + hashZoneCount + 2;
Packit Service d40955
  int result = allocateThreadConfig(logicalZoneCount, physicalZoneCount,
Packit Service d40955
                                    hashZoneCount, total, &config);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  ThreadID id = 0;
Packit Service d40955
  config->adminThread   = id;
Packit Service d40955
  config->journalThread = id++;
Packit Service d40955
  config->packerThread  = id++;
Packit Service d40955
  assignThreadIDs(config->logicalThreads, logicalZoneCount, &id;;
Packit Service d40955
  assignThreadIDs(config->physicalThreads, physicalZoneCount, &id;;
Packit Service d40955
  assignThreadIDs(config->hashZoneThreads, hashZoneCount, &id;;
Packit Service d40955
Packit Service d40955
  ASSERT_LOG_ONLY(id == total, "correct number of thread IDs assigned");
Packit Service d40955
Packit Service d40955
  *configPtr = config;
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int makeZeroThreadConfig(ThreadConfig **configPtr)
Packit Service d40955
{
Packit Service d40955
  ThreadConfig *config;
Packit Service d40955
  int result = ALLOCATE(1, ThreadConfig, __func__, &config);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  config->logicalZoneCount  = 0;
Packit Service d40955
  config->physicalZoneCount = 0;
Packit Service d40955
  config->hashZoneCount     = 0;
Packit Service d40955
  config->baseThreadCount   = 0;
Packit Service d40955
  *configPtr                = config;
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int makeOneThreadConfig(ThreadConfig **configPtr)
Packit Service d40955
{
Packit Service d40955
  ThreadConfig *config;
Packit Service d40955
  int result = allocateThreadConfig(1, 1, 1, 1, &config);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  config->logicalThreads[0]  = 0;
Packit Service d40955
  config->physicalThreads[0] = 0;
Packit Service d40955
  config->hashZoneThreads[0] = 0;
Packit Service d40955
  *configPtr = config;
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
int copyThreadConfig(const ThreadConfig *oldConfig, ThreadConfig **configPtr)
Packit Service d40955
{
Packit Service d40955
  ThreadConfig *config;
Packit Service d40955
  int result = allocateThreadConfig(oldConfig->logicalZoneCount,
Packit Service d40955
                                    oldConfig->physicalZoneCount,
Packit Service d40955
                                    oldConfig->hashZoneCount,
Packit Service d40955
                                    oldConfig->baseThreadCount,
Packit Service d40955
                                    &config);
Packit Service d40955
  if (result != VDO_SUCCESS) {
Packit Service d40955
    return result;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  config->adminThread   = oldConfig->adminThread;
Packit Service d40955
  config->journalThread = oldConfig->journalThread;
Packit Service d40955
  config->packerThread  = oldConfig->packerThread;
Packit Service d40955
  for (ZoneCount i = 0; i < config->logicalZoneCount; i++) {
Packit Service d40955
    config->logicalThreads[i] = oldConfig->logicalThreads[i];
Packit Service d40955
  }
Packit Service d40955
  for (ZoneCount i = 0; i < config->physicalZoneCount; i++) {
Packit Service d40955
    config->physicalThreads[i] = oldConfig->physicalThreads[i];
Packit Service d40955
  }
Packit Service d40955
  for (ZoneCount i = 0; i < config->hashZoneCount; i++) {
Packit Service d40955
    config->hashZoneThreads[i] = oldConfig->hashZoneThreads[i];
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  *configPtr = config;
Packit Service d40955
  return VDO_SUCCESS;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void freeThreadConfig(ThreadConfig **configPtr)
Packit Service d40955
{
Packit Service d40955
  if (*configPtr == NULL) {
Packit Service d40955
    return;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  ThreadConfig *config = *configPtr;
Packit Service d40955
  *configPtr           = NULL;
Packit Service d40955
Packit Service d40955
  FREE(config->logicalThreads);
Packit Service d40955
  FREE(config->physicalThreads);
Packit Service d40955
  FREE(config->hashZoneThreads);
Packit Service d40955
  FREE(config);
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
static bool getZoneThreadName(const ThreadID  threadIDs[],
Packit Service d40955
                              ZoneCount       count,
Packit Service d40955
                              ThreadID        id,
Packit Service d40955
                              const char     *prefix,
Packit Service d40955
                              char           *buffer,
Packit Service d40955
                              size_t          bufferLength)
Packit Service d40955
{
Packit Service d40955
  if (id >= threadIDs[0]) {
Packit Service d40955
    ThreadID index = id - threadIDs[0];
Packit Service d40955
    if (index < count) {
Packit Service d40955
      snprintf(buffer, bufferLength, "%s%d", prefix, index);
Packit Service d40955
      return true;
Packit Service d40955
    }
Packit Service d40955
  }
Packit Service d40955
  return false;
Packit Service d40955
}
Packit Service d40955
Packit Service d40955
/**********************************************************************/
Packit Service d40955
void getVDOThreadName(const ThreadConfig *threadConfig,
Packit Service d40955
                      ThreadID            threadID,
Packit Service d40955
                      char               *buffer,
Packit Service d40955
                      size_t              bufferLength)
Packit Service d40955
{
Packit Service d40955
  if (threadConfig->baseThreadCount == 1) {
Packit Service d40955
    // Historically this was the "request queue" thread.
Packit Service d40955
    snprintf(buffer, bufferLength, "reqQ");
Packit Service d40955
    return;
Packit Service d40955
  }
Packit Service d40955
  if (threadID == threadConfig->journalThread) {
Packit Service d40955
    snprintf(buffer, bufferLength, "journalQ");
Packit Service d40955
    return;
Packit Service d40955
  } else if (threadID == threadConfig->adminThread) {
Packit Service d40955
    // Theoretically this could be different from the journal thread.
Packit Service d40955
    snprintf(buffer, bufferLength, "adminQ");
Packit Service d40955
    return;
Packit Service d40955
  } else if (threadID == threadConfig->packerThread) {
Packit Service d40955
    snprintf(buffer, bufferLength, "packerQ");
Packit Service d40955
    return;
Packit Service d40955
  }
Packit Service d40955
  if (getZoneThreadName(threadConfig->logicalThreads,
Packit Service d40955
                        threadConfig->logicalZoneCount,
Packit Service d40955
                        threadID, "logQ", buffer, bufferLength)) {
Packit Service d40955
    return;
Packit Service d40955
  }
Packit Service d40955
  if (getZoneThreadName(threadConfig->physicalThreads,
Packit Service d40955
                        threadConfig->physicalZoneCount,
Packit Service d40955
                        threadID, "physQ", buffer, bufferLength)) {
Packit Service d40955
    return;
Packit Service d40955
  }
Packit Service d40955
  if (getZoneThreadName(threadConfig->hashZoneThreads,
Packit Service d40955
                        threadConfig->hashZoneCount,
Packit Service d40955
                        threadID, "hashQ", buffer, bufferLength)) {
Packit Service d40955
    return;
Packit Service d40955
  }
Packit Service d40955
Packit Service d40955
  // Some sort of misconfiguration?
Packit Service d40955
  snprintf(buffer, bufferLength, "reqQ%d", threadID);
Packit Service d40955
}