<commit_before>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <string>
#include <string.h>

#include "common.h"
#include "bzfgl.h"
#include "TextureManager.h"
#include "TextureFont.h"
#include "bzfio.h"

#include "OpenGLGState.h"

TextureFont::TextureFont()
{
  for (int i = 0; i < MAX_TEXTURE_FONT_CHARS; i++) {
    listIDs[i] = INVALID_GL_LIST_ID;
    fontMetrics[i].charWidth = -1;
  }

  size = -1;
  textureID = -1;

  textureXSize = -1;
  textureYSize = -1;
  textureZStep = -1;
  numberOfCharacters = -1;
}

TextureFont::~TextureFont()
{
  for (int i = 0; i < MAX_TEXTURE_FONT_CHARS; i++) {
    if (listIDs[i] != INVALID_GL_LIST_ID) {
      glDeleteLists(listIDs[i], 1);
      listIDs[i] = INVALID_GL_LIST_ID;
    }
  }
}

int TextureFont::getSize()
{
  return size;
}

const char* TextureFont::getFaceName()
{
  return faceName.c_str();
}

// keep a line counter for debugging
static int line;

/* read values in Key: Value form from font metrics (.fmt) files */
bool readKeyInt(OSFile &file, std::string expectedLeft, int &retval, bool newfile=false)
{
  if (newfile)
    line = 0;

  const int expsize = int(expectedLeft.size());
  std::string tmpBuf;

  // allow for blank lines with native or foreign linebreaks, comment lines
  while (tmpBuf.size() == 0 || tmpBuf[0] == '#' || tmpBuf[0] == 10 || tmpBuf[0] == 13) {
    tmpBuf = file.readLine();
    line++;
  }

  if (tmpBuf.compare(0, expsize, expectedLeft) == 0 && tmpBuf[expsize]==':') {
    retval = atoi(tmpBuf.c_str()+expsize+1);
    return true;
  } else {
    DEBUG2("Unexpected line in font metrics file %s, line %d (expected %s)\n",
      file.getFileName().c_str(), line, expectedLeft.c_str());
    return false;
  }
}

// read Char: "x" entry
bool readLetter(OSFile &file, char expected)
{
  const std::string expectedLeft = "Char:";
  const int expsize = int(expectedLeft.size());
  std::string tmpBuf;

  // allow for blank lines with native or foreign linebreaks, comment lines
  while (tmpBuf.size() == 0 || tmpBuf[0] == '#' || tmpBuf[0] == 10 || tmpBuf[0] == 13) {
    tmpBuf = file.readLine();
    // keep a line counter
    line++;
  }

  if (tmpBuf.compare(0, expsize, expectedLeft) == 0) {
    if (int(tmpBuf.size()) >= expsize+4 && tmpBuf[expsize+1]=='"' && tmpBuf[expsize+3]=='"' &&
        tmpBuf[expsize+2]==expected) {
      return true;
    } else {
      DEBUG2("Unexpected character: %s, in font metrics file %s, line %d (expected \"%c\").\n",
             tmpBuf.c_str()+expsize, file.getFileName().c_str(), line, expected);
      return false;
    }
  } else {
    DEBUG2("Unexpected line in font metrics file %s, line %d (expected %s)\n",
      file.getFileName().c_str(), line, expectedLeft.c_str());
    return false;
  }
}

bool TextureFont::load(OSFile &file)
{
  std::string extension = file.getExtension();

  if (extension=="")
    return false;

  texture = file.getFileName();
  std::string::size_type underscore = texture.rfind('_');
  if (underscore == std::string::npos) {
    DEBUG1("Unexpected font file name: %s, no _size found\n", file.getStdName().c_str());
    return false;
  }
  faceName = texture.substr(0, underscore);
  size = atoi(texture.c_str() + underscore + 1);

  if (!file.open("rb"))
    return false;

  if (!readKeyInt(file, "NumChars", numberOfCharacters, true)) return false;
  if (!readKeyInt(file, "TextureWidth", textureXSize)) return false;
  if (!readKeyInt(file, "TextureHeight", textureYSize)) return false;
  if (!readKeyInt(file, "TextZStep", textureZStep)) return false;

  // clamp the maximum char count
  if (numberOfCharacters > MAX_TEXTURE_FONT_CHARS) {
    DEBUG1("Too many characters (%i) in %s.\n",
	   numberOfCharacters, file.getFileName().c_str());
    numberOfCharacters = MAX_TEXTURE_FONT_CHARS;
  }

  int i;
  for (i = 0; i < numberOfCharacters; i++) {
    // check character
    if (!readLetter(file, i + 32)) return false;

    // read metrics
    if (!readKeyInt(file, "InitialDist", fontMetrics[i].initialDist)) return false;
    if (!readKeyInt(file, "Width", fontMetrics[i].charWidth)) return false;
    if (!readKeyInt(file, "Whitespace", fontMetrics[i].whiteSpaceDist)) return false;
    if (!readKeyInt(file, "StartX", fontMetrics[i].startX)) return false;
    if (!readKeyInt(file, "EndX", fontMetrics[i].endX)) return false;
    if (!readKeyInt(file, "StartY", fontMetrics[i].startY)) return false;
    if (!readKeyInt(file, "EndY", fontMetrics[i].endY)) return false;
  }

  file.close();

  return (numberOfCharacters > 0);
}

void TextureFont::build(void)
{
  preLoadLists();
}

void TextureFont::preLoadLists(void)
{
  if (texture.size() < 1) {
    DEBUG2("Font %s does not have an associated texture name, not loading\n", texture.c_str());
    return;
  }

  // load up the texture
  TextureManager &tm = TextureManager::instance();
  std::string textureAndDir = "fonts/" + texture;
  textureID = tm.getTextureID(textureAndDir.c_str());

  DEBUG4("Font %s (face %s) has texture ID %d\n", texture.c_str(), faceName.c_str(), textureID);

  if (textureID == -1) {
    DEBUG2("Font texture %s has invalid ID\n", texture.c_str());
    return;
  }

  for (int i = 0; i < numberOfCharacters; i++) {
    if (listIDs[i] != INVALID_GL_LIST_ID) {
      glDeleteLists(listIDs[i], 1);
      listIDs[i] = INVALID_GL_LIST_ID; // make it a habit
    }
    listIDs[i] = glGenLists(1);
    glNewList(listIDs[i], GL_COMPILE);
    {
      glTranslatef((float)fontMetrics[i].initialDist, 0, 0);

      float fFontY = (float)fontMetrics[i].endY - fontMetrics[i].startY;
      float fFontX = (float)fontMetrics[i].endX - fontMetrics[i].startX;

      glBegin(GL_QUADS);
	glNormal3f(0.0f, 0.0f, 1.0f);
	glTexCoord2f((float)fontMetrics[i].startX / (float)textureXSize,
		     1.0f - (float)fontMetrics[i].startY / (float)textureYSize);
	glVertex3f(0.0f, fFontY, 0.0f);

	glTexCoord2f((float)fontMetrics[i].startX / (float)textureXSize,
		     1.0f - (float)fontMetrics[i].endY / (float)textureYSize);
	glVertex3f(0.0f, 0.0f, 0.0f);

	glTexCoord2f((float)fontMetrics[i].endX / (float)textureXSize,
		     1.0f - (float)fontMetrics[i].endY / (float)textureYSize);
	glVertex3f(fFontX, 0.0f, 0.0f);

	glTexCoord2f((float)fontMetrics[i].endX / (float)textureXSize,
		     1.0f - (float)fontMetrics[i].startY / (float)textureYSize);
	glVertex3f(fFontX, fFontY, 0.0f);
      glEnd();

      glTranslatef(fFontX, 0.0f, 0.0f);
    }
    glEndList();
  }

  // create GState
  OpenGLGStateBuilder builder(gstate);
  builder.setTexture(textureID);
  builder.setBlending();
  builder.setAlphaFunc();
  builder.enableTextureReplace(false);
  gstate = builder.getState();
}

float TextureFont::getStrLength(float scale, const char *str, int len)
{
  int charToUse = 0;
  int lastCharacter = 0;

  float totalLen = 0;

  for (int i = 0; i < len; i++) {
    lastCharacter = charToUse;
    if (str[i] < 32)
      charToUse = 32;
    else if (str[i] > numberOfCharacters + 32)
      charToUse = 32;
    else
      charToUse = str[i];

    charToUse -= 32;

    if (charToUse == 0) {
      totalLen += fontMetrics[charToUse].initialDist +
		  fontMetrics[charToUse].charWidth +
		  fontMetrics[charToUse].whiteSpaceDist;
    } else {
      totalLen += fontMetrics[charToUse].endX -
		  fontMetrics[charToUse].startX +
		  fontMetrics[charToUse].initialDist;
    }
  }

  return totalLen * scale;
}

void TextureFont::free(void)
{
  textureID = -1;
}

