]> rtime.felk.cvut.cz Git - arc.git/blob - common/cirq_buffer.c
WriteDataByIdentifier should return CNC when callback returns E_NOT_OK but has a...
[arc.git] / common / cirq_buffer.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15 /*
16  * DESCRIPTION
17  *  A circular buffer implementation.
18  *
19  *  This file implements the following versions:
20  *  1. CirqBuffDynXXXX
21  *     - The size of the data is not known of compile time
22  *       (semidynamic, since there is no free() function )
23  *  2. CirqBuffXXX
24  *     - A static implementation, data is known at compile time.
25  *       (implemented in the header file?)
26  *
27  * Implementation note:
28  * - CirqBuffDynXXXX, valgrind: OK
29  * - coverage: Not run
30  *
31  */
32 //#define _TEST_CIRQ_BUFFER_DYN_
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdint.h>
36 #include "Cpu.h"
37 #include "cirq_buffer.h"
38
39 #ifdef _TEST_CIRQ_BUFFER_DYN_
40 #include <assert.h>
41 #endif
42
43 #if defined(__GNUC__)
44 #define MEMCPY(_x,_y,_z)        __builtin_memcpy(_x,_y,_z)
45 #else
46 #define MEMCPY(_x,_y,_z)        memcpy(_x,_y,_z)
47 #endif
48 //#define MEMCPY(_x,_y,_z)      memcpy(_x,_y,_z)
49
50
51 /* TODO: Not threadsafe, add DisableAllInterrts()/EnableAllInterrupts() */
52
53 void CirqBuff_Init(CirqBufferType *cirqbuffer, void *buffer, int maxCnt, size_t dataSize) {
54         cirqbuffer->bufStart = buffer;
55         cirqbuffer->maxCnt = maxCnt;
56         cirqbuffer->bufEnd = (char *)cirqbuffer->bufStart + dataSize*maxCnt;
57         cirqbuffer->head = cirqbuffer->bufStart;
58         cirqbuffer->tail = cirqbuffer->bufStart;
59         cirqbuffer->dataSize = dataSize;
60         cirqbuffer->currCnt = 0;
61 }
62
63
64 CirqBufferType CirqBuffStatCreate(void *buffer, int maxCnt, size_t dataSize) {
65         CirqBufferType cirqbuffer;
66         cirqbuffer.bufStart = buffer;
67         cirqbuffer.maxCnt = maxCnt;
68         cirqbuffer.bufEnd = (char *)cirqbuffer.bufStart + dataSize*maxCnt;
69         cirqbuffer.head = cirqbuffer.bufStart;
70         cirqbuffer.tail = cirqbuffer.bufStart;
71         cirqbuffer.dataSize = dataSize;
72         cirqbuffer.currCnt = 0;
73         /*return whole object */
74         return cirqbuffer;
75 }
76
77 CirqBufferType *CirqBuffDynCreate( size_t size, size_t dataSize ) {
78         CirqBufferType *cPtr;
79         cPtr = malloc(sizeof(CirqBufferType));
80         if( cPtr == NULL ) {
81                 return NULL;
82         }
83         cPtr->maxCnt = size;
84         cPtr->dataSize = dataSize;
85         cPtr->bufStart = malloc(dataSize*size);
86         cPtr->bufEnd = (char *)cPtr->bufStart + dataSize*size;
87         cPtr->head = cPtr->bufStart;
88         cPtr->tail = cPtr->bufStart;
89         cPtr->currCnt = 0;
90         return cPtr;
91 }
92
93
94
95 int CirqBuffDynDestroy(CirqBufferType *cPtr ) {
96         free(cPtr->bufStart);
97         free(cPtr);
98         return 0;
99 }
100
101 int CirqBuffPush( CirqBufferType *cPtr, void *dataPtr ) {
102         uint32_t flags;
103         Irq_Save(flags);
104         if( (cPtr->currCnt == cPtr->maxCnt) || (cPtr==NULL) ) {
105                 Irq_Restore(flags);
106                 return 1;       /* No more room */
107         }
108         MEMCPY(cPtr->head,dataPtr,cPtr->dataSize);
109         cPtr->head = (char *)cPtr->head + cPtr->dataSize;
110         if( cPtr->head == cPtr->bufEnd) {
111                 cPtr->head = cPtr->bufStart;
112         }
113         ++cPtr->currCnt;
114         Irq_Restore(flags);
115
116         return 0;
117 }
118
119
120
121 int CirqBuffPop(CirqBufferType *cPtr, void *dataPtr ) {
122         uint32_t flags;
123         Irq_Save(flags);
124         if( (cPtr->currCnt == 0) || (cPtr==NULL) ) {
125                 Irq_Restore(flags);
126                 return 1;
127         }
128         MEMCPY(dataPtr,cPtr->tail,cPtr->dataSize);
129         cPtr->tail = (char *)cPtr->tail + cPtr->dataSize;
130         if( cPtr->tail == cPtr->bufEnd) {
131                 cPtr->tail = cPtr->bufStart;
132         }
133         --cPtr->currCnt;
134         Irq_Restore(flags);
135         return 0;
136 }
137
138 void *CirqBuff_PushLock( CirqBufferType *cPtr) {
139         void *dataPtr;
140         if( (cPtr->currCnt == cPtr->maxCnt) || (cPtr==NULL) ) {
141                 return NULL;    /* No more room */
142         }
143         dataPtr = cPtr->head;
144         cPtr->head = (char *)cPtr->head + cPtr->dataSize;
145         if( cPtr->head == cPtr->bufEnd) {
146                 cPtr->head = cPtr->bufStart;
147         }
148         return dataPtr;
149 }
150
151
152 void * CirqBuff_PopLock(CirqBufferType *cPtr ) {
153         void *dataPtr;
154         if( (cPtr->currCnt == 0) || (cPtr==NULL) ) {
155                 return NULL;
156         }
157         dataPtr = cPtr->tail;
158         cPtr->tail = (char *)cPtr->tail + cPtr->dataSize;
159         if( cPtr->tail == cPtr->bufEnd) {
160                 cPtr->tail = cPtr->bufStart;
161         }
162         --cPtr->currCnt;
163         return dataPtr;
164 }
165
166
167
168 #ifdef _TEST_CIRQ_BUFFER_DYN_
169 int main( void ) {
170         CirqBufferType *cPtr;
171         uint8_t *dataPtr;
172         int rv;
173
174 #define DATA_SIZE       4
175 #define QSIZE           8
176         cPtr = CirqBuffDynCreate(QSIZE, DATA_SIZE );
177
178         dataPtr = malloc(DATA_SIZE);
179         dataPtr[0] = 1;
180         rv  = CirqBuffPush(cPtr,dataPtr);
181         assert(rv == 0);
182         free(dataPtr);
183
184         dataPtr = malloc(DATA_SIZE);
185         dataPtr[0] = 2;
186         rv  = CirqBuffPush(cPtr,dataPtr);
187         assert(rv == 0);
188         free(dataPtr);
189
190         dataPtr = malloc(DATA_SIZE);
191         rv = CirqBuffPop(cPtr,dataPtr);
192         assert( dataPtr[0] == 1);
193         assert(rv == 0);
194         free(dataPtr);
195
196         dataPtr = malloc(DATA_SIZE);
197         rv = CirqBuffPop(cPtr,dataPtr);
198         assert( dataPtr[0] == 2);
199         assert(rv == 0);
200         free(dataPtr);
201
202         CirqBuffDynDestroy(cPtr);
203 }
204 #endif
205
206