CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
MemoryRequestQueues.cpp
Go to the documentation of this file.
1
4
6
7namespace cmlabs {
8
9bool MemoryRequestQueues::InitQueue(char* data, uint32 size) {
10 if (!data || !size) return false;
11 memset(data, 0, sizeof(RequestQueueHeader));
12 RequestQueueHeader* header = (RequestQueueHeader*) data;
13 header->size = size;
14 header->createdTime = header->lastUpdateTime = GetTimeNow();
15 return true;
16}
17
18bool MemoryRequestQueues::CheckQueue(char* data, uint32 size) {
19 if (!data || !size) return false;
20 return ((RequestQueueHeader*) data)->size == size;
21}
22
24 if (!data || !msg) return false;
25 RequestQueueHeader* qHeader = (RequestQueueHeader*) data;
26 uint32 msgSize = msg->getSize();
27
28 uint32 spaceToEnd, inUse = 0, inUse2 = 0;
29 char* qData = ((char*)qHeader) + sizeof(RequestQueueHeader);
30 uint32 qDataSize = qHeader->size - sizeof(RequestQueueHeader);
31
32 if (qHeader->endPos == qHeader->startPos) {
33 spaceToEnd = qDataSize;
34 if (spaceToEnd >= msgSize) {
35 // add msg at buffer start
36 memcpy(qData, msg->data, msgSize);
37 qHeader->startPos = 0;
38 qHeader->endPos = msgSize;
39 qHeader->count++;
40 qHeader->padding = 0;
41 }
42 else {
43 // queue not big enough
44 return false;
45 }
46 }
47 else if (qHeader->endPos > qHeader->startPos) {
48 spaceToEnd = qDataSize - qHeader->endPos;
49 if (spaceToEnd >= msgSize) {
50 // add msg here
51 memcpy(qData+qHeader->endPos, msg->data, msgSize);
52 qHeader->endPos += msgSize;
53 qHeader->count++;
54 qHeader->padding = 0;
55 }
56 else if (qHeader->startPos >= msgSize) {
57 // fill end rest of space with 0
58 memset(qData+qHeader->endPos, 0, spaceToEnd);
59 qHeader->padding = spaceToEnd;
60 // add msg at buffer start
61 memcpy(qData, msg->data, msgSize);
62 qHeader->endPos = msgSize;
63 qHeader->count++;
64 }
65 else {
66 // queue not big enough
67 return false;
68 }
69 }
70 else {
71 spaceToEnd = qHeader->startPos - qHeader->endPos;
72 if (spaceToEnd > msgSize) {
73 // add msg here
74 memcpy(qData+qHeader->endPos, msg->data, msgSize);
75 qHeader->endPos += msgSize;
76 qHeader->count++;
77 }
78 else {
79 // queue not big enough
80 return false;
81 }
82 }
83 return true;
84}
85
87 if (!data) return NULL;
88 RequestQueueHeader* qHeader = (RequestQueueHeader*) data;
89 if (!qHeader->count)
90 return NULL;
91
92 DataMessage* msg = new DataMessage(((char*)qHeader) + sizeof(RequestQueueHeader) + qHeader->startPos, true);
93 qHeader->startPos += msg->getSize();
94 if (qHeader->startPos >= qHeader->size - sizeof(RequestQueueHeader) - qHeader->padding) {
95 qHeader->startPos = 0;
96 qHeader->padding = 0;
97 }
98 qHeader->count--;
99 return msg;
100}
101
102
103
104
105
106
107
108bool MemoryRequestQueues::InitRequestMap(char* data, uint32 count) {
109 if (!data || !count) return false;
110
111 uint32 requestsBitFieldSize = utils::Calc32BitFieldSize(count);
112 uint32 requestsSize = sizeof(RequestStatusHeader) + requestsBitFieldSize + count*sizeof(RequestStatusEntry);
113
114 memset(data, 0, sizeof(RequestStatusHeader));
116 header->countTotal = count;
117 header->size = requestsSize;
118 header->bitFieldSize = requestsBitFieldSize;
119 header->createdTime = header->lastUpdateTime = GetTimeNow();
120
121 memset(((char*)header)+sizeof(RequestStatusHeader), 255, requestsBitFieldSize);
122 // Position 0 is not allowed, used to indicate error or unused
123 utils::SetBit(0, BITOCCUPIED, ((char*)header + sizeof(RequestStatusHeader)), header->bitFieldSize);
124
125 return true;
126}
127
128bool MemoryRequestQueues::CheckRequestMap(char* data, uint32 count) {
129 if (!data || !count) return false;
130 return ((RequestQueueHeader*) data)->count == count;
131}
132
133uint64 MemoryRequestQueues::AddNewRequest(char* data, uint16 status, uint32 from, uint32 to) {
134 if (!data) return false;
135
137 if (header->countInUse >= header->countTotal-1)
138 return 0;
139
140 uint32 loc;
141 if (!utils::GetFirstFreeBitLoc(((char*)header + sizeof(RequestStatusHeader)), header->bitFieldSize, loc))
142 return 0;
143 if (loc >= header->countTotal)
144 return 0;
145
146 uint64 reqID = (uint64)loc;
147 RequestStatusEntry* entry = GetRequestEntry(data, reqID);
148 if (!entry)
149 return 0;
150
151 // Reserve it
152 utils::SetBit(loc, BITOCCUPIED, ((char*)header + sizeof(RequestStatusHeader)), header->bitFieldSize);
153 header->countInUse++;
154
155 entry->id = reqID;
156 entry->status = status;
157 entry->createdTime = entry->lastUpdateTime = GetTimeNow();
158 entry->from = from;
159 entry->to = to;
160 return reqID;
161}
162
163bool MemoryRequestQueues::SetRequestStatus(char* data, uint64 id, uint16 status) {
164 RequestStatusEntry* entry = GetRequestEntry(data, id);
165 if (!entry)
166 return false;
167 entry->status = status;
168 return true;
169}
170
171uint32 MemoryRequestQueues::GetRequestStatus(char* data, uint64 id, uint64& createdTime, uint64& lastUpdateTime) {
172 RequestStatusEntry* entry = GetRequestEntry(data, id);
173 if (!entry)
174 return false;
175 return entry->status;
176}
177
178
179bool MemoryRequestQueues::CloseRequest(char* data, uint64 id) {
181 RequestStatusEntry* entry = GetRequestEntry(data, id);
182 if (!entry)
183 return false;
184 memset(entry, 0, sizeof(RequestStatusEntry));
185 // clear bitfield entry
186 utils::SetBit((uint32)id, BITFREE, ((char*)header + sizeof(RequestStatusHeader)), header->bitFieldSize);
187 header->countInUse--;
188 return true;
189}
190
191RequestStatusEntry* MemoryRequestQueues::GetRequestEntry(char* data, uint64 id) {
192 if (data == NULL)
193 return NULL;
194 RequestStatusEntry* entry = NULL;
196
197 // Calc offset
198 uint32 offset = sizeof(RequestStatusHeader) + header->bitFieldSize + (uint32)id * sizeof(RequestStatusEntry);
199 if (offset > header->size)
200 return NULL;
201 entry = (RequestStatusEntry*) (data+offset);
202 if ((entry->id == id) && (entry->createdTime != 0))
203 return entry;
204 else if (!entry->id && !entry->createdTime)
205 return entry;
206 else
207 return NULL;
208}
209
210} // namespace cmlabs
Static algorithms for request queues and the request-status map used by the shared-memory request/rep...
#define BITOCCUPIED
Definition Types.h:34
#define BITFREE
Definition Types.h:33
The central Psyclone data container: a self-contained binary message with typed, named user entries.
DataMessageHeader * data
Pointer to the message's flat memory block (header + user entries).
uint32 getSize()
getSize() Get message size Many types of data of any size can be put into a message as user entries; ...
static bool InitRequestMap(char *data, uint32 count)
Initialise a status map for count requests.
static uint64 AddNewRequest(char *data, uint16 status, uint32 from, uint32 to)
Allocate a request slot.
static DataMessage * GetNextQueueMessage(char *data)
Pop the next message.
static bool AddToQueue(char *data, DataMessage *msg)
Append a copy of msg (caller keeps ownership).
static bool CloseRequest(char *data, uint64 id)
Release the request slot.
static bool SetRequestStatus(char *data, uint64 id, uint16 status)
Advance a request's MEMORYREQUEST_* status.
static uint32 GetRequestStatus(char *data, uint64 id, uint64 &createdTime, uint64 &lastUpdateTime)
static bool CheckQueue(char *data, uint32 size)
Validate an existing queue region.
static bool CheckRequestMap(char *data, uint32 count)
Validate an existing status map.
static bool InitQueue(char *data, uint32 size)
Initialise a queue region of size bytes.
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
Definition PsyTime.cpp:69
bool GetFirstFreeBitLoc(const char *bitfield, uint32 bytesize, uint32 &loc)
Find the first 0 (free) bit.
Definition Utils.cpp:2445
bool SetBit(uint32 loc, bit value, char *bitfield, uint32 bytesize)
Set bit loc to value.
Definition Utils.cpp:2569
uint32 Calc32BitFieldSize(uint32 bitsize)
Compute the byte size needed for a bitfield of bitsize bits, rounded up to a 32-bit boundary.
Definition Utils.cpp:2435
Header of one circular request queue; followed by serialized DataMessages between startPos and endPos...
One request transaction's status record.
uint64 createdTime
uint32 to
uint32 from
uint64 lastUpdateTime
uint16 status
uint64 id
Header of the request-status table; followed by a bitfield and countTotal RequestStatusEntry records.