Directory: | ./ |
---|---|
File: | pdserv/src/lib/SessionTaskData.cpp |
Date: | 2025-08-17 04:10:43 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 83 | 100 | 83.0% |
Branches: | 74 | 161 | 46.0% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /***************************************************************************** | ||
2 | * | ||
3 | * Copyright 2010 - 2012 Richard Hacker (lerichi at gmx dot net) | ||
4 | * Florian Pose <fp@igh-essen.com> | ||
5 | * | ||
6 | * This file is part of the pdserv library. | ||
7 | * | ||
8 | * The pdserv library is free software: you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU Lesser General Public License as published | ||
10 | * by the Free Software Foundation, either version 3 of the License, or (at | ||
11 | * your option) any later version. | ||
12 | * | ||
13 | * The pdserv library is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
15 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | ||
16 | * License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public License | ||
19 | * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>. | ||
20 | * | ||
21 | ****************************************************************************/ | ||
22 | |||
23 | #include "../Debug.h" | ||
24 | #include "../SessionTask.h" | ||
25 | #include "Main.h" | ||
26 | #include "SessionTaskData.h" | ||
27 | #include "ShmemDataStructures.h" | ||
28 | #include "Signal.h" | ||
29 | |||
30 | //////////////////////////////////////////////////////////////////////////// | ||
31 | 299 | SessionTaskData::SessionTaskData (PdServ::SessionTask *st, | |
32 | const std::vector<Signal*>* signals, | ||
33 | 299 | struct Pdo *txMemBegin, const void *txMemEnd): | |
34 | sessionTask(st), | ||
35 |
1/2✓ Branch 6 taken 299 times.
✗ Branch 7 not taken.
|
299 | task(const_cast<Task*>(static_cast<const Task*>(st->task))), |
36 | signals(signals), | ||
37 | 598 | txMemBegin(txMemBegin), txMemEnd(txMemEnd) | |
38 | { | ||
39 | 299 | signalListId = 0; | |
40 | 299 | pdoSize = 0; | |
41 | |||
42 |
1/2✓ Branch 4 taken 299 times.
✗ Branch 5 not taken.
|
299 | signalPosition.resize(signals->size()); |
43 | |||
44 |
1/2✓ Branch 2 taken 299 times.
✗ Branch 3 not taken.
|
299 | init(); |
45 | 299 | } | |
46 | |||
47 | //////////////////////////////////////////////////////////////////////////// | ||
48 | 592 | SessionTaskData::~SessionTaskData () | |
49 | { | ||
50 | 296 | for (SignalSet::const_iterator it = subscribedSet.begin(); | |
51 |
1/2✗ Branch 6 not taken.
✓ Branch 7 taken 296 times.
|
296 | it != subscribedSet.end(); it++) { |
52 | //log_debug("Auto unsubscribe from %s", (*it)->path.c_str()); | ||
53 | ✗ | static_cast<const PdServ::Signal*>(*it)->unsubscribe(sessionTask); | |
54 | } | ||
55 | 296 | } | |
56 | |||
57 | //////////////////////////////////////////////////////////////////////////// | ||
58 | // When this function exits, pdo | ||
59 | // * points to the end of the pdo list, | ||
60 | // * is a Data Pdo | ||
61 | // and its signalListId is valid | ||
62 | 299 | void SessionTaskData::init() | |
63 | { | ||
64 |
2/2✓ Branch 2 taken 148 times.
✓ Branch 3 taken 151 times.
|
299 | const Signal *signals[signalPosition.size()]; |
65 | 299 | size_t nelem; | |
66 | |||
67 | 299 | pdo = txMemBegin; | |
68 | 3 | while (true) { | |
69 | while (true) { | ||
70 | // Check whether pdo is valid | ||
71 |
2/4✓ Branch 2 taken 459 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 459 times.
|
616 | if (pdo < txMemBegin or pdo+1 >= txMemEnd) { |
72 | ✗ | pdo = txMemBegin; | |
73 | ✗ | break; | |
74 | } | ||
75 | |||
76 |
2/2✓ Branch 2 taken 302 times.
✓ Branch 3 taken 157 times.
|
459 | if (!pdo->next) { |
77 | // At end of pdo list. Get the signal list and test | ||
78 | // whether ith is a data pdo and that the | ||
79 | // signalListId matches | ||
80 | |||
81 |
1/2✓ Branch 8 taken 302 times.
✗ Branch 9 not taken.
|
302 | task->getSignalList(signals, &nelem, &signalListId); |
82 | |||
83 |
3/4✗ Branch 2 not taken.
✓ Branch 3 taken 302 times.
✓ Branch 4 taken 299 times.
✓ Branch 5 taken 3 times.
|
302 | if (pdo->type != Pdo::Data |
84 |
1/2✓ Branch 3 taken 299 times.
✗ Branch 4 not taken.
|
299 | or pdo->signalListId != signalListId) |
85 | break; | ||
86 | |||
87 | // OK. Everything is fine | ||
88 | 299 | seqNo = pdo->seqNo; | |
89 |
1/2✓ Branch 3 taken 299 times.
✗ Branch 4 not taken.
|
299 | loadSignalList(signals, nelem, signalListId); |
90 | |||
91 | log_debug("Session %p sync'ed: pdo=%p seqNo=%u" | ||
92 | " signalListId=%u", | ||
93 | this, (void *) pdo, seqNo, signalListId); | ||
94 | |||
95 | 598 | return; | |
96 | } | ||
97 | |||
98 | 157 | pdo = pdo->next; | |
99 | } | ||
100 | |||
101 | // Sleep for half task sample time in the hope that next time round | ||
102 | // there is a valid pdo | ||
103 |
1/2✓ Branch 28 taken 3 times.
✗ Branch 29 not taken.
|
6 | task->main->sleep( |
104 | 6 | std::max(50U, static_cast<unsigned>(500*task->sampleTime))); | |
105 | 299 | } | |
106 | } | ||
107 | |||
108 | //////////////////////////////////////////////////////////////////////////// | ||
109 | 47 | void SessionTaskData::subscribe(const Signal* s) | |
110 | { | ||
111 |
6/20✓ Branch 5 taken 47 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 47 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 47 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 47 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 47 times.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 47 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
|
94 | if (activeSet.find(s) != activeSet.end() |
112 |
6/16✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 47 times.
✓ Branch 8 taken 47 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 47 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 47 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
|
141 | or (subscribedSet.insert(s).second |
113 |
2/4✓ Branch 16 taken 47 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 47 times.
|
47 | and s->task->subscribe(s, this, true) |
114 |
4/20✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 47 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 47 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 47 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 47 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
|
47 | and transferredSet.find(s) != transferredSet.end())) { |
115 | ✗ | activeSet.insert(s); | |
116 | ✗ | sessionTask->newSignal(s); | |
117 | ✗ | return; | |
118 | } | ||
119 | } | ||
120 | |||
121 | //////////////////////////////////////////////////////////////////////////// | ||
122 | 44 | void SessionTaskData::unsubscribe(const Signal* s) | |
123 | { | ||
124 |
1/2✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
44 | if (subscribedSet.erase(s)) { |
125 | 44 | activeSet.erase(s); | |
126 | 44 | s->task->subscribe(s, this, false); | |
127 | } | ||
128 | 44 | } | |
129 | |||
130 | //////////////////////////////////////////////////////////////////////////// | ||
131 | 23407 | bool SessionTaskData::rxPdo (const struct timespec **time, | |
132 | const PdServ::TaskStatistics **statistics) | ||
133 | { | ||
134 |
2/2✓ Branch 2 taken 3901 times.
✓ Branch 3 taken 19506 times.
|
23451 | while (pdo->next) { |
135 | size_t n; | ||
136 | |||
137 | 3901 | pdo = pdo->next; | |
138 |
2/4✓ Branch 2 taken 3901 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3901 times.
|
3901 | if (pdo < txMemBegin or &pdo->data > txMemEnd) { |
139 | goto out; | ||
140 | } | ||
141 | |||
142 | 3901 | n = pdo->count; | |
143 | |||
144 |
3/5✗ Branch 2 not taken.
✓ Branch 3 taken 3901 times.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 3857 times.
✗ Branch 6 not taken.
|
3901 | switch (pdo->type) { |
145 | 44 | case Pdo::SignalList: | |
146 | { | ||
147 |
1/2✗ Branch 4 not taken.
✓ Branch 5 taken 44 times.
|
44 | const Signal *sp[signals->size()]; |
148 | |||
149 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
|
44 | if (&pdo->signalIdx + n > txMemEnd) { |
150 | ✗ | goto out; | |
151 | } | ||
152 | |||
153 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 44 times.
|
96 | for (size_t i = 0; i < n; ++i) { |
154 | 52 | size_t idx = (&pdo->signalIdx)[i]; | |
155 | |||
156 |
1/2✗ Branch 4 not taken.
✓ Branch 5 taken 52 times.
|
52 | if (idx >= signals->size()) |
157 | ✗ | goto out; | |
158 | |||
159 | 52 | sp[i] = (*signals)[idx]; | |
160 | } | ||
161 |
1/2✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
|
88 | loadSignalList(sp, n, pdo->signalListId); |
162 | } | ||
163 | |||
164 | 44 | break; | |
165 | |||
166 | 3857 | case Pdo::Data: | |
167 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 3857 times.
|
3857 | if (&pdo->data + pdoSize >= txMemEnd |
168 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 3857 times.
|
3857 | or pdo->signalListId != signalListId |
169 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 3857 times.
|
3857 | or pdo->seqNo - seqNo != 1) { |
170 | log_debug("%p + %zu >= %p; %u != %u; %i != 1; %u %u %u", | ||
171 | (void *) &pdo->data, pdoSize, (void *) txMemEnd, | ||
172 | pdo->signalListId, signalListId, | ||
173 | pdo->seqNo - seqNo, | ||
174 | &pdo->data + pdoSize >= txMemEnd, | ||
175 | pdo->signalListId != signalListId, | ||
176 | pdo->seqNo - seqNo != 1 | ||
177 | ); | ||
178 | goto out; | ||
179 | } | ||
180 | |||
181 | 3857 | seqNo = pdo->seqNo; | |
182 | 3857 | signalBuffer = &pdo->data; | |
183 | 3857 | *time = &pdo->time; | |
184 | 3857 | *statistics = &pdo->taskStatistics; | |
185 | |||
186 | 3857 | return true; | |
187 | |||
188 | ✗ | default: | |
189 | ✗ | goto out; | |
190 | } | ||
191 | } | ||
192 | |||
193 | 19506 | *time = &pdo->time; | |
194 | 19506 | *statistics = &pdo->taskStatistics; | |
195 | |||
196 | 19506 | return false; | |
197 | |||
198 | ✗ | out: | |
199 | log_debug("Session %p out of sync.", this); | ||
200 | ✗ | init(); | |
201 | ✗ | return true; | |
202 | } | ||
203 | |||
204 | //////////////////////////////////////////////////////////////////////////// | ||
205 | 343 | void SessionTaskData::loadSignalList(const Signal * const* sp, size_t n, | |
206 | unsigned int id) | ||
207 | { | ||
208 | log_debug("Loading %zu signals with id %u", n, id); | ||
209 | // cout << __func__ << " n=" << n << " id=" << id; | ||
210 |
1/2✓ Branch 7 taken 343 times.
✗ Branch 8 not taken.
|
343 | std::fill(signalPosition.begin(), signalPosition.end(), ~0U); |
211 | 343 | transferredSet.clear(); | |
212 | |||
213 | 343 | signalListId = id; | |
214 | 343 | pdoSize = 0; | |
215 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 343 times.
|
396 | for (size_t i = 0; i < n; ++i) { |
216 | 53 | signalPosition[sp[i]->index] = pdoSize; | |
217 | 53 | pdoSize += sp[i]->memSize; | |
218 | 53 | transferredSet.insert(sp[i]); | |
219 |
7/20✓ Branch 6 taken 53 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 53 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 53 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 53 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 53 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 47 times.
✓ Branch 23 taken 6 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
|
106 | if (subscribedSet.find(sp[i]) != subscribedSet.end() |
220 |
1/2✓ Branch 7 taken 52 times.
✗ Branch 8 not taken.
|
52 | and int(signalListId - sp[i]->subscriptionId) >= 0 |
221 |
10/16✓ Branch 0 taken 52 times.
✓ Branch 1 taken 1 times.
✓ Branch 5 taken 52 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 52 times.
✓ Branch 9 taken 47 times.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 52 times.
✓ Branch 12 taken 1 times.
✓ Branch 14 taken 52 times.
✓ Branch 15 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
158 | and activeSet.insert(sp[i]).second) { |
222 | 47 | sessionTask->newSignal(sp[i]); | |
223 | } | ||
224 | // cout << ' ' << sp[i]->index << '(' << pdoSize << ')'; | ||
225 | } | ||
226 | log_debug("pdosize=%zu", pdoSize); | ||
227 | // cout << endl; | ||
228 | 343 | } | |
229 | |||
230 | //////////////////////////////////////////////////////////////////////////// | ||
231 | 1179 | const char *SessionTaskData::getValue(const PdServ::Signal *s) const | |
232 | { | ||
233 | return | ||
234 |
1/2✓ Branch 1 taken 1179 times.
✗ Branch 2 not taken.
|
1179 | signalBuffer + signalPosition[static_cast<const Signal*>(s)->index]; |
235 | } | ||
236 | |||
237 | //////////////////////////////////////////////////////////////////////////// | ||
238 | ✗ | const struct timespec *SessionTaskData::getTaskTime() const | |
239 | { | ||
240 | ✗ | return &pdo->time; | |
241 | } | ||
242 | |||
243 | //////////////////////////////////////////////////////////////////////////// | ||
244 | ✗ | const PdServ::TaskStatistics* SessionTaskData::getTaskStatistics() const | |
245 | { | ||
246 | ✗ | return &pdo->taskStatistics; | |
247 | } | ||
248 |