void TextureFont::drawString(float scale, GLfloat color[3], const char *str,
			     int len)
{
  if (!str)
    return;

  if (textureID == -1)
    preLoadLists();

  if (textureID == -1)
    return;

  gstate.setState();

  TextureManager &tm = TextureManager::instance();
  if (!tm.bind(textureID))
    return;

  if (color[0] >= 0)
    glColor3fv(color);

  glPushMatrix();
  glScalef(scale, scale, 1);

  glPushMatrix();
  int charToUse = 0;
  int lastCharacter = 0;
  for (int i = 0; i < len; i++) {
    lastCharacter = charToUse;
    const char space = ' '; // decimal 32
    if (str[i] < space) {
      charToUse = space;
    } else if (str[i] > (numberOfCharacters + space)) {
      charToUse = space;
    } else {
      charToUse = str[i];
    }

    charToUse -= space;

    if (charToUse == 0) {
      glTranslatef((float)fontMetrics[charToUse].initialDist +
		   (float)fontMetrics[charToUse].charWidth +
		   (float)fontMetrics[charToUse].whiteSpaceDist, 0.0f, 0.0f);
    } else {
      glCallList(listIDs[charToUse]);
    }
  }
  glPopMatrix();
  if (color[0] >= 0)
    glColor4f(1, 1, 1, 1);
  glPopMatrix();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>g++ 2.95 has no substring compare function, so use less efficient way that should work for everybody<commit_after>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <string>
#include <string.h>

#include "common.h"
#include "bzfgl.h"
#include "TextureManager.h"
#include "TextureFont.h"
#include "bzfio.h"

#include "OpenGLGState.h"

TextureFont::TextureFont()
{
  for (int i = 0; i < MAX_TEXTURE_FONT_CHARS; i++) {
    listIDs[i] = INVALID_GL_LIST_ID;
    fontMetrics[i].charWidth = -1;
  }

  size = -1;
  textureID = -1;

  textureXSize = -1;
  textureYSize = -1;
  textureZStep = -1;
  numberOfCharacters = -1;
}

TextureFont::~TextureFont()
{
  for (int i = 0; i < MAX_TEXTURE_FONT_CHARS; i++) {
    if (listIDs[i] != INVALID_GL_LIST_ID) {
      glDeleteLists(listIDs[i], 1);
      listIDs[i] = INVALID_GL_LIST_ID;
    }
  }
}

int TextureFont::getSize()
{
  return size;
}

const char* TextureFont::getFaceName()
{
  return faceName.c_str();
}

// keep a line counter for debugging
static int line;

/* read values in Key: Value form from font metrics (.fmt) files */
bool readKeyInt(OSFile &file, std::string expectedLeft, int &retval, bool newfile=false)
{
  if (newfile)
    line = 0;

  const int expsize = int(expectedLeft.size());
  std::string tmpBuf;

  // allow for blank lines with native or foreign linebreaks, comment lines
  while (tmpBuf.size() == 0 || tmpBuf[0] == '#' || tmpBuf[0] == 10 || tmpBuf[0] == 13) {
    tmpBuf = file.readLine();
    line++;
  }

  if (tmpBuf.substr(0, expsize) == expectedLeft && tmpBuf[expsize]==':') {
    retval = atoi(tmpBuf.c_str()+expsize+1);
    return true;
  } else {
    DEBUG2("Unexpected line in font metrics file %s, line %d (expected %s)\n",
      file.getFileName().c_str(), line, expectedLeft.c_str());
    return false;
  }
}

// read Char: "x" entry
bool readLetter(OSFile &file, char expected)
{
  const std::string expectedLeft = "Char:";
  const int expsize = int(expectedLeft.size());
  std::string tmpBuf;

  // allow for blank lines with native or foreign linebreaks, comment lines
  while (tmpBuf.size() == 0 || tmpBuf[0] == '#' || tmpBuf[0] == 10 || tmpBuf[0] == 13) {
    tmpBuf = file.readLine();
    // keep a line counter
    line++;
  }

  if (tmpBuf.substr(0, expsize) == expectedLeft) {
    if (int(tmpBuf.size()) >= expsize+4 && tmpBuf[expsize+1]=='"' && tmpBuf[expsize+3]=='"' &&
        tmpBuf[expsize+2]==expected) {
      return true;
    } else {
      DEBUG2("Unexpected character: %s, in font metrics file %s, line %d (expected \"%c\").\n",
             tmpBuf.c_str()+expsize, file.getFileName().c_str(), line, expected);
      return false;
    }
  } else {
    DEBUG2("Unexpected line in font metrics file %s, line %d (expected %s)\n",
      file.getFileName().c_str(), line, expectedLeft.c_str());
    return false;
  }
}

bool TextureFont::load(OSFile &file)
{
  std::string extension = file.getExtension();

  if (extension=="")
    return false;

  texture = file.getFileName();
  std::string::size_type underscore = texture.rfind('_');
  if (underscore == std::string::npos) {
    DEBUG1("Unexpected font file name: %s, no _size found\n", file.getStdName().c_str());
    return false;
  }
  faceName = texture.substr(0, underscore);
  size = atoi(texture.c_str() + underscore + 1);

  if (!file.open("rb"))
    return false;

  if (!readKeyInt(file, "NumChars", numberOfCharacters, true)) return false;
  if (!readKeyInt(file, "TextureWidth", textureXSize)) return false;
  if (!readKeyInt(file, "TextureHeight", textureYSize)) return false;
  if (!readKeyInt(file, "TextZStep", textureZStep)) return false;

  // clamp the maximum char count
  if (numberOfCharacters > MAX_TEXTURE_FONT_CHARS) {
    DEBUG1("Too many characters (%i) in %s.\n",
	   numberOfCharacters, file.getFileName().c_str());
    numberOfCharacters = MAX_TEXTURE_FONT_CHARS;
  }

  int i;
  for (i = 0; i < numberOfCharacters; i++) {
    // check character
    if (!readLetter(file, i + 32)) return false;

    // read metrics
    if (!readKeyInt(file, "InitialDist", fontMetrics[i].initialDist)) return false;
    if (!readKeyInt(file, "Width", fontMetrics[i].charWidth)) return false;
    if (!readKeyInt(file, "Whitespace", fontMetrics[i].whiteSpaceDist)) return false;
    if (!readKeyInt(file, "StartX", fontMetrics[i].startX)) return false;
    if (!readKeyInt(file, "EndX", fontMetrics[i].endX)) return false;
    if (!readKeyInt(file, "StartY", fontMetrics[i].startY)) return false;
    if (!readKeyInt(file, "EndY", fontMetrics[i].endY)) return false;
  }

  file.close();

  return (numberOfCharacters > 0);
}

void TextureFont::build(void)
{
  preLoadLists();
}

void TextureFont::preLoadLists(void)
{
  if (texture.size() < 1) {
    DEBUG2("Font %s does not have an associated texture name, not loading\n", texture.c_str());
    return;
  }

  // load up the texture
  TextureManager &tm = TextureManager::instance();
  std::string textureAndDir = "fonts/" + texture;
  textureID = tm.getTextureID(textureAndDir.c_str());

  DEBUG4("Font %s (face %s) has texture ID %d\n", texture.c_str(), faceName.c_str(), textureID);

  if (textureID == -1) {
    DEBUG2("Font texture %s has invalid ID\n", texture.c_str());
    return;
  }

  for (int i = 0; i < numberOfCharacters; i++) {
    if (listIDs[i] != INVALID_GL_LIST_ID) {
      glDeleteLists(listIDs[i], 1);
      listIDs[i] = INVALID_GL_LIST_ID; // make it a habit
    }
    listIDs[i] = glGenLists(1);
    glNewList(listIDs[i], GL_COMPILE);
    {
      glTranslatef((float)fontMetrics[i].initialDist, 0, 0);

      float fFontY = (float)fontMetrics[i].endY - fontMetrics[i].startY;
      float fFontX = (float)fontMetrics[i].endX - fontMetrics[i].startX;

      glBegin(GL_QUADS);
	glNormal3f(0.0f, 0.0f, 1.0f);
	glTexCoord2f((float)fontMetrics[i].startX / (float)textureXSize,
		     1.0f - (float)fontMetrics[i].startY / (float)textureYSize);
	glVertex3f(0.0f, fFontY, 0.0f);

	glTexCoord2f((float)fontMetrics[i].startX / (float)textureXSize,
		     1.0f - (float)fontMetrics[i].endY / (float)textureYSize);
	glVertex3f(0.0f, 0.0f, 0.0f);

	glTexCoord2f((float)fontMetrics[i].endX / (float)textureXSize,
		     1.0f - (float)fontMetrics[i].endY / (float)textureYSize);
	glVertex3f(fFontX, 0.0f, 0.0f);

	glTexCoord2f((float)fontMetrics[i].endX / (float)textureXSize,
		     1.0f - (float)fontMetrics[i].startY / (float)textureYSize);
	glVertex3f(fFontX, fFontY, 0.0f);
      glEnd();

      glTranslatef(fFontX, 0.0f, 0.0f);
    }
    glEndList();
  }

  // create GState
  OpenGLGStateBuilder builder(gstate);
  builder.setTexture(textureID);
  builder.setBlending();
  builder.setAlphaFunc();
  builder.enableTextureReplace(false);
  gstate = builder.getState();
}

float TextureFont::getStrLength(float scale, const char *str, int len)
{
  int charToUse = 0;
  int lastCharacter = 0;

  float totalLen = 0;

  for (int i = 0; i < len; i++) {
    lastCharacter = charToUse;
    if (str[i] < 32)
      charToUse = 32;
    else if (str[i] > numberOfCharacters + 32)
      charToUse = 32;
    else
      charToUse = str[i];

    charToUse -= 32;

    if (charToUse == 0) {
      totalLen += fontMetrics[charToUse].initialDist +
		  fontMetrics[charToUse].charWidth +
		  fontMetrics[charToUse].whiteSpaceDist;
    } else {
      totalLen += fontMetrics[charToUse].endX -
		  fontMetrics[charToUse].startX +
		  fontMetrics[charToUse].initialDist;
    }
  }

  return totalLen * scale;
}

void TextureFont::free(void)
{
  textureID = -1;
}

void TextureFont::drawString(float scale, GLfloat color[3], const char *str,
			     int len)
{
  if (!str)
    return;

  if (textureID == -1)
    preLoadLists();

  if (textureID == -1)
    return;

  gstate.setState();

  TextureManager &tm = TextureManager::instance();
  if (!tm.bind(textureID))
    return;

  if (color[0] >= 0)
    glColor3fv(color);

  glPushMatrix();
  glScalef(scale, scale, 1);

  glPushMatrix();
  int charToUse = 0;
  int lastCharacter = 0;
  for (int i = 0; i < len; i++) {
    lastCharacter = charToUse;
    const char space = ' '; // decimal 32
    if (str[i] < space) {
      charToUse = space;
    } else if (str[i] > (numberOfCharacters + space)) {
      charToUse = space;
    } else {
      charToUse = str[i];
    }

    charToUse -= space;

    if (charToUse == 0) {
      glTranslatef((float)fontMetrics[charToUse].initialDist +
		   (float)fontMetrics[charToUse].charWidth +
		   (float)fontMetrics[charToUse].whiteSpaceDist, 0.0f, 0.0f);
    } else {
      glCallList(listIDs[charToUse]);
    }
  }
  glPopMatrix();
  if (color[0] >= 0)
    glColor4f(1, 1, 1, 1);
  glPopMatrix();
}

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2016 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <algorithm>

#include <boost/lexical_cast.hpp>

#include "cluster-controller/http-communication-manager/LongPollingMessageReceiver.h"
#include "cluster-controller/httpnetworking/HttpNetworking.h"
#include "joynr/Util.h"
#include "joynr/DispatcherUtils.h"
#include "cluster-controller/httpnetworking/HttpResult.h"
#include "joynr/Future.h"
#include "joynr/JoynrMessage.h"
#include "joynr/system/RoutingTypes/ChannelAddress.h"
#include "joynr/MessageRouter.h"
#include "joynr/JoynrMessage.h"

namespace joynr
{

INIT_LOGGER(LongPollingMessageReceiver);

LongPollingMessageReceiver::LongPollingMessageReceiver(
        const BrokerUrl& brokerUrl,
        const std::string& channelId,
        const std::string& receiverId,
        const LongPollingMessageReceiverSettings& settings,
        std::shared_ptr<Semaphore> channelCreatedSemaphore,
        std::function<void(const std::string&)> onTextMessageReceived)
        : Thread("LongPollRecv"),
          brokerUrl(brokerUrl),
          channelId(channelId),
          receiverId(receiverId),
          settings(settings),
          interrupted(false),
          interruptedMutex(),
          interruptedWait(),
          channelCreatedSemaphore(channelCreatedSemaphore),
          onTextMessageReceived(onTextMessageReceived)
{
}

LongPollingMessageReceiver::~LongPollingMessageReceiver()
{
    stop();
}

void LongPollingMessageReceiver::interrupt()
{
    interrupted = true;
    interruptedWait.notify_all();
}

bool LongPollingMessageReceiver::isInterrupted()
{
    return interrupted;
}

void LongPollingMessageReceiver::stop()
{
    interrupt();
    Thread::stop();
}

void LongPollingMessageReceiver::run()
{
    checkServerTime();
    std::string createChannelUrl = brokerUrl.getCreateChannelUrl(channelId).toString();
    JOYNR_LOG_INFO(logger, "Running lpmr with channelId {}", channelId);
    std::shared_ptr<IHttpPostBuilder> createChannelRequestBuilder(
            HttpNetworking::getInstance()->createHttpPostBuilder(createChannelUrl));
    std::shared_ptr<HttpRequest> createChannelRequest(
            createChannelRequestBuilder->addHeader("X-Atmosphere-tracking-id", receiverId)
                    ->withContentType("application/json")
                    ->withTimeout(settings.brokerTimeout)
                    ->build());

    std::string channelUrl;
    while (channelUrl.empty() && !isInterrupted()) {
        JOYNR_LOG_DEBUG(logger, "sending create channel request");
        HttpResult createChannelResult = createChannelRequest->execute();
        if (createChannelResult.getStatusCode() == 201) {
            const std::unordered_multimap<std::string, std::string>& headers =
                    createChannelResult.getHeaders();
            auto it = headers.find("Location");
            channelUrl = it->second;
            JOYNR_LOG_INFO(logger, "channel creation successfull; channel url: {}", channelUrl);
            channelCreatedSemaphore->notify();
        } else {
            JOYNR_LOG_INFO(logger,
                           "channel creation failed); status code: {}",
                           createChannelResult.getStatusCode());
            std::unique_lock<std::mutex> lock(interruptedMutex);
            interruptedWait.wait_for(lock, settings.createChannelRetryInterval);
        }
    }

    // TODO: The received URL must be forwarded in such a way that ChannelAddress objects use it.

    while (!isInterrupted()) {

        std::shared_ptr<IHttpGetBuilder> longPollRequestBuilder(
                HttpNetworking::getInstance()->createHttpGetBuilder(channelUrl));

        std::shared_ptr<HttpRequest> longPollRequest(
                longPollRequestBuilder->acceptGzip()
                        ->addHeader("Accept", "application/json")
                        ->addHeader("X-Atmosphere-tracking-id", receiverId)
                        ->withTimeout(settings.longPollTimeout)
                        ->build());

        JOYNR_LOG_DEBUG(logger, "sending long polling request; url: {}", channelUrl);
        HttpResult longPollingResult = longPollRequest->execute();
        if (!isInterrupted()) {
            // TODO: remove HttpErrorCodes and use constants.
            // there is a bug in atmosphere, which currently gives back 503 instead of 200 as a
            // result to longpolling.
            // Accepting 503 is a temporary workaround for this bug. As soon as atmosphere is fixed,
            // this should be removed
            // 200 does nott refect the state of the message body! It could be empty.
            if (longPollingResult.getStatusCode() == 200 ||
                longPollingResult.getStatusCode() == 503) {
                util::logSerializedMessage(
                        logger, "long polling successful; contents: ", longPollingResult.getBody());
                processReceivedInput(longPollingResult.getBody());
                // Atmosphere currently cannot return 204 when a long poll times out, so this code
                // is currently never executed (2.2.2012)
            } else if (longPollingResult.getStatusCode() == 204) {
                JOYNR_LOG_DEBUG(logger, "long polling successfull);full; no data");
            } else {
                std::string body("NULL");
                if (!longPollingResult.getBody().empty()) {
                    body = longPollingResult.getBody();
                }
                JOYNR_LOG_ERROR(logger,
                                "long polling failed; error message: {}; contents: {}",
                                longPollingResult.getErrorMessage(),
                                body);
                std::unique_lock<std::mutex> lock(interruptedMutex);
                interruptedWait.wait_for(lock, settings.createChannelRetryInterval);
            }
        }
    }
}

void LongPollingMessageReceiver::processReceivedInput(const std::string& receivedInput)
{
    std::vector<std::string> jsonObjects = util::splitIntoJsonObjects(receivedInput);
    for (std::size_t i = 0; i < jsonObjects.size(); i++) {
        processReceivedJsonObjects(jsonObjects.at(i));
    }
}

void LongPollingMessageReceiver::processReceivedJsonObjects(const std::string& jsonObject)
{
    if (onTextMessageReceived) {
        onTextMessageReceived(jsonObject);
    } else {
        JOYNR_LOG_ERROR(
                logger,
                "Discarding received message, since onTextMessageReceived callback is empty.");
    }
}

void LongPollingMessageReceiver::checkServerTime()
{
    std::string timeCheckUrl = brokerUrl.getTimeCheckUrl().toString();

    IHttpGetBuilder* timeCheckRequestBuilder =
            HttpNetworking::getInstance()->createHttpGetBuilder(timeCheckUrl);
    std::shared_ptr<HttpRequest> timeCheckRequest(
            timeCheckRequestBuilder->addHeader("Accept", "text/plain")
                    ->withTimeout(settings.brokerTimeout)
                    ->build());
    delete timeCheckRequestBuilder;
    timeCheckRequestBuilder = nullptr;
    JOYNR_LOG_DEBUG(logger, "CheckServerTime: sending request to Bounce Proxy ({})", timeCheckUrl);
    std::chrono::system_clock::time_point localTimeBeforeRequest = std::chrono::system_clock::now();
    HttpResult timeCheckResult = timeCheckRequest->execute();
    std::chrono::system_clock::time_point localTimeAfterRequest = std::chrono::system_clock::now();
    std::uint64_t localTime = (util::toMilliseconds(localTimeBeforeRequest) +
                               util::toMilliseconds(localTimeAfterRequest)) /
                              2;
    if (timeCheckResult.getStatusCode() != 200) {
        JOYNR_LOG_ERROR(logger,
                        "CheckServerTime: Bounce Proxy not reached [statusCode={}] [body={}]",
                        timeCheckResult.getStatusCode(),
                        timeCheckResult.getBody());
    } else {
        JOYNR_LOG_TRACE(logger,
                        "CheckServerTime: reply received [statusCode={}] [body={}]",
                        timeCheckResult.getStatusCode(),
                        timeCheckResult.getBody());
        std::uint64_t serverTime = boost::lexical_cast<std::uint64_t>(timeCheckResult.getBody());

        auto minMaxTime = std::minmax(serverTime, localTime);
        std::uint64_t diff = minMaxTime.second - minMaxTime.first;

        JOYNR_LOG_INFO(logger,
                       "CheckServerTime [server time={}] [local time={}] [diff={} ms]",
                       util::toDateString(JoynrTimePoint(std::chrono::milliseconds(serverTime))),
                       util::toDateString(JoynrTimePoint(std::chrono::milliseconds(localTime))),
                       diff);

        if (diff > 500) {
            JOYNR_LOG_ERROR(logger, "CheckServerTime: time difference to server is {} ms", diff);
        }
    }
}

} // namespace joynr
<commit_msg>[C++] added missing mutex lock in LPMR<commit_after>/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2016 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <algorithm>

#include <boost/lexical_cast.hpp>

#include "cluster-controller/http-communication-manager/LongPollingMessageReceiver.h"
#include "cluster-controller/httpnetworking/HttpNetworking.h"
#include "joynr/Util.h"
#include "joynr/DispatcherUtils.h"
#include "cluster-controller/httpnetworking/HttpResult.h"
#include "joynr/Future.h"
#include "joynr/JoynrMessage.h"
#include "joynr/system/RoutingTypes/ChannelAddress.h"
#include "joynr/MessageRouter.h"
#include "joynr/JoynrMessage.h"

namespace joynr
{

INIT_LOGGER(LongPollingMessageReceiver);

LongPollingMessageReceiver::LongPollingMessageReceiver(
        const BrokerUrl& brokerUrl,
        const std::string& channelId,
        const std::string& receiverId,
        const LongPollingMessageReceiverSettings& settings,
        std::shared_ptr<Semaphore> channelCreatedSemaphore,
        std::function<void(const std::string&)> onTextMessageReceived)
        : Thread("LongPollRecv"),
          brokerUrl(brokerUrl),
          channelId(channelId),
          receiverId(receiverId),
          settings(settings),
          interrupted(false),
          interruptedMutex(),
          interruptedWait(),
          channelCreatedSemaphore(channelCreatedSemaphore),
          onTextMessageReceived(onTextMessageReceived)
{
}

LongPollingMessageReceiver::~LongPollingMessageReceiver()
{
    stop();
}

void LongPollingMessageReceiver::interrupt()
{
    std::unique_lock<std::mutex> lock(interruptedMutex);
    interrupted = true;
    interruptedWait.notify_all();
}

bool LongPollingMessageReceiver::isInterrupted()
{
    return interrupted;
}

void LongPollingMessageReceiver::stop()
{
    interrupt();
    Thread::stop();
}

void LongPollingMessageReceiver::run()
{
    checkServerTime();
    std::string createChannelUrl = brokerUrl.getCreateChannelUrl(channelId).toString();
    JOYNR_LOG_INFO(logger, "Running lpmr with channelId {}", channelId);
    std::shared_ptr<IHttpPostBuilder> createChannelRequestBuilder(
            HttpNetworking::getInstance()->createHttpPostBuilder(createChannelUrl));
    std::shared_ptr<HttpRequest> createChannelRequest(
            createChannelRequestBuilder->addHeader("X-Atmosphere-tracking-id", receiverId)
                    ->withContentType("application/json")
                    ->withTimeout(settings.brokerTimeout)
                    ->build());

    std::string channelUrl;
    while (channelUrl.empty() && !isInterrupted()) {
        JOYNR_LOG_DEBUG(logger, "sending create channel request");
        HttpResult createChannelResult = createChannelRequest->execute();
        if (createChannelResult.getStatusCode() == 201) {
            const std::unordered_multimap<std::string, std::string>& headers =
                    createChannelResult.getHeaders();
            auto it = headers.find("Location");
            channelUrl = it->second;
            JOYNR_LOG_INFO(logger, "channel creation successfull; channel url: {}", channelUrl);
            channelCreatedSemaphore->notify();
        } else {
            JOYNR_LOG_INFO(logger,
                           "channel creation failed); status code: {}",
                           createChannelResult.getStatusCode());
            std::unique_lock<std::mutex> lock(interruptedMutex);
            interruptedWait.wait_for(lock, settings.createChannelRetryInterval);
        }
    }

    // TODO: The received URL must be forwarded in such a way that ChannelAddress objects use it.

    while (!isInterrupted()) {

        std::shared_ptr<IHttpGetBuilder> longPollRequestBuilder(
                HttpNetworking::getInstance()->createHttpGetBuilder(channelUrl));

        std::shared_ptr<HttpRequest> longPollRequest(
                longPollRequestBuilder->acceptGzip()
                        ->addHeader("Accept", "application/json")
                        ->addHeader("X-Atmosphere-tracking-id", receiverId)
                        ->withTimeout(settings.longPollTimeout)
                        ->build());

        JOYNR_LOG_DEBUG(logger, "sending long polling request; url: {}", channelUrl);
        HttpResult longPollingResult = longPollRequest->execute();
        if (!isInterrupted()) {
            // TODO: remove HttpErrorCodes and use constants.
            // there is a bug in atmosphere, which currently gives back 503 instead of 200 as a
            // result to longpolling.
            // Accepting 503 is a temporary workaround for this bug. As soon as atmosphere is fixed,
            // this should be removed
            // 200 does nott refect the state of the message body! It could be empty.
            if (longPollingResult.getStatusCode() == 200 ||
                longPollingResult.getStatusCode() == 503) {
                util::logSerializedMessage(
                        logger, "long polling successful; contents: ", longPollingResult.getBody());
                processReceivedInput(longPollingResult.getBody());
                // Atmosphere currently cannot return 204 when a long poll times out, so this code
                // is currently never executed (2.2.2012)
            } else if (longPollingResult.getStatusCode() == 204) {
                JOYNR_LOG_DEBUG(logger, "long polling successfull);full; no data");
            } else {
                std::string body("NULL");
                if (!longPollingResult.getBody().empty()) {
                    body = longPollingResult.getBody();
                }
                JOYNR_LOG_ERROR(logger,
                                "long polling failed; error message: {}; contents: {}",
                                longPollingResult.getErrorMessage(),
                                body);
                std::unique_lock<std::mutex> lock(interruptedMutex);
                interruptedWait.wait_for(lock, settings.createChannelRetryInterval);
            }
        }
    }
}

void LongPollingMessageReceiver::processReceivedInput(const std::string& receivedInput)
{
    std::vector<std::string> jsonObjects = util::splitIntoJsonObjects(receivedInput);
    for (std::size_t i = 0; i < jsonObjects.size(); i++) {
        processReceivedJsonObjects(jsonObjects.at(i));
    }
}

void LongPollingMessageReceiver::processReceivedJsonObjects(const std::string& jsonObject)
{
    if (onTextMessageReceived) {
        onTextMessageReceived(jsonObject);
    } else {
        JOYNR_LOG_ERROR(
                logger,
                "Discarding received message, since onTextMessageReceived callback is empty.");
    }
}

void LongPollingMessageReceiver::checkServerTime()
{
    std::string timeCheckUrl = brokerUrl.getTimeCheckUrl().toString();

    IHttpGetBuilder* timeCheckRequestBuilder =
            HttpNetworking::getInstance()->createHttpGetBuilder(timeCheckUrl);
    std::shared_ptr<HttpRequest> timeCheckRequest(
            timeCheckRequestBuilder->addHeader("Accept", "text/plain")
                    ->withTimeout(settings.brokerTimeout)
                    ->build());
    delete timeCheckRequestBuilder;
    timeCheckRequestBuilder = nullptr;
    JOYNR_LOG_DEBUG(logger, "CheckServerTime: sending request to Bounce Proxy ({})", timeCheckUrl);
    std::chrono::system_clock::time_point localTimeBeforeRequest = std::chrono::system_clock::now();
    HttpResult timeCheckResult = timeCheckRequest->execute();
    std::chrono::system_clock::time_point localTimeAfterRequest = std::chrono::system_clock::now();
    std::uint64_t localTime = (util::toMilliseconds(localTimeBeforeRequest) +
                               util::toMilliseconds(localTimeAfterRequest)) /
                              2;
    if (timeCheckResult.getStatusCode() != 200) {
        JOYNR_LOG_ERROR(logger,
                        "CheckServerTime: Bounce Proxy not reached [statusCode={}] [body={}]",
                        timeCheckResult.getStatusCode(),
                        timeCheckResult.getBody());
    } else {
        JOYNR_LOG_TRACE(logger,
                        "CheckServerTime: reply received [statusCode={}] [body={}]",
                        timeCheckResult.getStatusCode(),
                        timeCheckResult.getBody());
        std::uint64_t serverTime = boost::lexical_cast<std::uint64_t>(timeCheckResult.getBody());

        auto minMaxTime = std::minmax(serverTime, localTime);
        std::uint64_t diff = minMaxTime.second - minMaxTime.first;

        JOYNR_LOG_INFO(logger,
                       "CheckServerTime [server time={}] [local time={}] [diff={} ms]",
                       util::toDateString(JoynrTimePoint(std::chrono::milliseconds(serverTime))),
                       util::toDateString(JoynrTimePoint(std::chrono::milliseconds(localTime))),
                       diff);

        if (diff > 500) {
            JOYNR_LOG_ERROR(logger, "CheckServerTime: time difference to server is {} ms", diff);
        }
    }
}

} // namespace joynr
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_OS_SYNC_CLIENT_HPP
#define REALM_OS_SYNC_CLIENT_HPP

#include <realm/sync/client.hpp>

#include <thread>

#if REALM_PLATFORM_APPLE
#include "sync/impl/apple/network_reachability_observer.hpp"
#endif

namespace realm {
namespace _impl {

using ReconnectMode = sync::Client::ReconnectMode;

struct SyncClient {
    sync::Client client;

    SyncClient(std::unique_ptr<util::Logger> logger,
               ReconnectMode reconnect_mode = ReconnectMode::normal,
               bool verify_ssl = true)
    : client(make_client(*logger, reconnect_mode, verify_ssl)) // Throws
    , m_logger(std::move(logger))
    , m_thread([this] {
        client.run();
    }) // Throws
#if REALM_PLATFORM_APPLE
    , m_reachability_observer(none, [=](const NetworkReachabilityStatus status) {
        if (status != NotReachable) {
            cancel_reconnect_delay();
        }
    })
    {
        if (!m_reachability_observer.start_observing()) {
            m_logger->error("Failed to setup network reachability observer");
        }
    }
#else
    {
    }
#endif

    void cancel_reconnect_delay() {
        // FIXME: Implement after https://github.com/realm/realm-sync/issues/794
        // client.cancel_reconnect_delay();
    }

    void stop()
    {
        client.stop();
        if (m_thread.joinable())
            m_thread.join();
    }

    ~SyncClient()
    {
        stop();
    }

private:
    static sync::Client make_client(util::Logger& logger, ReconnectMode reconnect_mode, bool verify_ssl)
    {
        sync::Client::Config config;
        config.logger = &logger;
        config.reconnect_mode = std::move(reconnect_mode);
        config.verify_servers_ssl_certificate = verify_ssl;
        return sync::Client(std::move(config)); // Throws
    }

    const std::unique_ptr<util::Logger> m_logger;
    std::thread m_thread;
#if REALM_PLATFORM_APPLE
    NetworkReachabilityObserver m_reachability_observer;
#endif
};

}
}

#endif // REALM_OS_SYNC_CLIENT_HPP
<commit_msg>enable client.cancel_reconnect_delay()<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_OS_SYNC_CLIENT_HPP
#define REALM_OS_SYNC_CLIENT_HPP

#include <realm/sync/client.hpp>

#include <thread>

#if REALM_PLATFORM_APPLE
#include "sync/impl/apple/network_reachability_observer.hpp"
#endif

namespace realm {
namespace _impl {

using ReconnectMode = sync::Client::ReconnectMode;

struct SyncClient {
    sync::Client client;

    SyncClient(std::unique_ptr<util::Logger> logger,
               ReconnectMode reconnect_mode = ReconnectMode::normal,
               bool verify_ssl = true)
    : client(make_client(*logger, reconnect_mode, verify_ssl)) // Throws
    , m_logger(std::move(logger))
    , m_thread([this] {
        client.run();
    }) // Throws
#if REALM_PLATFORM_APPLE
    , m_reachability_observer(none, [=](const NetworkReachabilityStatus status) {
        if (status != NotReachable) {
            cancel_reconnect_delay();
        }
    })
    {
        if (!m_reachability_observer.start_observing()) {
            m_logger->error("Failed to setup network reachability observer");
        }
    }
#else
    {
    }
#endif

    void cancel_reconnect_delay() {
        client.cancel_reconnect_delay();
    }

    void stop()
    {
        client.stop();
        if (m_thread.joinable())
            m_thread.join();
    }

    ~SyncClient()
    {
        stop();
    }

private:
    static sync::Client make_client(util::Logger& logger, ReconnectMode reconnect_mode, bool verify_ssl)
    {
        sync::Client::Config config;
        config.logger = &logger;
        config.reconnect_mode = std::move(reconnect_mode);
        config.verify_servers_ssl_certificate = verify_ssl;
        return sync::Client(std::move(config)); // Throws
    }

    const std::unique_ptr<util::Logger> m_logger;
    std::thread m_thread;
#if REALM_PLATFORM_APPLE
    NetworkReachabilityObserver m_reachability_observer;
#endif
};

}
}

#endif // REALM_OS_SYNC_CLIENT_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google, Inc.
 *
 * 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 the copyright holders 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 THE COPYRIGHT
 * OWNER 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.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/scheduler.hh"

#include "base/fiber.hh"
#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/kernel.hh"
#include "systemc/ext/core/sc_main.hh"

namespace sc_gem5
{

Scheduler::Scheduler() :
    eq(nullptr), readyEvent(this, false, ReadyPriority),
    pauseEvent(this, false, PausePriority),
    stopEvent(this, false, StopPriority),
    scMain(nullptr),
    starvationEvent(this, false, StarvationPriority),
    _started(false), _paused(false), _stopped(false),
    maxTickEvent(this, false, MaxTickPriority),
    _numCycles(0), _current(nullptr), initDone(false),
    runOnce(false)
{}

Scheduler::~Scheduler()
{
    // Clear out everything that belongs to us to make sure nobody tries to
    // clear themselves out after the scheduler goes away.

    // Delta notifications.
    for (auto &e: deltas)
        e->deschedule();

    // Timed notifications.
    for (auto &ts: timeSlots) {
        for (auto &e: ts.second->events)
            e->deschedule();
        delete ts.second;
        ts.second = nullptr;
    }

    // gem5 events.
    if (readyEvent.scheduled())
        eq->deschedule(&readyEvent);
    if (pauseEvent.scheduled())
        eq->deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        eq->deschedule(&stopEvent);
    if (starvationEvent.scheduled())
        eq->deschedule(&starvationEvent);
    if (maxTickEvent.scheduled())
        eq->deschedule(&maxTickEvent);

    Process *p;
    while ((p = toFinalize.getNext()))
        p->popListNode();
    while ((p = initList.getNext()))
        p->popListNode();
    while ((p = readyList.getNext()))
        p->popListNode();

    Channel *c;
    while ((c = updateList.getNext()))
        c->popListNode();
}

void
Scheduler::initPhase()
{
    for (Process *p = toFinalize.getNext(); p; p = toFinalize.getNext()) {
        p->finalize();
        p->popListNode();
    }

    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
        p->finalize();
        p->popListNode();
        p->ready();
    }

    update();

    for (auto &e: deltas)
        e->run();
    deltas.clear();

    for (auto ets: eventsToSchedule)
        eq->schedule(ets.first, ets.second);
    eventsToSchedule.clear();

    if (_started) {
        if (starved() && !runToTime)
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    initDone = true;
}

void
Scheduler::reg(Process *p)
{
    if (initDone) {
        // If we're past initialization, finalize static sensitivity.
        p->finalize();
        // Mark the process as ready.
        p->ready();
    } else {
        // Otherwise, record that this process should be initialized once we
        // get there.
        initList.pushLast(p);
    }
}

void
Scheduler::dontInitialize(Process *p)
{
    if (initDone) {
        // Pop this process off of the ready list.
        p->popListNode();
    } else {
        // Push this process onto the list of processes which still need
        // their static sensitivity to be finalized. That implicitly pops it
        // off the list of processes to be initialized/marked ready.
        toFinalize.pushLast(p);
    }
}

void
Scheduler::yield()
{
    _current = readyList.getNext();
    if (!_current) {
        // There are no more processes, so return control to evaluate.
        Fiber::primaryFiber()->run();
    } else {
        _current->popListNode();
        // Switch to whatever Fiber is supposed to run this process. All
        // Fibers which aren't running should be parked at this line.
        _current->fiber()->run();
        // If the current process needs to be manually started, start it.
        if (_current && _current->needsStart())
            _current->run();
    }
    if (_current && _current->excWrapper) {
        // Make sure this isn't a method process.
        assert(!_current->needsStart());
        auto ew = _current->excWrapper;
        _current->excWrapper = nullptr;
        ew->throw_it();
    }
}

void
Scheduler::ready(Process *p)
{
    // Clump methods together to minimize context switching.
    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
        readyList.pushFirst(p);
    else
        readyList.pushLast(p);

    scheduleReadyEvent();
}

void
Scheduler::requestUpdate(Channel *c)
{
    updateList.pushLast(c);
    scheduleReadyEvent();
}

void
Scheduler::scheduleReadyEvent()
{
    // Schedule the evaluate and update phases.
    if (!readyEvent.scheduled()) {
        schedule(&readyEvent);
        if (starvationEvent.scheduled())
            deschedule(&starvationEvent);
    }
}

void
Scheduler::scheduleStarvationEvent()
{
    if (!starvationEvent.scheduled()) {
        schedule(&starvationEvent);
        if (readyEvent.scheduled())
            deschedule(&readyEvent);
    }
}

void
Scheduler::runReady()
{
    bool empty = readyList.empty();

    // The evaluation phase.
    do {
        yield();
    } while (!readyList.empty());

    if (!empty)
        _numCycles++;

    // The update phase.
    update();

    if (starved() && !runToTime)
        scheduleStarvationEvent();

    // The delta phase.
    for (auto &e: deltas)
        e->run();
    deltas.clear();

    if (runOnce)
        schedulePause();
}

void
Scheduler::update()
{
    Channel *channel = updateList.getNext();
    while (channel) {
        channel->popListNode();
        channel->update();
        channel = updateList.getNext();
    }
}

void
Scheduler::pause()
{
    _paused = true;
    kernel->status(::sc_core::SC_PAUSED);
    runOnce = false;
    scMain->run();
}

void
Scheduler::stop()
{
    _stopped = true;
    kernel->stop();
    runOnce = false;
    scMain->run();
}

void
Scheduler::start(Tick max_tick, bool run_to_time)
{
    // We should be running from sc_main. Keep track of that Fiber to return
    // to later.
    scMain = Fiber::currentFiber();

    _started = true;
    _paused = false;
    _stopped = false;
    runToTime = run_to_time;

    maxTick = max_tick;

    if (initDone) {
        if (starved() && !runToTime)
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    schedule(&maxTickEvent, maxTick);

    // Return to gem5 to let it run events, etc.
    Fiber::primaryFiber()->run();

    if (pauseEvent.scheduled())
        eq->deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        eq->deschedule(&stopEvent);
    if (maxTickEvent.scheduled())
        eq->deschedule(&maxTickEvent);
    if (starvationEvent.scheduled())
        eq->deschedule(&starvationEvent);
}

void
Scheduler::oneCycle()
{
    runOnce = true;
    start(::MaxTick, false);
}

void
Scheduler::schedulePause()
{
    if (pauseEvent.scheduled())
        return;

    eq->schedule(&pauseEvent, eq->getCurTick());
}

void
Scheduler::scheduleStop(bool finish_delta)
{
    if (stopEvent.scheduled())
        return;

    if (!finish_delta) {
        // If we're not supposed to finish the delta cycle, flush the list
        // of ready processes, scheduled updates, and delta notifications.
        Process *p;
        while ((p = readyList.getNext()))
            p->popListNode();
        Channel *c;
        while ((c = updateList.getNext()))
            c->popListNode();
        for (auto &e: deltas)
            e->deschedule();
        deltas.clear();
    }
    eq->schedule(&stopEvent, eq->getCurTick());
}

Scheduler scheduler;

} // namespace sc_gem5
<commit_msg>systemc: Make sure no delta cycles are scheduled when stopping.<commit_after>/*
 * Copyright 2018 Google, Inc.
 *
 * 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 the copyright holders 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 THE COPYRIGHT
 * OWNER 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.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/scheduler.hh"

#include "base/fiber.hh"
#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/kernel.hh"
#include "systemc/ext/core/sc_main.hh"

namespace sc_gem5
{

Scheduler::Scheduler() :
    eq(nullptr), readyEvent(this, false, ReadyPriority),
    pauseEvent(this, false, PausePriority),
    stopEvent(this, false, StopPriority),
    scMain(nullptr),
    starvationEvent(this, false, StarvationPriority),
    _started(false), _paused(false), _stopped(false),
    maxTickEvent(this, false, MaxTickPriority),
    _numCycles(0), _current(nullptr), initDone(false),
    runOnce(false)
{}

Scheduler::~Scheduler()
{
    // Clear out everything that belongs to us to make sure nobody tries to
    // clear themselves out after the scheduler goes away.

    // Delta notifications.
    for (auto &e: deltas)
        e->deschedule();

    // Timed notifications.
    for (auto &ts: timeSlots) {
        for (auto &e: ts.second->events)
            e->deschedule();
        delete ts.second;
        ts.second = nullptr;
    }

    // gem5 events.
    if (readyEvent.scheduled())
        eq->deschedule(&readyEvent);
    if (pauseEvent.scheduled())
        eq->deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        eq->deschedule(&stopEvent);
    if (starvationEvent.scheduled())
        eq->deschedule(&starvationEvent);
    if (maxTickEvent.scheduled())
        eq->deschedule(&maxTickEvent);

    Process *p;
    while ((p = toFinalize.getNext()))
        p->popListNode();
    while ((p = initList.getNext()))
        p->popListNode();
    while ((p = readyList.getNext()))
        p->popListNode();

    Channel *c;
    while ((c = updateList.getNext()))
        c->popListNode();
}

void
Scheduler::initPhase()
{
    for (Process *p = toFinalize.getNext(); p; p = toFinalize.getNext()) {
        p->finalize();
        p->popListNode();
    }

    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
        p->finalize();
        p->popListNode();
        p->ready();
    }

    update();

    for (auto &e: deltas)
        e->run();
    deltas.clear();

    for (auto ets: eventsToSchedule)
        eq->schedule(ets.first, ets.second);
    eventsToSchedule.clear();

    if (_started) {
        if (starved() && !runToTime)
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    initDone = true;
}

void
Scheduler::reg(Process *p)
{
    if (initDone) {
        // If we're past initialization, finalize static sensitivity.
        p->finalize();
        // Mark the process as ready.
        p->ready();
    } else {
        // Otherwise, record that this process should be initialized once we
        // get there.
        initList.pushLast(p);
    }
}

void
Scheduler::dontInitialize(Process *p)
{
    if (initDone) {
        // Pop this process off of the ready list.
        p->popListNode();
    } else {
        // Push this process onto the list of processes which still need
        // their static sensitivity to be finalized. That implicitly pops it
        // off the list of processes to be initialized/marked ready.
        toFinalize.pushLast(p);
    }
}

void
Scheduler::yield()
{
    _current = readyList.getNext();
    if (!_current) {
        // There are no more processes, so return control to evaluate.
        Fiber::primaryFiber()->run();
    } else {
        _current->popListNode();
        // Switch to whatever Fiber is supposed to run this process. All
        // Fibers which aren't running should be parked at this line.
        _current->fiber()->run();
        // If the current process needs to be manually started, start it.
        if (_current && _current->needsStart())
            _current->run();
    }
    if (_current && _current->excWrapper) {
        // Make sure this isn't a method process.
        assert(!_current->needsStart());
        auto ew = _current->excWrapper;
        _current->excWrapper = nullptr;
        ew->throw_it();
    }
}

void
Scheduler::ready(Process *p)
{
    // Clump methods together to minimize context switching.
    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
        readyList.pushFirst(p);
    else
        readyList.pushLast(p);

    scheduleReadyEvent();
}

void
Scheduler::requestUpdate(Channel *c)
{
    updateList.pushLast(c);
    scheduleReadyEvent();
}

void
Scheduler::scheduleReadyEvent()
{
    // Schedule the evaluate and update phases.
    if (!readyEvent.scheduled()) {
        schedule(&readyEvent);
        if (starvationEvent.scheduled())
            deschedule(&starvationEvent);
    }
}

void
Scheduler::scheduleStarvationEvent()
{
    if (!starvationEvent.scheduled()) {
        schedule(&starvationEvent);
        if (readyEvent.scheduled())
            deschedule(&readyEvent);
    }
}

void
Scheduler::runReady()
{
    bool empty = readyList.empty();

    // The evaluation phase.
    do {
        yield();
    } while (!readyList.empty());

    if (!empty)
        _numCycles++;

    // The update phase.
    update();

    if (starved() && !runToTime)
        scheduleStarvationEvent();

    // The delta phase.
    for (auto &e: deltas)
        e->run();
    deltas.clear();

    if (runOnce)
        schedulePause();
}

void
Scheduler::update()
{
    Channel *channel = updateList.getNext();
    while (channel) {
        channel->popListNode();
        channel->update();
        channel = updateList.getNext();
    }
}

void
Scheduler::pause()
{
    _paused = true;
    kernel->status(::sc_core::SC_PAUSED);
    runOnce = false;
    scMain->run();
}

void
Scheduler::stop()
{
    _stopped = true;
    kernel->stop();

    if (readyEvent.scheduled())
        eq->deschedule(&readyEvent);

    runOnce = false;
    scMain->run();
}

void
Scheduler::start(Tick max_tick, bool run_to_time)
{
    // We should be running from sc_main. Keep track of that Fiber to return
    // to later.
    scMain = Fiber::currentFiber();

    _started = true;
    _paused = false;
    _stopped = false;
    runToTime = run_to_time;

    maxTick = max_tick;

    if (initDone) {
        if (starved() && !runToTime)
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    schedule(&maxTickEvent, maxTick);

    // Return to gem5 to let it run events, etc.
    Fiber::primaryFiber()->run();

    if (pauseEvent.scheduled())
        eq->deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        eq->deschedule(&stopEvent);
    if (maxTickEvent.scheduled())
        eq->deschedule(&maxTickEvent);
    if (starvationEvent.scheduled())
        eq->deschedule(&starvationEvent);
}

void
Scheduler::oneCycle()
{
    runOnce = true;
    start(::MaxTick, false);
}

void
Scheduler::schedulePause()
{
    if (pauseEvent.scheduled())
        return;

    eq->schedule(&pauseEvent, eq->getCurTick());
}

void
Scheduler::scheduleStop(bool finish_delta)
{
    if (stopEvent.scheduled())
        return;

    if (!finish_delta) {
        // If we're not supposed to finish the delta cycle, flush the list
        // of ready processes, scheduled updates, and delta notifications.
        Process *p;
        while ((p = readyList.getNext()))
            p->popListNode();
        Channel *c;
        while ((c = updateList.getNext()))
            c->popListNode();
        for (auto &e: deltas)
            e->deschedule();
        deltas.clear();
    }
    eq->schedule(&stopEvent, eq->getCurTick());
}

Scheduler scheduler;

} // namespace sc_gem5
<|endoftext|>


<commit_before>/*
 * Copyright 2015 eje inc.
 * Copyright 2015 Samsung Electronics Co., LTD
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "includes.h"

/***************************************************************************
 * Renders a GL_TEXTURE_EXTERNAL_OES texture.
 ***************************************************************************/

#include "OESShader.h"
#include "Material.h"
#include "mesh.h"
#include "RenderData.h"

namespace mgn {

static const char VERTEX_SHADER[] =
        "attribute vec4 Position;\n"
        "attribute vec2 TexCoord;\n"
        "uniform highp mat4 Mvpm;\n"
        "uniform highp mat4 Texm;\n"
        "varying highp vec2 oTexCoord;\n"
        "void main() {\n"
        "  oTexCoord = vec2(Texm * vec4(TexCoord, 0, 1));\n"
        "  gl_Position = Mvpm * Position;\n"
        "}\n";

static const char FRAGMENT_SHADER[] =
        "#extension GL_OES_EGL_image_external : require\n"
        "precision highp float;\n"
        "uniform samplerExternalOES Texture0;\n"
        "uniform vec4 UniformColor;\n"
        "uniform float Opacity;\n"
        "varying highp vec2 oTexCoord;\n"
        "void main() {\n"
        "  vec4 texel = texture2D(Texture0, oTexCoord) * UniformColor * Opacity;\n"
        "  if (texel.a < 0.1)\n"
        "    discard;\n"
        "  gl_FragColor = texel;\n"
        "}\n";

OESShader::OESShader() {
    program = BuildProgram(VERTEX_SHADER, FRAGMENT_SHADER);
    opacity = glGetUniformLocation(program.Program, "Opacity");
}

OESShader::~OESShader() {
    DeleteProgram(program);
}

void OESShader::Render(const Matrix4f & mvpMatrix, const GlGeometry & geometry, const Material * material, const int eye) const {

    Vector4f color = material->GetColor();

    GL(glUseProgram(program.Program));

    GL(glUniformMatrix4fv(program.uMvp, 1, GL_TRUE, mvpMatrix.M[0]));
    GL(glUniformMatrix4fv(program.uTexm, 1, GL_TRUE, TexmForVideo(material->GetStereoMode(), eye).M[ 0 ] ));
    GL(glActiveTexture (GL_TEXTURE0));
    GL(glBindTexture(GL_TEXTURE_EXTERNAL_OES, material->GetTextureId()));
    GL(glUniform4f(program.uColor, color.x, color.y, color.z, color.w));
    GL(glUniform1f(opacity, material->GetOpacity()));

    geometry.Draw();

    GL(glBindTexture( GL_TEXTURE_EXTERNAL_OES, 0 ));
}

const Matrix4f & OESShader::TexmForVideo(const Material::StereoMode stereoMode, const int eye ) const
{
    switch (stereoMode) {
        case Material::StereoMode::TOP_BOTTOM:
            return eye ? bottomM : topM;

        case Material::StereoMode::BOTTOM_TOP:
            return eye ? topM : bottomM;

        case Material::StereoMode::LEFT_RIGHT:
            return eye ? rightM : leftM;

        case Material::StereoMode::RIGHT_LEFT:
            return eye ? leftM : rightM;

        case Material::StereoMode::TOP_ONLY:
            return topM;

        case Material::StereoMode::BOTTOM_ONLY:
            return bottomM;

        case Material::StereoMode::LEFT_ONLY:
            return leftM;

        case Material::StereoMode::RIGHT_ONLY:
            return rightM;

        case Material::StereoMode::NORMAL:
        default:
            return normalM;
    }
}
}
;
<commit_msg>Update to GLES3<commit_after>/*
 * Copyright 2015 eje inc.
 * Copyright 2015 Samsung Electronics Co., LTD
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "includes.h"

/***************************************************************************
 * Renders a GL_TEXTURE_EXTERNAL_OES texture.
 ***************************************************************************/

#include "OESShader.h"
#include "Material.h"
#include "mesh.h"
#include "RenderData.h"

namespace mgn {

static const char * ImageExternalDirectives =
    "#extension GL_OES_EGL_image_external : enable\n"
    "#extension GL_OES_EGL_image_external_essl3 : enable\n";

static const char VERTEX_SHADER[] =
        "in vec4 Position;\n"
        "in vec2 TexCoord;\n"
        "uniform highp mat4 Mvpm;\n"
        "uniform highp mat4 Texm;\n"
        "out highp vec2 oTexCoord;\n"
        "void main() {\n"
        "  oTexCoord = vec2(Texm * vec4(TexCoord, 0, 1));\n"
        "  gl_Position = Mvpm * Position;\n"
        "}\n";

static const char FRAGMENT_SHADER[] =
        "precision highp float;\n"
        "uniform samplerExternalOES Texture0;\n"
        "uniform vec4 UniformColor;\n"
        "uniform float Opacity;\n"
        "in highp vec2 oTexCoord;\n"
        "void main() {\n"
        "  vec4 texel = texture2D(Texture0, oTexCoord) * UniformColor * Opacity;\n"
        "  if (texel.a < 0.1)\n"
        "    discard;\n"
        "  gl_FragColor = texel;\n"
        "}\n";

OESShader::OESShader() {
    program = BuildProgram(NULL, VERTEX_SHADER, ImageExternalDirectives, FRAGMENT_SHADER);
    opacity = glGetUniformLocation(program.Program, "Opacity");
}

OESShader::~OESShader() {
    DeleteProgram(program);
}

void OESShader::Render(const Matrix4f & mvpMatrix, const GlGeometry & geometry, const Material * material, const int eye) const {

    Vector4f color = material->GetColor();

    GL(glUseProgram(program.Program));

    GL(glUniformMatrix4fv(program.uMvp, 1, GL_TRUE, mvpMatrix.M[0]));
    GL(glUniformMatrix4fv(program.uTexm, 1, GL_TRUE, TexmForVideo(material->GetStereoMode(), eye).M[ 0 ] ));
    GL(glActiveTexture (GL_TEXTURE0));
    GL(glBindTexture(GL_TEXTURE_EXTERNAL_OES, material->GetTextureId()));
    GL(glUniform4f(program.uColor, color.x, color.y, color.z, color.w));
    GL(glUniform1f(opacity, material->GetOpacity()));

    geometry.Draw();

    GL(glBindTexture( GL_TEXTURE_EXTERNAL_OES, 0 ));
}

const Matrix4f & OESShader::TexmForVideo(const Material::StereoMode stereoMode, const int eye ) const
{
    switch (stereoMode) {
        case Material::StereoMode::TOP_BOTTOM:
            return eye ? bottomM : topM;

        case Material::StereoMode::BOTTOM_TOP:
            return eye ? topM : bottomM;

        case Material::StereoMode::LEFT_RIGHT:
            return eye ? rightM : leftM;

        case Material::StereoMode::RIGHT_LEFT:
            return eye ? leftM : rightM;

        case Material::StereoMode::TOP_ONLY:
            return topM;

        case Material::StereoMode::BOTTOM_ONLY:
            return bottomM;

        case Material::StereoMode::LEFT_ONLY:
            return leftM;

        case Material::StereoMode::RIGHT_ONLY:
            return rightM;

        case Material::StereoMode::NORMAL:
        default:
            return normalM;
    }
}
}
;
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file memdiags_fir.C
/// @brief Subroutines for memdiags/prd FIR
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>

#include <generic/memory/lib/utils/scom.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/fir/fir.H>
#include <lib/fir/memdiags_fir.H>
#include <lib/mc/port.H>
#include <lib/workarounds/mcbist_workarounds.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;

namespace mss
{

namespace unmask
{

///
/// @brief Unmask and setup actions for memdiags related FIR
/// @param[in] i_target the fapi2::Target MCBIST
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
template<>
fapi2::ReturnCode after_memdiags( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
{
    fapi2::ReturnCode l_rc;
    fapi2::buffer<uint64_t> dsm0_buffer;
    fapi2::buffer<uint64_t> l_mnfg_buffer;
    uint64_t rd_tag_delay = 0;
    uint64_t wr_done_delay = 0;
    fapi2::buffer<uint64_t> l_aue_buffer;
    fapi2::ATTR_CHIP_EC_FEATURE_HW414700_Type l_checkstop_flag;
    constexpr uint64_t MNFG_THRESHOLDS_ATTR = 63;

    // Broadcast mode workaround for UEs causing out of sync
    FAPI_TRY(mss::workarounds::mcbist::broadcast_out_of_sync(i_target, mss::ON));

    for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target))
    {
        fir::reg<MCA_FIR> l_ecc64_fir_reg(p, l_rc);
        FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_FIR);

        fir::reg<MCA_MBACALFIRQ> l_cal_fir_reg(p, l_rc);
        FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_MBACALFIRQ);

        // Read out the wr_done and rd_tag delays and find min
        // and set the RCD Protect Time to this value
        FAPI_TRY (mss::read_dsm0q_register(p, dsm0_buffer) );
        mss::get_wrdone_delay(dsm0_buffer, wr_done_delay);
        mss::get_rdtag_delay(dsm0_buffer, rd_tag_delay);
        const auto rcd_protect_time = std::min(wr_done_delay, rd_tag_delay);
        FAPI_TRY (mss::change_rcd_protect_time(p, rcd_protect_time) );

        l_ecc64_fir_reg.checkstop<MCA_FIR_MAINLINE_AUE>()
        .recoverable_error<MCA_FIR_MAINLINE_UE>()
        .checkstop<MCA_FIR_MAINLINE_IAUE>()
        .recoverable_error<MCA_FIR_MAINLINE_IUE>();

        // If ATTR_CHIP_EC_FEATURE_HW414700 is enabled set checkstops
        auto l_chip_target = mss::find_target<fapi2::TARGET_TYPE_PROC_CHIP>(i_target);
        FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_HW414700, l_chip_target, l_checkstop_flag) );

        if (l_checkstop_flag)
        {
            l_ecc64_fir_reg.checkstop<MCA_FIR_MAINLINE_UE>()
            .checkstop<MCA_FIR_MAINLINE_RCD>();
        }

        // If MNFG FLAG Threshhold is enabled skip IUE unflagging
        FAPI_TRY ( mss::mnfg_flags(l_mnfg_buffer) );

        if ( !(l_mnfg_buffer.getBit<MNFG_THRESHOLDS_ATTR>()) )
        {
            l_ecc64_fir_reg.recoverable_error<MCA_FIR_MAINTENANCE_IUE>();
        }

        l_cal_fir_reg.recoverable_error<MCA_MBACALFIRQ_PORT_FAIL>();

        FAPI_TRY(l_ecc64_fir_reg.write(), "unable to write fir::reg %d", MCA_FIR);
        FAPI_TRY(l_cal_fir_reg.write(), "unable to write fir::reg %d", MCA_MBACALFIRQ);

        // Change Maint AUE and IAUE to checkstop without unmasking
        // Normal setup modifies masked bits in addition to setting checkstop
        // This causes issues if error has occured, manually scoming to avoid this
        FAPI_TRY( mss::getScom(p, MCA_ACTION1, l_aue_buffer) );
        l_aue_buffer.clearBit<MCA_FIR_MAINTENANCE_AUE>();
        l_aue_buffer.clearBit<MCA_FIR_MAINTENANCE_IAUE>();
        FAPI_TRY( mss::putScom(p, MCA_ACTION1, l_aue_buffer) );

        // Note: We also want to include the following setup RCD recovery and port fail
        FAPI_TRY( mss::change_port_fail_disable(p, mss::LOW) );
        FAPI_TRY( mss::change_rcd_recovery_disable(p, mss::LOW) );
    }

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Unmask and setup actions for scrub related FIR
/// @param[in] i_target the fapi2::Target MCBIST
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
template<>
fapi2::ReturnCode after_background_scrub( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
{
    for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target))
    {
        fapi2::ReturnCode l_rc;
        fir::reg<MCA_FIR> l_ecc64_fir_reg(p, l_rc);
        FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_FIR);

        l_ecc64_fir_reg.recoverable_error<MCA_FIR_MAINLINE_MPE_RANK_0_TO_7,
                                          MCA_FIR_MAINLINE_MPE_RANK_0_TO_7_LEN>()
                                          .recoverable_error<MCA_FIR_MAINLINE_NCE>()
                                          .recoverable_error<MCA_FIR_MAINLINE_TCE>()
                                          .recoverable_error<MCA_FIR_MAINLINE_IMPE>()
                                          .recoverable_error<MCA_FIR_MAINTENANCE_IMPE>();

        FAPI_TRY(l_ecc64_fir_reg.write(), "unable to write fir::reg %d", MCA_FIR);
    }

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;
}

}
}
<commit_msg>Fixed port fail SUE bug for DD2 modules<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/fir/memdiags_fir.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file memdiags_fir.C
/// @brief Subroutines for memdiags/prd FIR
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>

