| rev |
line source |
|
msach@24
|
1 /*
|
|
msach@24
|
2 * Copyright 2009 OpenSourceStewardshipFoundation.org
|
|
msach@24
|
3 * Licensed under GNU General Public License version 2
|
|
msach@24
|
4 *
|
|
msach@24
|
5 * Author: seanhalle@yahoo.com
|
|
msach@24
|
6 */
|
|
msach@24
|
7
|
|
msach@24
|
8
|
|
msach@24
|
9 #include <stdio.h>
|
|
msach@24
|
10 #include <string.h>
|
|
msach@24
|
11 #include <errno.h>
|
|
msach@24
|
12 #include <stdlib.h>
|
|
msach@24
|
13
|
|
msach@24
|
14 #include "PrivateQueue.h"
|
|
msach@24
|
15 #include "VMS_Implementations/VMS_impl/vmalloc.h"
|
|
msach@24
|
16
|
|
msach@24
|
17
|
|
msach@24
|
18
|
|
msach@24
|
19 //===========================================================================
|
|
msach@24
|
20
|
|
msach@24
|
21 /*This kind of queue is private to a single core at a time -- has no
|
|
msach@24
|
22 * synchronizations
|
|
msach@24
|
23 */
|
|
msach@24
|
24
|
|
msach@24
|
25 PrivQueueStruc* makePrivQ()
|
|
msach@24
|
26 {
|
|
msach@24
|
27 PrivQueueStruc *retQ;
|
|
msach@24
|
28 retQ = VMS_int__malloc( sizeof( PrivQueueStruc ) );
|
|
msach@24
|
29 retQ->startOfData = (void*)VMS_int__malloc( 1024 * sizeof(void *) );
|
|
msach@24
|
30 memset( retQ->startOfData, 0, 1024 );
|
|
msach@24
|
31
|
|
msach@24
|
32 retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty
|
|
msach@24
|
33 retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be
|
|
msach@24
|
34 retQ->endOfData = &(retQ->startOfData[1023]);
|
|
msach@24
|
35
|
|
msach@24
|
36 return retQ;
|
|
msach@24
|
37 }
|
|
msach@24
|
38
|
|
msach@24
|
39
|
|
msach@24
|
40 void
|
|
msach@24
|
41 enlargePrivQ( PrivQueueStruc *Q )
|
|
msach@24
|
42 { size_t oldSize, newSize;
|
|
msach@24
|
43 void **oldStartOfData;
|
|
msach@24
|
44
|
|
msach@24
|
45 oldSize = Q->endOfData - Q->startOfData + 1;
|
|
msach@24
|
46 newSize = 2 * oldSize;
|
|
msach@24
|
47 oldStartOfData = Q->startOfData;
|
|
msach@24
|
48 Q->startOfData = VMS_int__malloc( newSize * sizeof(void*));
|
|
msach@24
|
49 //copy second half
|
|
msach@24
|
50 size_t secondHalfSize = Q->endOfData - Q->extractPos + 1;
|
|
msach@24
|
51 memcpy(Q->startOfData,Q->extractPos, secondHalfSize * sizeof(void*));
|
|
msach@24
|
52 //copy first half
|
|
msach@24
|
53 memcpy(Q->startOfData + secondHalfSize, oldStartOfData,
|
|
msach@24
|
54 (oldSize-secondHalfSize) * sizeof(void*));
|
|
msach@24
|
55 VMS_int__free(oldStartOfData);
|
|
msach@24
|
56
|
|
msach@24
|
57 Q->extractPos = Q->startOfData;
|
|
msach@24
|
58 Q->insertPos = Q->startOfData + oldSize - 1;
|
|
msach@24
|
59 Q->endOfData = &(Q->startOfData[newSize - 1]);
|
|
msach@24
|
60 }
|
|
msach@24
|
61
|
|
msach@24
|
62
|
|
msach@24
|
63 /*Returns NULL when queue is empty
|
|
msach@24
|
64 */
|
|
msach@24
|
65 void* readPrivQ( PrivQueueStruc* Q )
|
|
msach@24
|
66 { void *out = 0;
|
|
msach@24
|
67 void **startOfData = Q->startOfData;
|
|
msach@24
|
68 void **endOfData = Q->endOfData;
|
|
msach@24
|
69
|
|
msach@24
|
70 void **insertPos = Q->insertPos;
|
|
msach@24
|
71 void **extractPos = Q->extractPos;
|
|
msach@24
|
72
|
|
msach@24
|
73 //if not empty -- (extract is just below insert when empty)
|
|
msach@24
|
74 if( insertPos - extractPos != 1 &&
|
|
msach@24
|
75 !(extractPos == endOfData && insertPos == startOfData))
|
|
msach@24
|
76 { //move before read
|
|
msach@24
|
77 if( extractPos == endOfData ) //write new pos exactly once, correctly
|
|
msach@24
|
78 { Q->extractPos = startOfData; //can't overrun then fix it 'cause
|
|
msach@24
|
79 } // other thread might read bad pos
|
|
msach@24
|
80 else
|
|
msach@24
|
81 { Q->extractPos++;
|
|
msach@24
|
82 }
|
|
msach@24
|
83 out = *(Q->extractPos);
|
|
msach@24
|
84 return out;
|
|
msach@24
|
85 }
|
|
msach@24
|
86 //Q is empty
|
|
msach@24
|
87 return NULL;
|
|
msach@24
|
88 }
|
|
msach@24
|
89
|
|
msach@24
|
90 int32
|
|
msach@24
|
91 numInPrivQ( PrivQueueStruc *Q )
|
|
msach@24
|
92 { int32 size, numIn;
|
|
msach@24
|
93
|
|
msach@24
|
94 if( Q->insertPos < Q->extractPos )
|
|
msach@24
|
95 { //insert has wrapped around so numIn is:
|
|
msach@24
|
96 // insertPos + size - extractPos -- Consider, is empty when
|
|
msach@24
|
97 // extractPos = endOfData and insert = start -- correctly get zero
|
|
msach@24
|
98 size = Q->endOfData - Q->startOfData;
|
|
msach@24
|
99 numIn = Q->insertPos + size - Q->extractPos;
|
|
msach@24
|
100 }
|
|
msach@24
|
101 else
|
|
msach@24
|
102 {
|
|
msach@24
|
103 numIn = Q->insertPos - Q->extractPos -1;//-1 bec empty @ side-by-side
|
|
msach@24
|
104 }
|
|
msach@24
|
105 return numIn;
|
|
msach@24
|
106 }
|
|
msach@24
|
107
|
|
msach@24
|
108
|
|
msach@24
|
109 /*Expands the queue size automatically when it's full
|
|
msach@24
|
110 */
|
|
msach@24
|
111 void
|
|
msach@24
|
112 writePrivQ( void * in, PrivQueueStruc* Q )
|
|
msach@24
|
113 {
|
|
msach@24
|
114 while(1){
|
|
msach@24
|
115 void **startOfData = Q->startOfData;
|
|
msach@24
|
116 void **endOfData = Q->endOfData;
|
|
msach@24
|
117
|
|
msach@24
|
118 void **insertPos = Q->insertPos;
|
|
msach@24
|
119 void **extractPos = Q->extractPos;
|
|
msach@24
|
120
|
|
msach@24
|
121 //Full? (insert is just below extract when full)
|
|
msach@24
|
122 if( extractPos - insertPos != 1 &&
|
|
msach@24
|
123 !(insertPos == endOfData && extractPos == startOfData))
|
|
msach@24
|
124 { *(Q->insertPos) = in; //insert before move
|
|
msach@24
|
125 if( insertPos == endOfData ) //write new pos exactly once, correctly
|
|
msach@24
|
126 { Q->insertPos = startOfData;
|
|
msach@24
|
127 }
|
|
msach@24
|
128 else
|
|
msach@24
|
129 { Q->insertPos++;
|
|
msach@24
|
130 }
|
|
msach@24
|
131 return;
|
|
msach@24
|
132 }
|
|
msach@24
|
133 //Q is full
|
|
msach@24
|
134 enlargePrivQ( Q );
|
|
msach@24
|
135 }
|
|
msach@24
|
136 }
|
|
msach@24
|
137
|
|
msach@24
|
138
|
|
msach@24
|
139 /*Returns false when the queue was full.
|
|
msach@24
|
140 * have option of calling make_larger_PrivQ to make more room, then try again
|
|
msach@24
|
141 */
|
|
msach@24
|
142 int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q )
|
|
msach@24
|
143 {
|
|
msach@24
|
144 void **startOfData = Q->startOfData;
|
|
msach@24
|
145 void **endOfData = Q->endOfData;
|
|
msach@24
|
146
|
|
msach@24
|
147 void **insertPos = Q->insertPos;
|
|
msach@24
|
148 void **extractPos = Q->extractPos;
|
|
msach@24
|
149
|
|
msach@24
|
150 if( extractPos - insertPos != 1 &&
|
|
msach@24
|
151 !(insertPos == endOfData && extractPos == startOfData))
|
|
msach@24
|
152 { *(Q->insertPos) = in; //insert before move
|
|
msach@24
|
153 if( insertPos == endOfData ) //write new pos exactly once, correctly
|
|
msach@24
|
154 { Q->insertPos = startOfData;
|
|
msach@24
|
155 }
|
|
msach@24
|
156 else
|
|
msach@24
|
157 { Q->insertPos++;
|
|
msach@24
|
158 }
|
|
msach@24
|
159 return TRUE;
|
|
msach@24
|
160 }
|
|
msach@24
|
161 //Q is full
|
|
msach@24
|
162 return FALSE;
|
|
msach@24
|
163 }
|
|
msach@24
|
164
|
|
msach@24
|
165 /*Treats queue as a stack -- no matter contents, if read done right after
|
|
msach@24
|
166 * a push, then the pushed item is what comes out.
|
|
msach@24
|
167 * Expands the queue size automatically when it's full.
|
|
msach@24
|
168 */
|
|
msach@24
|
169 void
|
|
msach@24
|
170 pushPrivQ( void * in, PrivQueueStruc* Q )
|
|
msach@24
|
171 {
|
|
msach@24
|
172 while(1){
|
|
msach@24
|
173 void **startOfData = Q->startOfData;
|
|
msach@24
|
174 void **endOfData = Q->endOfData;
|
|
msach@24
|
175
|
|
msach@24
|
176 void **insertPos = Q->insertPos;
|
|
msach@24
|
177 void **extractPos = Q->extractPos;
|
|
msach@24
|
178
|
|
msach@24
|
179 //Full? (insert is just below extract when full)
|
|
msach@24
|
180 if( extractPos - insertPos != 1 &&
|
|
msach@24
|
181 !(insertPos == endOfData && extractPos == startOfData))
|
|
msach@24
|
182 { //insert -- but go backwards, inserting at read position then
|
|
msach@24
|
183 // move read pos backwards
|
|
msach@24
|
184 *(Q->extractPos) = in;
|
|
msach@24
|
185 if( extractPos == startOfData ) //write new pos exactly once, correctly
|
|
msach@24
|
186 { Q->extractPos = endOfData; //can't overrun then fix it 'cause
|
|
msach@24
|
187 } // other thread might read bad pos
|
|
msach@24
|
188 else
|
|
msach@24
|
189 { Q->extractPos--;
|
|
msach@24
|
190 }
|
|
msach@24
|
191 return;
|
|
msach@24
|
192 }
|
|
msach@24
|
193 //Q is full
|
|
msach@24
|
194 enlargePrivQ( Q );
|
|
msach@24
|
195 }
|
|
msach@24
|
196 }
|
|
msach@24
|
197
|
|
msach@24
|
198 void
|
|
msach@24
|
199 freePrivQ( PrivQueueStruc *Q )
|
|
msach@24
|
200 {
|
|
msach@24
|
201 VMS_int__free( Q->startOfData );
|
|
msach@24
|
202 VMS_int__free( Q );
|
|
Me@9
|
203 } |