1/*
2* \file       ocsd_gen_elem_stack.cpp
3* \brief      OpenCSD : List of Generic trace elements for output.
4*
5* \copyright  Copyright (c) 2020, ARM Limited. All Rights Reserved.
6*/
7
8
9/*
10* Redistribution and use in source and binary forms, with or without modification,
11* are permitted provided that the following conditions are met:
12*
13* 1. Redistributions of source code must retain the above copyright notice,
14* this list of conditions and the following disclaimer.
15*
16* 2. Redistributions in binary form must reproduce the above copyright notice,
17* this list of conditions and the following disclaimer in the documentation
18* and/or other materials provided with the distribution.
19*
20* 3. Neither the name of the copyright holder nor the names of its contributors
21* may be used to endorse or promote products derived from this software without
22* specific prior written permission.
23*
24* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
25* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#include "common/ocsd_gen_elem_stack.h"
37
38OcsdGenElemStack::OcsdGenElemStack() :
39    m_pElemArray(0),
40    m_elemArraySize(0),
41    m_elem_to_send(0),
42    m_curr_elem_idx(0),
43    m_send_elem_idx(0),
44    m_CSID(0),
45    m_is_init(false)
46{
47
48}
49
50OcsdGenElemStack::~OcsdGenElemStack()
51{
52    for (int i = 0; i<m_elemArraySize; i++)
53    {
54        delete m_pElemArray[i].pElem;
55    }
56    delete [] m_pElemArray;
57    m_pElemArray = 0;
58}
59
60ocsd_err_t OcsdGenElemStack::addElem(const ocsd_trc_index_t trc_pkt_idx)
61{
62    ocsd_err_t err = OCSD_OK;
63
64    if (((m_curr_elem_idx + 1) == m_elemArraySize) || !m_pElemArray)
65    {
66        err = growArray();
67        if (err)
68            return err;
69    }
70
71    // if there is a least one element then copy and increment
72    // otherwise we are at base of stack.
73    if (m_elem_to_send)
74    {
75        copyPersistentData(m_curr_elem_idx, m_curr_elem_idx + 1);
76        m_curr_elem_idx++;
77    }
78    m_pElemArray[m_curr_elem_idx].trc_pkt_idx = trc_pkt_idx;
79    m_elem_to_send++;
80    return err;
81}
82
83ocsd_err_t OcsdGenElemStack::addElemType(const ocsd_trc_index_t trc_pkt_idx, ocsd_gen_trc_elem_t elem_type)
84{
85    ocsd_err_t err = addElem(trc_pkt_idx);
86    if (!err)
87        getCurrElem().setType(elem_type);
88    return err;
89}
90
91ocsd_err_t OcsdGenElemStack::resetElemStack()
92{
93    ocsd_err_t err = OCSD_OK;
94    if (!m_pElemArray)
95    {
96        err = growArray();
97        if (err)
98            return err;
99    }
100
101    if (!isInit())
102        return OCSD_ERR_NOT_INIT;
103
104    resetIndexes();
105    return err;
106}
107
108void OcsdGenElemStack::resetIndexes()
109{
110    // last time there was more than one element on stack
111    if (m_curr_elem_idx > 0)
112        copyPersistentData(m_curr_elem_idx, 0);
113
114    // indexes to bottom of stack, nothing in use at present
115    m_curr_elem_idx = 0;
116    m_send_elem_idx = 0;
117    m_elem_to_send = 0;
118}
119
120ocsd_datapath_resp_t OcsdGenElemStack::sendElements()
121{
122    ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
123    if (!isInit())
124        return OCSD_RESP_FATAL_NOT_INIT;
125
126    while (m_elem_to_send && OCSD_DATA_RESP_IS_CONT(resp))
127    {
128        resp = m_sendIf->first()->TraceElemIn(m_pElemArray[m_send_elem_idx].trc_pkt_idx, m_CSID, *(m_pElemArray[m_send_elem_idx].pElem));
129        m_send_elem_idx++;
130        m_elem_to_send--;
131    }
132
133    // clear the indexes if we are done.
134    if (!m_elem_to_send)
135        resetIndexes();
136    return resp;
137}
138
139ocsd_err_t OcsdGenElemStack::growArray()
140{
141    elemPtr_t *p_new_array = 0;
142    const int increment = 4;
143
144    p_new_array = new (std::nothrow) elemPtr_t[m_elemArraySize + increment];
145
146    if (p_new_array != 0)
147    {
148        OcsdTraceElement *pElem = 0;
149
150        // fill the last increment elements with new objects
151        for (int i = 0; i < increment; i++)
152        {
153            pElem = new (std::nothrow) OcsdTraceElement();
154            if (!pElem)
155                return OCSD_ERR_MEM;
156            pElem->init();
157            p_new_array[m_elemArraySize + i].pElem = pElem;
158        }
159
160        // copy the existing objects from the old array to the start of the new one
161        if (m_elemArraySize > 0)
162        {
163            for (int i = 0; i < m_elemArraySize; i++)
164            {
165                p_new_array[i].pElem = m_pElemArray[i].pElem;
166                p_new_array[i].trc_pkt_idx = m_pElemArray[i].trc_pkt_idx;
167            }
168        }
169
170        // delete the old pointer array.
171        delete[] m_pElemArray;
172        m_elemArraySize += increment;
173        m_pElemArray = p_new_array;
174    }
175    else
176        return OCSD_ERR_MEM;
177
178    return OCSD_OK;
179}
180
181void OcsdGenElemStack::copyPersistentData(int src, int dst)
182{
183    m_pElemArray[dst].pElem->copyPersistentData(*(m_pElemArray[src].pElem));
184}
185
186const bool OcsdGenElemStack::isInit()
187{
188    if (!m_is_init) {
189        if (m_elemArraySize && m_pElemArray && m_sendIf)
190            m_is_init = true;
191    }
192    return m_is_init;
193}
194
195
196/* End of File ocsd_gen_elem_stack.cpp */
197