#include <generic/memory/lib/utils/scom.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/fir/fir.H>
#include <lib/fir/memdiags_fir.H>
#include <lib/mc/port.H>
#include <lib/workarounds/mcbist_workarounds.H>

using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;

namespace mss
{

namespace unmask
{

///
/// @brief Unmask and setup actions for memdiags related FIR
/// @param[in] i_target the fapi2::Target MCBIST
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
template<>
fapi2::ReturnCode after_memdiags( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
{
    fapi2::ReturnCode l_rc;
    fapi2::buffer<uint64_t> dsm0_buffer;
    fapi2::buffer<uint64_t> l_mnfg_buffer;
    uint64_t rd_tag_delay = 0;
    uint64_t wr_done_delay = 0;
    fapi2::buffer<uint64_t> l_aue_buffer;
    fapi2::ATTR_CHIP_EC_FEATURE_HW414700_Type l_checkstop_flag;
    constexpr uint64_t MNFG_THRESHOLDS_ATTR = 63;

    // Broadcast mode workaround for UEs causing out of sync
    FAPI_TRY(mss::workarounds::mcbist::broadcast_out_of_sync(i_target, mss::ON));

    for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target))
    {
        fir::reg<MCA_FIR> l_ecc64_fir_reg(p, l_rc);
        FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_FIR);

