From c4aeac89fc1e941bc852c6cefc2875c6a4dd8de0 Mon Sep 17 00:00:00 2001
From: Dario Casalinuovo <b.vitruvio@gmail.com>
Date: Tue, 17 Feb 2015 01:04:25 +0100
Subject: [PATCH] BTimeSource cleanup, rework slave nodes management which is
now using BObjectList.
---
src/kits/media/TimeSource.cpp | 332 +++++++++++++++++++++++++-----------------
1 file changed, 202 insertions(+), 130 deletions(-)
diff --git a/src/kits/media/TimeSource.cpp b/src/kits/media/TimeSource.cpp
index dae0244..43c33f1 100644
a
|
b
|
|
1 | 1 | /* |
2 | | * Copyright 2002-2012, Haiku. All Rights Reserved. |
3 | | * This file may be used under the terms of the MIT License. |
| 2 | * Copyright 2002-2015 Haiku, Inc. All rights reserved. |
| 3 | * Distributed under the terms of the MIT License. |
4 | 4 | * |
5 | | * Author: Marcus Overhagen |
| 5 | * Authors: |
| 6 | * Marcus Overhagen |
| 7 | * Dario Casalinuovo |
6 | 8 | */ |
7 | 9 | |
8 | 10 | |
9 | | #include <TimeSource.h> |
10 | 11 | #include <Autolock.h> |
| 12 | #include <ObjectList.h> |
| 13 | #include <TimeSource.h> |
| 14 | |
11 | 15 | #include <string.h> |
| 16 | |
12 | 17 | #include "debug.h" |
13 | 18 | #include "DataExchange.h" |
14 | 19 | #include "ServerInterface.h" |
… |
… |
namespace BPrivate { namespace media {
|
26 | 31 | |
27 | 32 | #define _atomic_read(p) atomic_or((p), 0) |
28 | 33 | |
29 | | #define TS_AREA_SIZE B_PAGE_SIZE // must be multiple of page size |
30 | | #define TS_INDEX_COUNT 128 // must be power of two |
| 34 | // must be multiple of page size |
| 35 | #define TS_AREA_SIZE B_PAGE_SIZE |
| 36 | // must be power of two |
| 37 | #define TS_INDEX_COUNT 128 |
31 | 38 | |
32 | | struct TimeSourceTransmit // sizeof(TimeSourceTransmit) must be <= TS_AREA_SIZE |
| 39 | // sizeof(TimeSourceTransmit) must be <= TS_AREA_SIZE |
| 40 | struct TimeSourceTransmit |
33 | 41 | { |
34 | 42 | int32 readindex; |
35 | 43 | int32 writeindex; |
… |
… |
struct TimeSourceTransmit // sizeof(TimeSourceTransmit) must be <= TS_AREA_SIZE
|
39 | 47 | float drift[TS_INDEX_COUNT]; |
40 | 48 | }; |
41 | 49 | |
42 | | #define SLAVE_NODES_COUNT 300 |
| 50 | #define MAX_SLAVE_NODES 300 |
43 | 51 | |
44 | | // XXX TODO: storage for slave nodes uses public data members, this should be changed |
45 | 52 | |
46 | | class SlaveNodes |
| 53 | class SlaveNode |
47 | 54 | { |
48 | 55 | public: |
49 | | SlaveNodes(); |
50 | | ~SlaveNodes(); |
| 56 | SlaveNode(media_node_id nodeId, port_id nodePort); |
| 57 | |
| 58 | media_node_id NodeId() const; |
| 59 | port_id NodePort() const; |
| 60 | |
| 61 | private: |
| 62 | media_node_id fNodeId; |
| 63 | port_id fNodePort; |
| 64 | }; |
| 65 | |
| 66 | |
| 67 | SlaveNode::SlaveNode(media_node_id nodeId, port_id nodePort) |
| 68 | { |
| 69 | fNodeId = nodeId; |
| 70 | fNodePort = nodePort; |
| 71 | } |
| 72 | |
| 73 | |
| 74 | media_node_id |
| 75 | SlaveNode::NodeId() const |
| 76 | { |
| 77 | return fNodeId; |
| 78 | } |
| 79 | |
| 80 | |
| 81 | port_id |
| 82 | SlaveNode::NodePort() const |
| 83 | { |
| 84 | return fNodePort; |
| 85 | } |
| 86 | |
| 87 | |
| 88 | class SlaveNodes : public BLocker |
| 89 | { |
51 | 90 | public: |
52 | | BLocker * locker; |
53 | | int32 count; |
54 | | media_node_id node_id[SLAVE_NODES_COUNT]; |
55 | | port_id node_port[SLAVE_NODES_COUNT]; |
| 91 | SlaveNodes(); |
| 92 | |
| 93 | int32 CountSlaves() const; |
| 94 | |
| 95 | port_id PortAt(int32 index) const; |
| 96 | SlaveNode* SlaveAt(int32 index) const; |
| 97 | |
| 98 | bool InsertSlave(const media_node& node); |
| 99 | bool RemoveSlave(const media_node& node); |
| 100 | |
| 101 | private: |
| 102 | BObjectList<SlaveNode> fSlaveList; |
56 | 103 | }; |
57 | 104 | |
58 | 105 | |
59 | 106 | SlaveNodes::SlaveNodes() |
60 | 107 | { |
61 | | locker = new BLocker("BTimeSource SlaveNodes"); |
62 | | count = 0; |
63 | | memset(node_id, 0, sizeof(node_id)); |
64 | | memset(node_port, 0, sizeof(node_port)); |
| 108 | fSlaveList = BObjectList<SlaveNode>(true); |
| 109 | } |
| 110 | |
| 111 | |
| 112 | int32 |
| 113 | SlaveNodes::CountSlaves() const |
| 114 | { |
| 115 | return fSlaveList.CountItems(); |
65 | 116 | } |
66 | 117 | |
67 | 118 | |
68 | | SlaveNodes::~SlaveNodes() |
| 119 | port_id |
| 120 | SlaveNodes::PortAt(int32 index) const |
69 | 121 | { |
70 | | delete locker; |
| 122 | return SlaveAt(index)->NodePort(); |
71 | 123 | } |
72 | 124 | |
73 | 125 | |
74 | | } } |
| 126 | SlaveNode* |
| 127 | SlaveNodes::SlaveAt(int32 index) const |
| 128 | { |
| 129 | return fSlaveList.ItemAt(index); |
| 130 | } |
| 131 | |
| 132 | |
| 133 | bool |
| 134 | SlaveNodes::InsertSlave(const media_node& node) |
| 135 | { |
| 136 | return fSlaveList.AddItem(new SlaveNode(node.node, node.port)); |
| 137 | } |
| 138 | |
| 139 | |
| 140 | bool |
| 141 | SlaveNodes::RemoveSlave(const media_node& node) |
| 142 | { |
| 143 | for (int i = 0; i < CountSlaves(); i++) { |
| 144 | SlaveNode* slave = fSlaveList.ItemAt(i); |
| 145 | if (slave->NodeId() == node.node |
| 146 | && slave->NodePort() == node.port) { |
| 147 | return fSlaveList.RemoveItemAt(i); |
| 148 | } |
| 149 | } |
| 150 | return false; |
| 151 | } |
| 152 | |
| 153 | |
| 154 | } } // namespace BPrivate::media |
75 | 155 | |
76 | 156 | |
77 | 157 | /************************************************************* |
… |
… |
BTimeSource::~BTimeSource()
|
92 | 172 | |
93 | 173 | status_t |
94 | 174 | BTimeSource::SnoozeUntil(bigtime_t performance_time, |
95 | | bigtime_t with_latency, |
96 | | bool retry_signals) |
| 175 | bigtime_t with_latency, bool retry_signals) |
97 | 176 | { |
98 | 177 | CALLED(); |
99 | 178 | bigtime_t time; |
… |
… |
BTimeSource::PerformanceTimeFor(bigtime_t real_time)
|
125 | 204 | if (GetTime(&last_perf_time, &last_real_time, &last_drift) != B_OK) |
126 | 205 | debugger("BTimeSource::PerformanceTimeFor: GetTime failed"); |
127 | 206 | |
128 | | return last_perf_time + (bigtime_t)((real_time - last_real_time) * last_drift); |
| 207 | return last_perf_time |
| 208 | + (bigtime_t)((real_time - last_real_time) * last_drift); |
129 | 209 | } |
130 | 210 | |
131 | 211 | |
132 | 212 | bigtime_t |
133 | 213 | BTimeSource::RealTimeFor(bigtime_t performance_time, |
134 | | bigtime_t with_latency) |
| 214 | bigtime_t with_latency) |
135 | 215 | { |
136 | 216 | PRINT(8, "CALLED BTimeSource::RealTimeFor()\n"); |
137 | 217 | |
… |
… |
BTimeSource::RealTimeFor(bigtime_t performance_time,
|
146 | 226 | if (GetTime(&last_perf_time, &last_real_time, &last_drift) != B_OK) |
147 | 227 | debugger("BTimeSource::RealTimeFor: GetTime failed"); |
148 | 228 | |
149 | | return last_real_time - with_latency + (bigtime_t)((performance_time - last_perf_time) / last_drift); |
| 229 | return last_real_time - with_latency |
| 230 | + (bigtime_t)((performance_time - last_perf_time) / last_drift); |
150 | 231 | } |
151 | 232 | |
152 | 233 | |
… |
… |
BTimeSource::IsRunning()
|
157 | 238 | |
158 | 239 | bool isrunning; |
159 | 240 | |
| 241 | // The system time source is always running |
160 | 242 | if (fIsRealtime) |
161 | | isrunning = true; // The system time source is always running :) |
| 243 | isrunning = true; |
162 | 244 | else |
163 | 245 | isrunning = fBuf ? atomic_add(&fBuf->isrunning, 0) : fStarted; |
164 | 246 | |
… |
… |
BTimeSource::IsRunning()
|
169 | 251 | |
170 | 252 | |
171 | 253 | status_t |
172 | | BTimeSource::GetTime(bigtime_t *performance_time, |
173 | | bigtime_t *real_time, |
174 | | float *drift) |
| 254 | BTimeSource::GetTime(bigtime_t* performance_time, |
| 255 | bigtime_t* real_time, float* drift) |
175 | 256 | { |
176 | 257 | PRINT(8, "CALLED BTimeSource::GetTime()\n"); |
177 | 258 | |
… |
… |
BTimeSource::GetTime(bigtime_t *performance_time,
|
180 | 261 | *drift = 1.0f; |
181 | 262 | return B_OK; |
182 | 263 | } |
183 | | // if (fBuf == 0) { |
184 | | // PRINT(1, "BTimeSource::GetTime: fBuf == 0, name %s, id %ld\n",Name(),ID()); |
185 | | // *performance_time = *real_time = system_time(); |
186 | | // *drift = 1.0f; |
187 | | // return B_OK; |
188 | | // } |
189 | 264 | |
190 | 265 | int32 index; |
191 | 266 | index = _atomic_read(&fBuf->readindex); |
… |
… |
BTimeSource::GetTime(bigtime_t *performance_time,
|
194 | 269 | *performance_time = fBuf->perftime[index]; |
195 | 270 | *drift = fBuf->drift[index]; |
196 | 271 | |
197 | | // if (*real_time == 0) { |
198 | | // *performance_time = *real_time = system_time(); |
199 | | // *drift = 1.0f; |
200 | | // return B_OK; |
201 | | // } |
202 | | // printf("BTimeSource::GetTime timesource %ld, index %ld, perf %16Ld, real %16Ld, drift %2.2f\n", ID(), index, *performance_time, *real_time, *drift); |
203 | | |
204 | 272 | TRACE_TIMESOURCE("BTimeSource::GetTime timesource %" B_PRId32 |
205 | 273 | ", perf %16" B_PRId64 ", real %16" B_PRId64 ", drift %2.2f\n", ID(), |
206 | 274 | *performance_time, *real_time, *drift); |
… |
… |
BTimeSource::RealTime()
|
217 | 285 | |
218 | 286 | |
219 | 287 | status_t |
220 | | BTimeSource::GetStartLatency(bigtime_t *out_latency) |
| 288 | BTimeSource::GetStartLatency(bigtime_t* out_latency) |
221 | 289 | { |
222 | 290 | CALLED(); |
223 | 291 | *out_latency = 0; |
… |
… |
BTimeSource::GetStartLatency(bigtime_t *out_latency)
|
229 | 297 | *************************************************************/ |
230 | 298 | |
231 | 299 | |
232 | | BTimeSource::BTimeSource() : |
| 300 | BTimeSource::BTimeSource() |
| 301 | : |
233 | 302 | BMediaNode("This one is never called"), |
234 | 303 | fStarted(false), |
235 | 304 | fArea(-1), |
… |
… |
BTimeSource::BTimeSource() :
|
239 | 308 | { |
240 | 309 | CALLED(); |
241 | 310 | AddNodeKind(B_TIME_SOURCE); |
242 | | // printf("##### BTimeSource::BTimeSource() name %s, id %ld\n", Name(), ID()); |
243 | | |
244 | 311 | // This constructor is only called by real time sources that inherit |
245 | 312 | // BTimeSource. We create the communication area in FinishCreate(), |
246 | 313 | // since we don't have a correct ID() until this node is registered. |
… |
… |
BTimeSource::BTimeSource() :
|
248 | 315 | |
249 | 316 | |
250 | 317 | status_t |
251 | | BTimeSource::HandleMessage(int32 message, |
252 | | const void *rawdata, |
253 | | size_t size) |
| 318 | BTimeSource::HandleMessage(int32 message, const void* rawdata, |
| 319 | size_t size) |
254 | 320 | { |
255 | 321 | PRINT(4, "BTimeSource::HandleMessage %#" B_PRIx32 ", node %" B_PRId32 "\n", |
256 | 322 | message, fNodeID); |
… |
… |
BTimeSource::HandleMessage(int32 message,
|
258 | 324 | switch (message) { |
259 | 325 | case TIMESOURCE_OP: |
260 | 326 | { |
261 | | const time_source_op_info *data = static_cast<const time_source_op_info *>(rawdata); |
| 327 | const time_source_op_info* data |
| 328 | = static_cast<const time_source_op_info*>(rawdata); |
262 | 329 | |
263 | 330 | status_t result; |
264 | 331 | result = TimeSourceOp(*data, NULL); |
… |
… |
BTimeSource::HandleMessage(int32 message,
|
285 | 352 | |
286 | 353 | case TIMESOURCE_ADD_SLAVE_NODE: |
287 | 354 | { |
288 | | const timesource_add_slave_node_command *data = static_cast<const timesource_add_slave_node_command *>(rawdata); |
| 355 | const timesource_add_slave_node_command* data |
| 356 | = static_cast<const timesource_add_slave_node_command*>(rawdata); |
289 | 357 | DirectAddMe(data->node); |
290 | 358 | return B_OK; |
291 | 359 | } |
292 | 360 | |
293 | 361 | case TIMESOURCE_REMOVE_SLAVE_NODE: |
294 | 362 | { |
295 | | const timesource_remove_slave_node_command *data = static_cast<const timesource_remove_slave_node_command *>(rawdata); |
| 363 | const timesource_remove_slave_node_command* data |
| 364 | = static_cast<const timesource_remove_slave_node_command*>(rawdata); |
296 | 365 | DirectRemoveMe(data->node); |
297 | 366 | return B_OK; |
298 | 367 | } |
299 | 368 | |
300 | 369 | case TIMESOURCE_GET_START_LATENCY: |
301 | 370 | { |
302 | | const timesource_get_start_latency_request *request = static_cast<const timesource_get_start_latency_request *>(rawdata); |
| 371 | const timesource_get_start_latency_request* request |
| 372 | = static_cast<const timesource_get_start_latency_request*>(rawdata); |
303 | 373 | timesource_get_start_latency_reply reply; |
304 | 374 | rv = GetStartLatency(&reply.start_latency); |
305 | 375 | request->SendReply(rv, &reply, sizeof(reply)); |
… |
… |
BTimeSource::HandleMessage(int32 message,
|
312 | 382 | |
313 | 383 | void |
314 | 384 | BTimeSource::PublishTime(bigtime_t performance_time, |
315 | | bigtime_t real_time, |
316 | | float drift) |
| 385 | bigtime_t real_time, float drift) |
317 | 386 | { |
318 | 387 | TRACE_TIMESOURCE("BTimeSource::PublishTime timesource %" B_PRId32 |
319 | 388 | ", perf %16" B_PRId64 ", real %16" B_PRId64 ", drift %2.2f\n", ID(), |
… |
… |
BTimeSource::PublishTime(bigtime_t performance_time,
|
332 | 401 | fBuf->perftime[index] = performance_time; |
333 | 402 | fBuf->drift[index] = drift; |
334 | 403 | atomic_add(&fBuf->readindex, 1); |
335 | | |
336 | | // printf("BTimeSource::PublishTime timesource %ld, write index %ld, perf %16Ld, real %16Ld, drift %2.2f\n", ID(), index, performance_time, real_time, drift); |
337 | 404 | } |
338 | 405 | |
339 | 406 | |
340 | 407 | void |
341 | 408 | BTimeSource::BroadcastTimeWarp(bigtime_t at_real_time, |
342 | | bigtime_t new_performance_time) |
| 409 | bigtime_t new_performance_time) |
343 | 410 | { |
344 | 411 | CALLED(); |
345 | 412 | ASSERT(fSlaveNodes != NULL); |
… |
… |
BTimeSource::BroadcastTimeWarp(bigtime_t at_real_time,
|
350 | 417 | ", new_performance_time %" B_PRId64 "\n", at_real_time, |
351 | 418 | new_performance_time); |
352 | 419 | |
353 | | BAutolock lock(fSlaveNodes->locker); |
| 420 | BAutolock lock(fSlaveNodes); |
354 | 421 | |
355 | | for (int i = 0, n = 0; i < SLAVE_NODES_COUNT && n != fSlaveNodes->count; i++) { |
356 | | if (fSlaveNodes->node_id[i] != 0) { |
357 | | node_time_warp_command cmd; |
358 | | cmd.at_real_time = at_real_time; |
359 | | cmd.to_performance_time = new_performance_time; |
360 | | SendToPort(fSlaveNodes->node_port[i], NODE_TIME_WARP, &cmd, sizeof(cmd)); |
361 | | n++; |
362 | | } |
| 422 | for (int i = 0; i < fSlaveNodes->CountSlaves(); i++) { |
| 423 | node_time_warp_command cmd; |
| 424 | cmd.at_real_time = at_real_time; |
| 425 | cmd.to_performance_time = new_performance_time; |
| 426 | SendToPort(fSlaveNodes->PortAt(i), NODE_TIME_WARP, |
| 427 | &cmd, sizeof(cmd)); |
363 | 428 | } |
364 | 429 | } |
365 | 430 | |
… |
… |
BTimeSource::SendRunMode(run_mode mode)
|
372 | 437 | |
373 | 438 | // send the run mode change to all slaved nodes |
374 | 439 | |
375 | | BAutolock lock(fSlaveNodes->locker); |
| 440 | BAutolock lock(fSlaveNodes); |
376 | 441 | |
377 | | for (int i = 0, n = 0; i < SLAVE_NODES_COUNT && n != fSlaveNodes->count; i++) { |
378 | | if (fSlaveNodes->node_id[i] != 0) { |
379 | | node_set_run_mode_command cmd; |
380 | | cmd.mode = mode; |
381 | | SendToPort(fSlaveNodes->node_port[i], NODE_SET_RUN_MODE, &cmd, sizeof(cmd)); |
382 | | n++; |
383 | | } |
| 442 | for (int i = 0; i < fSlaveNodes->CountSlaves(); i++) { |
| 443 | node_set_run_mode_command cmd; |
| 444 | cmd.mode = mode; |
| 445 | SendToPort(fSlaveNodes->PortAt(i), NODE_SET_RUN_MODE, |
| 446 | &cmd, sizeof(cmd)); |
384 | 447 | } |
385 | 448 | } |
386 | 449 | |
… |
… |
status_t BTimeSource::_Reserved_TimeSource_4(void *) { return B_ERROR; }
|
410 | 473 | status_t BTimeSource::_Reserved_TimeSource_5(void *) { return B_ERROR; } |
411 | 474 | |
412 | 475 | /* explicit */ |
413 | | BTimeSource::BTimeSource(media_node_id id) : |
| 476 | BTimeSource::BTimeSource(media_node_id id) |
| 477 | : |
414 | 478 | BMediaNode("This one is never called"), |
415 | 479 | fStarted(false), |
416 | 480 | fArea(-1), |
… |
… |
BTimeSource::BTimeSource(media_node_id id) :
|
421 | 485 | CALLED(); |
422 | 486 | AddNodeKind(B_TIME_SOURCE); |
423 | 487 | ASSERT(id > 0); |
424 | | // printf("###### explicit BTimeSource::BTimeSource() id %ld, name %s\n", id, Name()); |
425 | 488 | |
426 | | // This constructor is only called by the derived BPrivate::media::TimeSourceObject objects |
427 | | // We create a clone of the communication area |
| 489 | // This constructor is only called by the derived |
| 490 | // BPrivate::media::TimeSourceObject objects |
| 491 | // We create a clone of the communication area. |
428 | 492 | char name[32]; |
429 | 493 | area_id area; |
430 | 494 | sprintf(name, "__timesource_buf_%" B_PRId32, id); |
… |
… |
BTimeSource::BTimeSource(media_node_id id) :
|
435 | 499 | return; |
436 | 500 | } |
437 | 501 | sprintf(name, "__cloned_timesource_buf_%" B_PRId32, id); |
438 | | fArea = clone_area(name, reinterpret_cast<void **>(const_cast<BPrivate::media::TimeSourceTransmit **>(&fBuf)), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area); |
| 502 | |
| 503 | void** buf = reinterpret_cast<void**> |
| 504 | (const_cast<BPrivate::media::TimeSourceTransmit**>(&fBuf)); |
| 505 | |
| 506 | fArea = clone_area(name, buf, B_ANY_ADDRESS, |
| 507 | B_READ_AREA | B_WRITE_AREA, area); |
| 508 | |
439 | 509 | if (fArea <= 0) { |
440 | 510 | ERROR("BTimeSource::BTimeSource couldn't clone area, node %" B_PRId32 |
441 | 511 | "\n", id); |
… |
… |
void
|
448 | 518 | BTimeSource::FinishCreate() |
449 | 519 | { |
450 | 520 | CALLED(); |
451 | | //printf("BTimeSource::FinishCreate(), id %ld\n", ID()); |
452 | 521 | |
453 | 522 | char name[32]; |
454 | 523 | sprintf(name, "__timesource_buf_%" B_PRId32, ID()); |
455 | | fArea = create_area(name, reinterpret_cast<void **>(const_cast<BPrivate::media::TimeSourceTransmit **>(&fBuf)), B_ANY_ADDRESS, TS_AREA_SIZE, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA); |
| 524 | |
| 525 | void** buf = reinterpret_cast<void**> |
| 526 | (const_cast<BPrivate::media::TimeSourceTransmit**>(&fBuf)); |
| 527 | |
| 528 | fArea = create_area(name, buf, B_ANY_ADDRESS, TS_AREA_SIZE, |
| 529 | B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA); |
| 530 | |
456 | 531 | if (fArea <= 0) { |
457 | 532 | ERROR("BTimeSource::BTimeSource couldn't create area, node %" B_PRId32 |
458 | 533 | "\n", ID()); |
… |
… |
BTimeSource::FinishCreate()
|
469 | 544 | |
470 | 545 | |
471 | 546 | status_t |
472 | | BTimeSource::RemoveMe(BMediaNode *node) |
| 547 | BTimeSource::RemoveMe(BMediaNode* node) |
473 | 548 | { |
474 | 549 | CALLED(); |
475 | 550 | if (fKinds & NODE_KIND_SHADOW_TIMESOURCE) { |
476 | 551 | timesource_remove_slave_node_command cmd; |
477 | 552 | cmd.node = node->Node(); |
478 | | SendToPort(fControlPort, TIMESOURCE_REMOVE_SLAVE_NODE, &cmd, sizeof(cmd)); |
| 553 | SendToPort(fControlPort, TIMESOURCE_REMOVE_SLAVE_NODE, |
| 554 | &cmd, sizeof(cmd)); |
479 | 555 | } else { |
480 | 556 | DirectRemoveMe(node->Node()); |
481 | 557 | } |
… |
… |
BTimeSource::RemoveMe(BMediaNode *node)
|
484 | 560 | |
485 | 561 | |
486 | 562 | status_t |
487 | | BTimeSource::AddMe(BMediaNode *node) |
| 563 | BTimeSource::AddMe(BMediaNode* node) |
488 | 564 | { |
489 | 565 | CALLED(); |
490 | 566 | if (fKinds & NODE_KIND_SHADOW_TIMESOURCE) { |
… |
… |
BTimeSource::AddMe(BMediaNode *node)
|
499 | 575 | |
500 | 576 | |
501 | 577 | void |
502 | | BTimeSource::DirectAddMe(const media_node &node) |
| 578 | BTimeSource::DirectAddMe(const media_node& node) |
503 | 579 | { |
504 | 580 | // XXX this code has race conditions and is pretty dumb, and it |
505 | 581 | // XXX won't detect nodes that crash and don't remove themself. |
506 | 582 | |
507 | 583 | CALLED(); |
508 | 584 | ASSERT(fSlaveNodes != NULL); |
509 | | BAutolock lock(fSlaveNodes->locker); |
| 585 | BAutolock lock(fSlaveNodes); |
510 | 586 | |
511 | | if (fSlaveNodes->count == SLAVE_NODES_COUNT) { |
| 587 | if (fSlaveNodes->CountSlaves() == MAX_SLAVE_NODES) { |
512 | 588 | ERROR("BTimeSource::DirectAddMe out of slave node slots\n"); |
513 | 589 | return; |
514 | 590 | } |
… |
… |
BTimeSource::DirectAddMe(const media_node &node)
|
516 | 592 | ERROR("BTimeSource::DirectAddMe should not add itself to slave nodes\n"); |
517 | 593 | return; |
518 | 594 | } |
519 | | for (int i = 0; i < SLAVE_NODES_COUNT; i++) { |
520 | | if (fSlaveNodes->node_id[i] == 0) { |
521 | | fSlaveNodes->node_id[i] = node.node; |
522 | | fSlaveNodes->node_port[i] = node.port; |
523 | | fSlaveNodes->count += 1; |
524 | | if (fSlaveNodes->count == 1) { |
525 | | // start the time source |
526 | | time_source_op_info msg; |
527 | | msg.op = B_TIMESOURCE_START; |
528 | | msg.real_time = RealTime(); |
529 | | TRACE_TIMESOURCE("starting time source %" B_PRId32 "\n", ID()); |
530 | | write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg)); |
531 | | } |
532 | | return; |
533 | | } |
| 595 | |
| 596 | if (fSlaveNodes->InsertSlave(node) != true) { |
| 597 | ERROR("BTimeSource::DirectAddMe failed\n"); |
| 598 | return; |
| 599 | } |
| 600 | |
| 601 | if (fSlaveNodes->CountSlaves() == 1) { |
| 602 | // start the time source |
| 603 | time_source_op_info msg; |
| 604 | msg.op = B_TIMESOURCE_START; |
| 605 | msg.real_time = RealTime(); |
| 606 | |
| 607 | TRACE_TIMESOURCE("starting time source %" B_PRId32 "\n", ID()); |
| 608 | |
| 609 | write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg)); |
534 | 610 | } |
535 | | ERROR("BTimeSource::DirectAddMe failed\n"); |
536 | 611 | } |
537 | 612 | |
538 | 613 | void |
539 | | BTimeSource::DirectRemoveMe(const media_node &node) |
| 614 | BTimeSource::DirectRemoveMe(const media_node& node) |
540 | 615 | { |
541 | 616 | // XXX this code has race conditions and is pretty dumb, and it |
542 | 617 | // XXX won't detect nodes that crash and don't remove themself. |
543 | 618 | |
544 | 619 | CALLED(); |
545 | 620 | ASSERT(fSlaveNodes != NULL); |
546 | | BAutolock lock(fSlaveNodes->locker); |
| 621 | BAutolock lock(fSlaveNodes); |
547 | 622 | |
548 | | if (fSlaveNodes->count == 0) { |
| 623 | if (fSlaveNodes->CountSlaves() == 0) { |
549 | 624 | ERROR("BTimeSource::DirectRemoveMe no slots used\n"); |
550 | 625 | return; |
551 | 626 | } |
552 | | for (int i = 0; i < SLAVE_NODES_COUNT; i++) { |
553 | | if (fSlaveNodes->node_id[i] == node.node && fSlaveNodes->node_port[i] == node.port) { |
554 | | fSlaveNodes->node_id[i] = 0; |
555 | | fSlaveNodes->node_port[i] = 0; |
556 | | fSlaveNodes->count -= 1; |
557 | | if (fSlaveNodes->count == 0) { |
558 | | // stop the time source |
559 | | time_source_op_info msg; |
560 | | msg.op = B_TIMESOURCE_STOP_IMMEDIATELY; |
561 | | msg.real_time = RealTime(); |
562 | | TRACE_TIMESOURCE("stopping time source %" B_PRId32 "\n", ID()); |
563 | | write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg)); |
564 | | } |
565 | | return; |
566 | | } |
| 627 | |
| 628 | if (fSlaveNodes->RemoveSlave(node) != true) { |
| 629 | ERROR("BTimeSource::DirectRemoveMe failed\n"); |
| 630 | return; |
| 631 | } |
| 632 | |
| 633 | if (fSlaveNodes->CountSlaves() == 0) { |
| 634 | // stop the time source |
| 635 | time_source_op_info msg; |
| 636 | msg.op = B_TIMESOURCE_STOP_IMMEDIATELY; |
| 637 | msg.real_time = RealTime(); |
| 638 | |
| 639 | TRACE_TIMESOURCE("stopping time source %" B_PRId32 "\n", ID()); |
| 640 | |
| 641 | write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg)); |
567 | 642 | } |
568 | | ERROR("BTimeSource::DirectRemoveMe failed\n"); |
569 | 643 | } |
570 | 644 | |
571 | 645 | void |
… |
… |
BTimeSource::DirectStart(bigtime_t at)
|
580 | 654 | |
581 | 655 | |
582 | 656 | void |
583 | | BTimeSource::DirectStop(bigtime_t at, |
584 | | bool immediate) |
| 657 | BTimeSource::DirectStop(bigtime_t at, bool immediate) |
585 | 658 | { |
586 | 659 | CALLED(); |
587 | 660 | if (fBuf) |
… |
… |
BTimeSource::DirectStop(bigtime_t at,
|
592 | 665 | |
593 | 666 | |
594 | 667 | void |
595 | | BTimeSource::DirectSeek(bigtime_t to, |
596 | | bigtime_t at) |
| 668 | BTimeSource::DirectSeek(bigtime_t to, bigtime_t at) |
597 | 669 | { |
598 | 670 | UNIMPLEMENTED(); |
599 | 671 | } |