blob: 3b4f879017f1aa0befa448f924d7335cd3a253ae [file] [log] [blame]
// umlrtsignalelement.cc
/*******************************************************************************
* Copyright (c) 2014-2015 Zeligsoft (2009) Limited and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
#include <stdlib.h>
#include "basedebug.hh"
#include "basedebugtype.hh"
#include "basefatal.hh"
#include "umlrtapi.hh"
#include "umlrtslot.hh"
#include "umlrtcommsportrole.hh"
#include "umlrtguard.hh"
#include "umlrtobjectclass.hh"
#include "umlrtsignalelement.hh"
#include "umlrtuserconfig.hh"
// See umlrtsignalelement.hh for documentation.
UMLRTSignalElement::UMLRTSignalElement() : id(0), srcPort(0), defaultPayload(0), payload(0), priority(PRIORITY_NORMAL), appPayloadSize(0),
maxPayloadSize(USER_CONFIG_SIGNAL_DEFAULT_PAYLOAD_SIZE), nonDefaultPayload(false), allocated(false), refCount(0)
{
// DEFAULT PAYLOAD SIZE IS A CONSTANT HERE, BUT HAS TO BE OBTAINED AT RUN-TIME.
if (!(defaultPayload = payload = (uint8_t*)malloc(USER_CONFIG_SIGNAL_DEFAULT_PAYLOAD_SIZE)))
{
FATAL("(%p) payload malloc(%d)",this, USER_CONFIG_SIGNAL_DEFAULT_PAYLOAD_SIZE);
}
BDEBUG(BD_SIGNALINIT, "(%p) signal element payload(%p)\n", this, payload);
}
// Initialize a signal from the pool and make sure the payload is large enough.
void UMLRTSignalElement::initialize( size_t payloadSize_, Priority priority_ )
{
BDEBUG(BD_SIGNAL, "[%p] initialize no id, srcPort or payloadSize\n", this);
srcPort = NULL; // No srcPort by default.
id = -1; // The signal id of '-1' used for 'uninitialized id value'.
priority = priority_;
if (refCount)
{
FATAL("(%p) signal element alloc refcount non-zero(%d)", this, refCount);
}
// If the user is requesting more space than is available in the
// default payload buffer, allocate it here.
// THIS CONSTANT MAY HAVE TO BE OBTAINED AT RUN-TIME FROM THE
// GENERATED USER-CONFIGURATION PARAMETERS, IF THE VALUES FROM umlrtapi.hh ARE NOT USED.
if (payloadSize_ > USER_CONFIG_SIGNAL_DEFAULT_PAYLOAD_SIZE)
{
if (!(payload = (uint8_t *)malloc(payloadSize_)))
{
FATAL("(%p) non-default payload malloc(%d)", this, payloadSize_ );
}
nonDefaultPayload = true;
maxPayloadSize = payloadSize_;
}
appPayloadSize = payloadSize_;
// Initialize encoding.
encodeInfo = payload;
incrementRefCount();
}
// Initialize a signal from the pool and make sure the payload is large enough.
void UMLRTSignalElement::initialize( Id id_, const UMLRTCommsPort * srcPort_, size_t payloadSize_, Priority priority_ )
{
if (!srcPort_)
{
SWERR("(%p) signal allocate src port == 0.", this);
}
initialize(payloadSize_); // Default initialization.
id = id_;
srcPort = srcPort_;
priority = priority_;
BDEBUG(BD_SIGNAL, "[%p] initialize id(%d) %s(%s) appPayloadSize(%d) maxPayloadSize(%d)\n",
this, id,
(srcPort_ != NULL) ? srcPort->slot->name : "(NULL src port)",
(srcPort_ != NULL) ? srcPort->role()->name : "(NULL src port)",
appPayloadSize,
maxPayloadSize);
}
void UMLRTSignalElement::initialize( Id id_, const UMLRTCommsPort * srcPort_ )
{
if (!srcPort_)
{
SWERR("(%p) signal allocate src port == 0.", this);
}
initialize(0); // Default initialization.
id = id_;
srcPort = srcPort_;
BDEBUG(BD_SIGNAL, "[%p] initialize id(%d) %s(%s) appPayloadSize(%d) maxPayloadSize(%d)\n",
this, id,
(srcPort_ != NULL) ? srcPort->slot->name : "(NULL src port)",
(srcPort_ != NULL) ? srcPort->role()->name : "(NULL src port)",
appPayloadSize,
maxPayloadSize);
}
// Free a signal element (return to the pool).
/*static*/ void UMLRTSignalElement::dealloc( UMLRTSignalElement * element )
{
if (!element)
{
FATAL("element NULL");
}
BDEBUG(BD_SIGNAL, "[%p] deallocate id(%d) srcPort(%s) appPayloadSize(%d) maxPayloadSize(%d)\n",
element, element->id, element->srcPort ? element->srcPort->role()->name : "NONE", element->appPayloadSize, element->maxPayloadSize);
if (element->refCount)
{
FATAL("(%p) signal element dealloc refcount non-zero(%d)", element, element->refCount);
}
if (element->nonDefaultPayload)
{
// Return non-default payload.
free(element->payload);
// Restore default payload.
element->payload = element->defaultPayload;
element->maxPayloadSize = USER_CONFIG_SIGNAL_DEFAULT_PAYLOAD_SIZE;
element->appPayloadSize = 0; // Should be unused while deallocated.
}
umlrt::SignalElementPutToPool(element);
}
void UMLRTSignalElement::incrementRefCount() const
{
BDEBUG(BD_SIGNALREF, "(%p) signal element inc ref count(%d)\n", this, refCount);
UMLRTGuard g(refCountMutex);
++refCount;
}
void UMLRTSignalElement::decrementRefCount() const
{
BDEBUG(BD_SIGNALREF, "(%p) signal element dec ref count(%d)\n", this, refCount);
UMLRTGuard g(refCountMutex);
if (refCount <= 0)
{
FATAL("(%p) signal element dec ref count that is already zero id(%d)", this, id);
}
else if (!(--refCount))
{
BDEBUG(BD_SIGNALREF, "(%p) signal element dec ref count == 0 dealloc\n", this);
UMLRTSignalElement::dealloc(const_cast<UMLRTSignalElement *>(this));
}
}
// See documentation in UMLRTSignal.
void UMLRTSignalElement::encode( const UMLRTObject_class * desc, const void * data, int arraySize )
{
// encodeInfo is intitialized to be 'payload' when the signal is initialized.
// It is moved forward during successive #encode calls.
for (int i = 0; i < arraySize; ++i)
{
encodeInfo = desc->encode(desc, data, encodeInfo);
}
}
// See documentation in UMLRTSignal.
void UMLRTSignalElement::encode( const UMLRTObject_class * desc, int ptrIndirection, const void * data, int arraySize )
{
FATAL("encode ptr indirection not implemented.");
}
// See documentation in UMLRTSignal.
void UMLRTSignalElement::decode( void * * decodeInfo, const UMLRTObject_class * desc, void * data, int arraySize )
{
// decodeInfo is initialized to be NULL by a decoder - it is owned by the decoder and not by
// the signal (contrary to the encodeInfo, which can be owned by the signal, since there is always
// only ever one encoder).
if (!(*decodeInfo))
{
*decodeInfo = payload;
}
for (int i = 0; i < arraySize; ++i)
{
*decodeInfo = desc->decode(desc, *decodeInfo, data);
}
}
// See documentation in UMLRTSignal.
void UMLRTSignalElement::decode( void * * decodeInfo, const UMLRTObject_class * desc, int ptrIndirection, void * data, int arraySize )
{
FATAL("decode ptr indirection not implemented.");
}
void UMLRTSignalElement::setAllocated( bool allocated_ )
{
if (allocated_)
{
if (allocated)
{
FATAL("signal-qid[%d] was already allocated", qid);
}
allocated = true;
}
else
{
if (!allocated)
{
FATAL("signal-qid[%d] was already deallocated", qid);
}
allocated = false;
}
}