        fir::reg<MCA_MBACALFIRQ> l_cal_fir_reg(p, l_rc);
        FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_MBACALFIRQ);

        // Read out the wr_done and rd_tag delays and find min
        // and set the RCD Protect Time to this value
        FAPI_TRY (mss::read_dsm0q_register(p, dsm0_buffer) );
        mss::get_wrdone_delay(dsm0_buffer, wr_done_delay);
        mss::get_rdtag_delay(dsm0_buffer, rd_tag_delay);
        const auto rcd_protect_time = std::min(wr_done_delay, rd_tag_delay);
        FAPI_TRY (mss::change_rcd_protect_time(p, rcd_protect_time) );

        l_ecc64_fir_reg.checkstop<MCA_FIR_MAINLINE_AUE>()
        .recoverable_error<MCA_FIR_MAINLINE_UE>()
        .checkstop<MCA_FIR_MAINLINE_IAUE>()
        .recoverable_error<MCA_FIR_MAINLINE_IUE>();

        l_cal_fir_reg.recoverable_error<MCA_MBACALFIRQ_PORT_FAIL>();

        // If ATTR_CHIP_EC_FEATURE_HW414700 is enabled set checkstops
        auto l_chip_target = mss::find_target<fapi2::TARGET_TYPE_PROC_CHIP>(i_target);
        FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_HW414700, l_chip_target, l_checkstop_flag) );

        // If the system is running DD2 chips override some recoverable firs with checkstop
        // Due to a known hardware defect with DD2 certain errors are not handled properly
        // As a result, these firs are marked as checkstop for DD2 to avoid any mishandling
        if (l_checkstop_flag)
        {
            l_ecc64_fir_reg.checkstop<MCA_FIR_MAINLINE_UE>()
            .checkstop<MCA_FIR_MAINLINE_RCD>();
            l_cal_fir_reg.checkstop<MCA_MBACALFIRQ_PORT_FAIL>();
        }

        // If MNFG FLAG Threshhold is enabled skip IUE unflagging
        FAPI_TRY ( mss::mnfg_flags(l_mnfg_buffer) );

        if ( !(l_mnfg_buffer.getBit<MNFG_THRESHOLDS_ATTR>()) )
        {
            l_ecc64_fir_reg.recoverable_error<MCA_FIR_MAINTENANCE_IUE>();
        }

        FAPI_TRY(l_ecc64_fir_reg.write(), "unable to write fir::reg %d", MCA_FIR);
        FAPI_TRY(l_cal_fir_reg.write(), "unable to write fir::reg %d", MCA_MBACALFIRQ);

        // Change Maint AUE and IAUE to checkstop without unmasking
        // Normal setup modifies masked bits in addition to setting checkstop
        // This causes issues if error has occured, manually scoming to avoid this
        FAPI_TRY( mss::getScom(p, MCA_ACTION1, l_aue_buffer) );
        l_aue_buffer.clearBit<MCA_FIR_MAINTENANCE_AUE>();
        l_aue_buffer.clearBit<MCA_FIR_MAINTENANCE_IAUE>();
        FAPI_TRY( mss::putScom(p, MCA_ACTION1, l_aue_buffer) );

        // Note: We also want to include the following setup RCD recovery and port fail
        FAPI_TRY( mss::change_port_fail_disable(p, mss::LOW) );
        FAPI_TRY( mss::change_rcd_recovery_disable(p, mss::LOW) );
    }

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Unmask and setup actions for scrub related FIR
/// @param[in] i_target the fapi2::Target MCBIST
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
template<>
fapi2::ReturnCode after_background_scrub( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
{
    for (const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target))
    {
        fapi2::ReturnCode l_rc;
        fir::reg<MCA_FIR> l_ecc64_fir_reg(p, l_rc);
        FAPI_TRY(l_rc, "unable to create fir::reg for %d", MCA_FIR);

        l_ecc64_fir_reg.recoverable_error<MCA_FIR_MAINLINE_MPE_RANK_0_TO_7,
                                          MCA_FIR_MAINLINE_MPE_RANK_0_TO_7_LEN>()
                                          .recoverable_error<MCA_FIR_MAINLINE_NCE>()
                                          .recoverable_error<MCA_FIR_MAINLINE_TCE>()
                                          .recoverable_error<MCA_FIR_MAINLINE_IMPE>()
                                          .recoverable_error<MCA_FIR_MAINTENANCE_IMPE>();

        FAPI_TRY(l_ecc64_fir_reg.write(), "unable to write fir::reg %d", MCA_FIR);
    }

    return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
    return fapi2::current_err;
}

}
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file raw_cards.C
/// @brief LRDIMM raw card data structure
/// Contains RCW settings per raw card rev
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

