Ticket #11852: 0001-BTimeSource-cleanup-rework-slave-nodes-management-wh.patch

File 0001-BTimeSource-cleanup-rework-slave-nodes-management-wh.patch, 18.3 KB (added by Barrett, 10 years ago)

Updated patch with just two little fixes.

  • src/kits/media/TimeSource.cpp

    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  
    11/*
    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.
    44 *
    5  * Author: Marcus Overhagen
     5 * Authors:
     6 *      Marcus Overhagen
     7 *      Dario Casalinuovo
    68 */
    79
    810
    9 #include <TimeSource.h>
    1011#include <Autolock.h>
     12#include <ObjectList.h>
     13#include <TimeSource.h>
     14
    1115#include <string.h>
     16
    1217#include "debug.h"
    1318#include "DataExchange.h"
    1419#include "ServerInterface.h"
    namespace BPrivate { namespace media {  
    2631
    2732#define _atomic_read(p)     atomic_or((p), 0)
    2833
    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
    3138
    32 struct TimeSourceTransmit // sizeof(TimeSourceTransmit) must be <= TS_AREA_SIZE
     39// sizeof(TimeSourceTransmit) must be <= TS_AREA_SIZE
     40struct TimeSourceTransmit
    3341{
    3442    int32 readindex;
    3543    int32 writeindex;
    struct TimeSourceTransmit // sizeof(TimeSourceTransmit) must be <= TS_AREA_SIZE  
    3947    float drift[TS_INDEX_COUNT];
    4048};
    4149
    42 #define SLAVE_NODES_COUNT 300
     50#define MAX_SLAVE_NODES 300
    4351
    44 // XXX TODO: storage for slave nodes uses public data members, this should be changed
    4552
    46 class SlaveNodes
     53class SlaveNode
    4754{
    4855public:
    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
     61private:
     62    media_node_id           fNodeId;
     63    port_id                 fNodePort;
     64};
     65
     66
     67SlaveNode::SlaveNode(media_node_id nodeId, port_id nodePort)
     68{
     69    fNodeId = nodeId;
     70    fNodePort = nodePort;
     71}
     72
     73
     74media_node_id
     75SlaveNode::NodeId() const
     76{
     77    return fNodeId;
     78}
     79
     80
     81port_id
     82SlaveNode::NodePort() const
     83{
     84    return fNodePort;
     85}
     86
     87
     88class SlaveNodes : public BLocker
     89{
    5190public:
    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
     101private:
     102    BObjectList<SlaveNode>  fSlaveList;
    56103};
    57104
    58105
    59106SlaveNodes::SlaveNodes()
    60107{
    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
     112int32
     113SlaveNodes::CountSlaves() const
     114{
     115    return fSlaveList.CountItems();
    65116}
    66117
    67118
    68 SlaveNodes::~SlaveNodes()
     119port_id
     120SlaveNodes::PortAt(int32 index) const
    69121{
    70     delete locker;
     122    return SlaveAt(index)->NodePort();
    71123}
    72124
    73125
    74 } }
     126SlaveNode*
     127SlaveNodes::SlaveAt(int32 index) const
     128{
     129    return fSlaveList.ItemAt(index);
     130}
     131
     132
     133bool
     134SlaveNodes::InsertSlave(const media_node& node)
     135{
     136    return fSlaveList.AddItem(new SlaveNode(node.node, node.port));
     137}
     138
     139
     140bool
     141SlaveNodes::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
    75155
    76156
    77157/*************************************************************
    BTimeSource::~BTimeSource()  
    92172
    93173status_t
    94174BTimeSource::SnoozeUntil(bigtime_t performance_time,
    95                          bigtime_t with_latency,
    96                          bool retry_signals)
     175    bigtime_t with_latency, bool retry_signals)
    97176{
    98177    CALLED();
    99178    bigtime_t time;
    BTimeSource::PerformanceTimeFor(bigtime_t real_time)  
    125204    if (GetTime(&last_perf_time, &last_real_time, &last_drift) != B_OK)
    126205        debugger("BTimeSource::PerformanceTimeFor: GetTime failed");
    127206
    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);
    129209}
    130210
    131211
    132212bigtime_t
    133213BTimeSource::RealTimeFor(bigtime_t performance_time,
    134                          bigtime_t with_latency)
     214    bigtime_t with_latency)
    135215{
    136216    PRINT(8, "CALLED BTimeSource::RealTimeFor()\n");
    137217
    BTimeSource::RealTimeFor(bigtime_t performance_time,  
    146226    if (GetTime(&last_perf_time, &last_real_time, &last_drift) != B_OK)
    147227        debugger("BTimeSource::RealTimeFor: GetTime failed");
    148228
    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);
    150231}
    151232
    152233
    BTimeSource::IsRunning()  
    157238
    158239    bool isrunning;
    159240
     241    // The system time source is always running
    160242    if (fIsRealtime)
    161         isrunning = true; // The system time source is always running :)
     243        isrunning = true;
    162244    else
    163245        isrunning = fBuf ? atomic_add(&fBuf->isrunning, 0) : fStarted;
    164246
    BTimeSource::IsRunning()  
    169251
    170252
    171253status_t
    172 BTimeSource::GetTime(bigtime_t *performance_time,
    173                      bigtime_t *real_time,
    174                      float *drift)
     254BTimeSource::GetTime(bigtime_t* performance_time,
     255    bigtime_t* real_time, float* drift)
    175256{
    176257    PRINT(8, "CALLED BTimeSource::GetTime()\n");
    177258
    BTimeSource::GetTime(bigtime_t *performance_time,  
    180261        *drift = 1.0f;
    181262        return B_OK;
    182263    }
    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 //  }
    189264
    190265    int32 index;
    191266    index = _atomic_read(&fBuf->readindex);
    BTimeSource::GetTime(bigtime_t *performance_time,  
    194269    *performance_time = fBuf->perftime[index];
    195270    *drift = fBuf->drift[index];
    196271
    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 
    204272    TRACE_TIMESOURCE("BTimeSource::GetTime     timesource %" B_PRId32
    205273        ", perf %16" B_PRId64 ", real %16" B_PRId64 ", drift %2.2f\n", ID(),
    206274        *performance_time, *real_time, *drift);
    BTimeSource::RealTime()  
    217285
    218286
    219287status_t
    220 BTimeSource::GetStartLatency(bigtime_t *out_latency)
     288BTimeSource::GetStartLatency(bigtime_t* out_latency)
    221289{
    222290    CALLED();
    223291    *out_latency = 0;
    BTimeSource::GetStartLatency(bigtime_t *out_latency)  
    229297 *************************************************************/
    230298
    231299
    232 BTimeSource::BTimeSource() :
     300BTimeSource::BTimeSource()
     301    :
    233302    BMediaNode("This one is never called"),
    234303    fStarted(false),
    235304    fArea(-1),
    BTimeSource::BTimeSource() :  
    239308{
    240309    CALLED();
    241310    AddNodeKind(B_TIME_SOURCE);
    242 //  printf("##### BTimeSource::BTimeSource() name %s, id %ld\n", Name(), ID());
    243 
    244311    // This constructor is only called by real time sources that inherit
    245312    // BTimeSource. We create the communication area in FinishCreate(),
    246313    // since we don't have a correct ID() until this node is registered.
    BTimeSource::BTimeSource() :  
    248315
    249316
    250317status_t
    251 BTimeSource::HandleMessage(int32 message,
    252                            const void *rawdata,
    253                            size_t size)
     318BTimeSource::HandleMessage(int32 message, const void* rawdata,
     319    size_t size)
    254320{
    255321    PRINT(4, "BTimeSource::HandleMessage %#" B_PRIx32 ", node %" B_PRId32 "\n",
    256322        message, fNodeID);
    BTimeSource::HandleMessage(int32 message,  
    258324    switch (message) {
    259325        case TIMESOURCE_OP:
    260326        {
    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);
    262329
    263330            status_t result;
    264331            result = TimeSourceOp(*data, NULL);
    BTimeSource::HandleMessage(int32 message,  
    285352
    286353        case TIMESOURCE_ADD_SLAVE_NODE:
    287354        {
    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);
    289357            DirectAddMe(data->node);
    290358            return B_OK;
    291359        }
    292360
    293361        case TIMESOURCE_REMOVE_SLAVE_NODE:
    294362        {
    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);
    296365            DirectRemoveMe(data->node);
    297366            return B_OK;
    298367        }
    299368
    300369        case TIMESOURCE_GET_START_LATENCY:
    301370        {
    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);
    303373            timesource_get_start_latency_reply reply;
    304374            rv = GetStartLatency(&reply.start_latency);
    305375            request->SendReply(rv, &reply, sizeof(reply));
    BTimeSource::HandleMessage(int32 message,  
    312382
    313383void
    314384BTimeSource::PublishTime(bigtime_t performance_time,
    315                          bigtime_t real_time,
    316                          float drift)
     385    bigtime_t real_time, float drift)
    317386{
    318387    TRACE_TIMESOURCE("BTimeSource::PublishTime timesource %" B_PRId32
    319388        ", perf %16" B_PRId64 ", real %16" B_PRId64 ", drift %2.2f\n", ID(),
    BTimeSource::PublishTime(bigtime_t performance_time,  
    332401    fBuf->perftime[index] = performance_time;
    333402    fBuf->drift[index] = drift;
    334403    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);
    337404}
    338405
    339406
    340407void
    341408BTimeSource::BroadcastTimeWarp(bigtime_t at_real_time,
    342                                bigtime_t new_performance_time)
     409    bigtime_t new_performance_time)
    343410{
    344411    CALLED();
    345412    ASSERT(fSlaveNodes != NULL);
    BTimeSource::BroadcastTimeWarp(bigtime_t at_real_time,  
    350417        ", new_performance_time %" B_PRId64 "\n", at_real_time,
    351418        new_performance_time);
    352419
    353     BAutolock lock(fSlaveNodes->locker);
     420    BAutolock lock(fSlaveNodes);
    354421
    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));
    363428    }
    364429}
    365430
    BTimeSource::SendRunMode(run_mode mode)  
    372437
    373438    // send the run mode change to all slaved nodes
    374439
    375     BAutolock lock(fSlaveNodes->locker);
     440    BAutolock lock(fSlaveNodes);
    376441
    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));
    384447    }
    385448}
    386449
    status_t BTimeSource::_Reserved_TimeSource_4(void *) { return B_ERROR; }  
    410473status_t BTimeSource::_Reserved_TimeSource_5(void *) { return B_ERROR; }
    411474
    412475/* explicit */
    413 BTimeSource::BTimeSource(media_node_id id) :
     476BTimeSource::BTimeSource(media_node_id id)
     477    :
    414478    BMediaNode("This one is never called"),
    415479    fStarted(false),
    416480    fArea(-1),
    BTimeSource::BTimeSource(media_node_id id) :  
    421485    CALLED();
    422486    AddNodeKind(B_TIME_SOURCE);
    423487    ASSERT(id > 0);
    424 //  printf("###### explicit BTimeSource::BTimeSource() id %ld, name %s\n", id, Name());
    425488
    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.
    428492    char name[32];
    429493    area_id area;
    430494    sprintf(name, "__timesource_buf_%" B_PRId32, id);
    BTimeSource::BTimeSource(media_node_id id) :  
    435499        return;
    436500    }
    437501    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
    439509    if (fArea <= 0) {
    440510        ERROR("BTimeSource::BTimeSource couldn't clone area, node %" B_PRId32
    441511            "\n", id);
    void  
    448518BTimeSource::FinishCreate()
    449519{
    450520    CALLED();
    451     //printf("BTimeSource::FinishCreate(), id %ld\n", ID());
    452521
    453522    char name[32];
    454523    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
    456531    if (fArea <= 0) {
    457532        ERROR("BTimeSource::BTimeSource couldn't create area, node %" B_PRId32
    458533            "\n", ID());
    BTimeSource::FinishCreate()  
    469544
    470545
    471546status_t
    472 BTimeSource::RemoveMe(BMediaNode *node)
     547BTimeSource::RemoveMe(BMediaNode* node)
    473548{
    474549    CALLED();
    475550    if (fKinds & NODE_KIND_SHADOW_TIMESOURCE) {
    476551        timesource_remove_slave_node_command cmd;
    477552        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));
    479555    } else {
    480556        DirectRemoveMe(node->Node());
    481557    }
    BTimeSource::RemoveMe(BMediaNode *node)  
    484560
    485561
    486562status_t
    487 BTimeSource::AddMe(BMediaNode *node)
     563BTimeSource::AddMe(BMediaNode* node)
    488564{
    489565    CALLED();
    490566    if (fKinds & NODE_KIND_SHADOW_TIMESOURCE) {
    BTimeSource::AddMe(BMediaNode *node)  
    499575
    500576
    501577void
    502 BTimeSource::DirectAddMe(const media_node &node)
     578BTimeSource::DirectAddMe(const media_node& node)
    503579{
    504580    // XXX this code has race conditions and is pretty dumb, and it
    505581    // XXX won't detect nodes that crash and don't remove themself.
    506582
    507583    CALLED();
    508584    ASSERT(fSlaveNodes != NULL);
    509     BAutolock lock(fSlaveNodes->locker);
     585    BAutolock lock(fSlaveNodes);
    510586
    511     if (fSlaveNodes->count == SLAVE_NODES_COUNT) {
     587    if (fSlaveNodes->CountSlaves() == MAX_SLAVE_NODES) {
    512588        ERROR("BTimeSource::DirectAddMe out of slave node slots\n");
    513589        return;
    514590    }
    BTimeSource::DirectAddMe(const media_node &node)  
    516592        ERROR("BTimeSource::DirectAddMe should not add itself to slave nodes\n");
    517593        return;
    518594    }
    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));
    534610    }
    535     ERROR("BTimeSource::DirectAddMe failed\n");
    536611}
    537612
    538613void
    539 BTimeSource::DirectRemoveMe(const media_node &node)
     614BTimeSource::DirectRemoveMe(const media_node& node)
    540615{
    541616    // XXX this code has race conditions and is pretty dumb, and it
    542617    // XXX won't detect nodes that crash and don't remove themself.
    543618
    544619    CALLED();
    545620    ASSERT(fSlaveNodes != NULL);
    546     BAutolock lock(fSlaveNodes->locker);
     621    BAutolock lock(fSlaveNodes);
    547622
    548     if (fSlaveNodes->count == 0) {
     623    if (fSlaveNodes->CountSlaves() == 0) {
    549624        ERROR("BTimeSource::DirectRemoveMe no slots used\n");
    550625        return;
    551626    }
    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));
    567642    }
    568     ERROR("BTimeSource::DirectRemoveMe failed\n");
    569643}
    570644
    571645void
    BTimeSource::DirectStart(bigtime_t at)  
    580654
    581655
    582656void
    583 BTimeSource::DirectStop(bigtime_t at,
    584                         bool immediate)
     657BTimeSource::DirectStop(bigtime_t at, bool immediate)
    585658{
    586659    CALLED();
    587660    if (fBuf)
    BTimeSource::DirectStop(bigtime_t at,  
    592665
    593666
    594667void
    595 BTimeSource::DirectSeek(bigtime_t to,
    596                         bigtime_t at)
     668BTimeSource::DirectSeek(bigtime_t to, bigtime_t at)
    597669{
    598670    UNIMPLEMENTED();
    599671}