]> rtime.felk.cvut.cz Git - arc.git/blob - common/cirq_buffer.c
Merge with f712c9ae3aa462feecaddbd7b9200590795833b0
[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
49 /* TODO: Not threadsafe, add DisableAllInterrts()/EnableAllInterrupts() */
50
51 CirqBufferType CirqBuffStatCreate(void *buffer, int maxCnt, size_t dataSize) {
52         CirqBufferType cirqbuffer;
53         cirqbuffer.bufStart = buffer;
54         cirqbuffer.maxCnt = maxCnt;
55         cirqbuffer.bufEnd = (char *)cirqbuffer.bufStart + dataSize*maxCnt;
56         cirqbuffer.head = cirqbuffer.bufStart;
57         cirqbuffer.tail = cirqbuffer.bufStart;
58         cirqbuffer.dataSize = dataSize;
59         cirqbuffer.currCnt = 0;
60         return cirqbuffer;
61 }
62
63 CirqBufferType *CirqBuffDynCreate( size_t size, size_t dataSize ) {
64         CirqBufferType *cPtr;
65         cPtr = malloc(sizeof(CirqBufferType));
66         if( cPtr == NULL ) {
67                 return NULL;
68         }
69         cPtr->maxCnt = size;
70         cPtr->dataSize = dataSize;
71         cPtr->bufStart = malloc(dataSize*size);
72         cPtr->bufEnd = (char *)cPtr->bufStart + dataSize*size;
73         cPtr->head = cPtr->bufStart;
74         cPtr->tail = cPtr->bufStart;
75         cPtr->currCnt = 0;
76         return cPtr;
77 }
78
79
80
81 int CirqBuffDynDestroy(CirqBufferType *cPtr ) {
82         free(cPtr->bufStart);
83         free(cPtr);
84         return 0;
85 }
86
87 int CirqBuffPush( CirqBufferType *cPtr, void *dataPtr ) {
88         uint32_t flags;
89         Irq_Save(flags);
90         if( (cPtr->currCnt == cPtr->maxCnt) || (cPtr==NULL) ) {
91                 Irq_Restore(flags);
92                 return 1;       /* No more room */
93         }
94         MEMCPY(cPtr->head,dataPtr,cPtr->dataSize);
95         cPtr->head = (char *)cPtr->head + cPtr->dataSize;
96         if( cPtr->head == cPtr->bufEnd) {
97                 cPtr->head = cPtr->bufStart;
98         }
99         ++cPtr->currCnt;
100         Irq_Restore(flags);
101
102         return 0;
103 }
104
105 int CirqBuffPop(CirqBufferType *cPtr, void *dataPtr ) {
106         uint32_t flags;
107         Irq_Save(flags);
108         if( (cPtr->currCnt == 0) || (cPtr==NULL) ) {
109                 Irq_Restore(flags);
110                 return 1;
111         }
112         MEMCPY(dataPtr,cPtr->tail,cPtr->dataSize);
113         cPtr->tail = (char *)cPtr->tail + cPtr->dataSize;
114         if( cPtr->tail == cPtr->bufEnd) {
115                 cPtr->tail = cPtr->bufStart;
116         }
117         --cPtr->currCnt;
118         Irq_Restore(flags);
119         return 0;
120 }
121
122
123
124 #ifdef _TEST_CIRQ_BUFFER_DYN_
125 int main( void ) {
126         CirqBufferType *cPtr;
127         uint8_t *dataPtr;
128         int rv;
129
130 #define DATA_SIZE       4
131 #define QSIZE           8
132         cPtr = CirqBuffDynCreate(QSIZE, DATA_SIZE );
133
134         dataPtr = malloc(DATA_SIZE);
135         dataPtr[0] = 1;
136         rv  = CirqBuffPush(cPtr,dataPtr);
137         assert(rv == 0);
138         free(dataPtr);
139
140         dataPtr = malloc(DATA_SIZE);
141         dataPtr[0] = 2;
142         rv  = CirqBuffPush(cPtr,dataPtr);
143         assert(rv == 0);
144         free(dataPtr);
145
146         dataPtr = malloc(DATA_SIZE);
147         rv = CirqBuffPop(cPtr,dataPtr);
148         assert( dataPtr[0] == 1);
149         assert(rv == 0);
150         free(dataPtr);
151
152         dataPtr = malloc(DATA_SIZE);
153         rv = CirqBuffPop(cPtr,dataPtr);
154         assert( dataPtr[0] == 2);
155         assert(rv == 0);
156         free(dataPtr);
157
158         CirqBuffDynDestroy(cPtr);
159 }
160 #endif
161
162