// std lib
#include <vector>

// fapi2
#include <fapi2.H>

// mss lib
#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H>

namespace mss
{

///
/// @brief raw card B0 settings
///
// TODO RTC:160116 Fill in valid RCD data for LRDIMM
rcw_settings lrdimm_rc_b0( 0x00, // RC00
                           0x00, // RC01 (C might be the right answer)
                           0x00, // RC02
                           0x1F, // RC06_7
                           0x00, // RC09
                           0x0E, // RC0B
                           0x00, // RC0C
                           0x00, // RC0F
                           0x00, // RC1X
                           0x00, // RC2X
                           0x00, // RC4X
                           0x00, // RC5X
                           0x00, // RC6C
                           0x00, // RC8X
                           0x00, // RC9X
                           0x00); // RCAX

namespace lrdimm
{

// TODO - RTC:160121 Catch all for adding raw card data for DIMMs
const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
{
    // I expect this to grow as Warren M. expects us to have
    // settings for every raw card that JEDEC puts out.  Openpower
    // can't break due to a missing raw card...
    {raw_card_rev::B0, lrdimm_rc_b0},
};

}// lrdimm
}// mss
<commit_msg>Turn off A17 if not needed<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file raw_cards.C
/// @brief LRDIMM raw card data structure
/// Contains RCW settings per raw card rev
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

// std lib
#include <vector>

// fapi2
#include <fapi2.H>

// mss lib
#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H>

namespace mss
{

///
/// @brief raw card B0 settings
///
// TODO RTC:160116 Fill in valid RCD data for LRDIMM
rcw_settings lrdimm_rc_b0( 0x00, // RC00
                           0x00, // RC01 (C might be the right answer)
                           0x1F, // RC06_7
                           0x00, // RC09
                           0x0E, // RC0B
                           0x00, // RC0C
                           0x00, // RC0F
                           0x00, // RC1X
                           0x00, // RC2X
                           0x00, // RC4X
                           0x00, // RC5X
                           0x00, // RC6C
                           0x00, // RC8X
                           0x00, // RC9X
                           0x00); // RCAX

namespace lrdimm
{

// TODO - RTC:160121 Catch all for adding raw card data for DIMMs
const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
{
    // I expect this to grow as Warren M. expects us to have
    // settings for every raw card that JEDEC puts out.  Openpower
    // can't break due to a missing raw card...
    {raw_card_rev::B0, lrdimm_rc_b0},
};

}// lrdimm
}// mss
<|endoftext|>