]> rtime.felk.cvut.cz Git - arc.git/blob - common/cirq_buffer.c
needs crc....
[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 #define MEMCPY(_x,_y,_z)        __builtin_memcpy(_x,_y,_z)
44 //#define MEMCPY(_x,_y,_z)      memcpy(_x,_y,_z)
45
46
47 /* TODO: Not threadsafe, add DisableAllInterrts()/EnableAllInterrupts() */
48
49 void CirqBuff_Init(CirqBufferType *cirqbuffer, void *buffer, int maxCnt, size_t dataSize) {
50         cirqbuffer->bufStart = buffer;
51         cirqbuffer->maxCnt = maxCnt;
52         cirqbuffer->bufEnd = (char *)cirqbuffer->bufStart + dataSize*maxCnt;
53         cirqbuffer->head = cirqbuffer->bufStart;
54         cirqbuffer->tail = cirqbuffer->bufStart;
55         cirqbuffer->dataSize = dataSize;
56         cirqbuffer->currCnt = 0;
57 }
58
59
60 #if 0
61 CirqBufferType CirqBuffStatCreate(void *buffer, int maxCnt, size_t dataSize) {
62         CirqBufferType cirqbuffer;
63         cirqbuffer.bufStart = buffer;
64         cirqbuffer.maxCnt = maxCnt;
65         cirqbuffer.bufEnd = (char *)cirqbuffer.bufStart + dataSize*maxCnt;
66         cirqbuffer.head = cirqbuffer.bufStart;
67         cirqbuffer.tail = cirqbuffer.bufStart;
68         cirqbuffer.dataSize = dataSize;
69         cirqbuffer.currCnt = 0;
70 #error returning AUTO variable......
71         return cirqbuffer;
72 }
73 #endif
74
75 CirqBufferType *CirqBuffDynCreate( size_t size, size_t dataSize ) {
76         CirqBufferType *cPtr;
77         cPtr = malloc(sizeof(CirqBufferType));
78         if( cPtr == NULL ) {
79                 return NULL;
80         }
81         cPtr->maxCnt = size;
82         cPtr->dataSize = dataSize;
83         cPtr->bufStart = malloc(dataSize*size);
84         cPtr->bufEnd = (char *)cPtr->bufStart + dataSize*size;
85         cPtr->head = cPtr->bufStart;
86         cPtr->tail = cPtr->bufStart;
87         cPtr->currCnt = 0;
88         return cPtr;
89 }
90
91
92
93 int CirqBuffDynDestroy(CirqBufferType *cPtr ) {
94         free(cPtr->bufStart);
95         free(cPtr);
96         return 0;
97 }
98
99 int CirqBuffPush( CirqBufferType *cPtr, void *dataPtr ) {
100         uint32_t flags;
101         Irq_Save(flags);
102         if( (cPtr->currCnt == cPtr->maxCnt) || (cPtr==NULL) ) {
103                 Irq_Restore(flags);
104                 return 1;       /* No more room */
105         }
106         MEMCPY(cPtr->head,dataPtr,cPtr->dataSize);
107         cPtr->head = (char *)cPtr->head + cPtr->dataSize;
108         if( cPtr->head == cPtr->bufEnd) {
109                 cPtr->head = cPtr->bufStart;
110         }
111         ++cPtr->currCnt;
112         Irq_Restore(flags);
113
114         return 0;
115 }
116
117
118
119 int CirqBuffPop(CirqBufferType *cPtr, void *dataPtr ) {
120         uint32_t flags;
121         Irq_Save(flags);
122         if( (cPtr->currCnt == 0) || (cPtr==NULL) ) {
123                 Irq_Restore(flags);
124                 return 1;
125         }
126         MEMCPY(dataPtr,cPtr->tail,cPtr->dataSize);
127         cPtr->tail = (char *)cPtr->tail + cPtr->dataSize;
128         if( cPtr->tail == cPtr->bufEnd) {
129                 cPtr->tail = cPtr->bufStart;
130         }
131         --cPtr->currCnt;
132         Irq_Restore(flags);
133         return 0;
134 }
135
136 void *CirqBuff_PushLock( CirqBufferType *cPtr) {
137         void *dataPtr;
138         if( (cPtr->currCnt == cPtr->maxCnt) || (cPtr==NULL) ) {
139                 return NULL;    /* No more room */
140         }
141         dataPtr = cPtr->head;
142         cPtr->head = (char *)cPtr->head + cPtr->dataSize;
143         if( cPtr->head == cPtr->bufEnd) {
144                 cPtr->head = cPtr->bufStart;
145         }
146         return dataPtr;
147 }
148
149
150 void * CirqBuff_PopLock(CirqBufferType *cPtr ) {
151         void *dataPtr;
152         if( (cPtr->currCnt == 0) || (cPtr==NULL) ) {
153                 return NULL;
154         }
155         dataPtr = cPtr->tail;
156         cPtr->tail = (char *)cPtr->tail + cPtr->dataSize;
157         if( cPtr->tail == cPtr->bufEnd) {
158                 cPtr->tail = cPtr->bufStart;
159         }
160         --cPtr->currCnt;
161         return dataPtr;
162 }
163
164
165
166 #ifdef _TEST_CIRQ_BUFFER_DYN_
167 int main( void ) {
168         CirqBufferType *cPtr;
169         uint8_t *dataPtr;
170         int rv;
171
172 #define DATA_SIZE       4
173 #define QSIZE           8
174         cPtr = CirqBuffDynCreate(QSIZE, DATA_SIZE );
175
176         dataPtr = malloc(DATA_SIZE);
177         dataPtr[0] = 1;
178         rv  = CirqBuffPush(cPtr,dataPtr);
179         assert(rv == 0);
180         free(dataPtr);
181
182         dataPtr = malloc(DATA_SIZE);
183         dataPtr[0] = 2;
184         rv  = CirqBuffPush(cPtr,dataPtr);
185         assert(rv == 0);
186         free(dataPtr);
187
188         dataPtr = malloc(DATA_SIZE);
189         rv = CirqBuffPop(cPtr,dataPtr);
190         assert( dataPtr[0] == 1);
191         assert(rv == 0);
192         free(dataPtr);
193
194         dataPtr = malloc(DATA_SIZE);
195         rv = CirqBuffPop(cPtr,dataPtr);
196         assert( dataPtr[0] == 2);
197         assert(rv == 0);
198         free(dataPtr);
199
200         CirqBuffDynDestroy(cPtr);
201 }
202 #endif
203
204