OpenCores
URL https://opencores.org/ocsvn/w11/w11/trunk

Subversion Repositories w11

[/] [w11/] [tags/] [w11a_V0.61/] [tools/] [src/] [librlink/] [RlinkServer.cpp] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 21 wfjm
// $Id: RlinkServer.cpp 513 2013-05-01 14:02:06Z mueller $
2 19 wfjm
//
3
// Copyright 2013- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
4
//
5
// This program is free software; you may redistribute and/or modify it under
6
// the terms of the GNU General Public License as published by the Free
7
// Software Foundation, either version 2, or at your option any later version.
8
//
9
// This program is distributed in the hope that it will be useful, but
10
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
11
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
// for complete details.
13
// 
14
// Revision History: 
15
// Date         Rev Version  Comment
16 21 wfjm
// 2013-05-01   513   1.0.2  fTraceLevel now uint32_t
17 20 wfjm
// 2013-04-21   509   1.0.1  add Resume(), reorganize server start handling
18 19 wfjm
// 2013-03-06   495   1.0    Initial version
19
// 2013-01-12   474   0.5    First draft
20
// ---------------------------------------------------------------------------
21
 
22
/*!
23
  \file
24 21 wfjm
  \version $Id: RlinkServer.cpp 513 2013-05-01 14:02:06Z mueller $
25 19 wfjm
  \brief   Implemenation of RlinkServer.
26
*/
27
 
28
#include "boost/thread/locks.hpp"
29
#include "boost/bind.hpp"
30
 
31
#include "librtools/Rexception.hpp"
32
#include "librtools/RosFill.hpp"
33
#include "librtools/RosPrintf.hpp"
34
#include "librtools/RosPrintBvi.hpp"
35
#include "librtools/Rexception.hpp"
36
#include "librtools/RlogMsg.hpp"
37
 
38
#include "RlinkServer.hpp"
39
 
40
using namespace std;
41
 
42
/*!
43
  \class Retro::RlinkServer
44
  \brief FIXME_docs
45
*/
46
 
47
// all method definitions in namespace Retro
48
namespace Retro {
49
 
50
//------------------------------------------+-----------------------------------
51
//! Default constructor
52
 
53
RlinkServer::RlinkServer()
54
  : fspConn(),
55
    fContext(),
56
    fAttnDsc(),
57
    fActnList(),
58
    fWakeupEvent(),
59
    fELoop(this),
60
    fServerThread(),
61
    fAttnSeen(false),
62
    fAttnPatt(0),
63
    fTraceLevel(0),
64
    fStats()
65
{
66
  fContext.SetStatus(0,
67
             ~(RlinkCommand::kStat_M_RbNak|RlinkCommand::kStat_M_RbErr));
68
 
69
  fELoop.AddPollHandler(boost::bind(&RlinkServer::WakeupHandler, this, _1),
70
                        fWakeupEvent, POLLIN);
71
 
72
  // Statistic setup
73
  fStats.Define(kStatNEloopWait,"NEloopWait","event loop turns (wait)");
74
  fStats.Define(kStatNEloopPoll,"NEloopPoll","event loop turns (poll)");
75
  fStats.Define(kStatNWakeupEvt,"NWakeupEvt","Wakeup events");
76
  fStats.Define(kStatNRlinkEvt, "NRlinkEvt", "Rlink data events");
77
  fStats.Define(kStatNAttnRead, "NAttnRead", "Attn read commands");
78
  fStats.Define(kStatNAttn00,   "NAttn00",   "Attn bit  0 set");
79
  fStats.Define(kStatNAttn01,   "NAttn01",   "Attn bit  1 set");
80
  fStats.Define(kStatNAttn02,   "NAttn02",   "Attn bit  2 set");
81
  fStats.Define(kStatNAttn03,   "NAttn03",   "Attn bit  3 set");
82
  fStats.Define(kStatNAttn04,   "NAttn04",   "Attn bit  4 set");
83
  fStats.Define(kStatNAttn05,   "NAttn05",   "Attn bit  5 set");
84
  fStats.Define(kStatNAttn06,   "NAttn06",   "Attn bit  6 set");
85
  fStats.Define(kStatNAttn07,   "NAttn07",   "Attn bit  7 set");
86
  fStats.Define(kStatNAttn08,   "NAttn08",   "Attn bit  8 set");
87
  fStats.Define(kStatNAttn09,   "NAttn09",   "Attn bit  9 set");
88
  fStats.Define(kStatNAttn10,   "NAttn10",   "Attn bit 10 set");
89
  fStats.Define(kStatNAttn11,   "NAttn11",   "Attn bit 11 set");
90
  fStats.Define(kStatNAttn12,   "NAttn12",   "Attn bit 12 set");
91
  fStats.Define(kStatNAttn13,   "NAttn13",   "Attn bit 13 set");
92
  fStats.Define(kStatNAttn14,   "NAttn14",   "Attn bit 14 set");
93
  fStats.Define(kStatNAttn15,   "NAttn15",   "Attn bit 15 set");
94
}
95
 
96
//------------------------------------------+-----------------------------------
97
//! Destructor
98
 
99
RlinkServer::~RlinkServer()
100
{
101
  Stop();
102
  if (fspConn) fspConn->SetServer(0);
103
}
104
 
105
//------------------------------------------+-----------------------------------
106
//! FIXME_docs
107
 
108
void RlinkServer::SetConnect(const boost::shared_ptr<RlinkConnect>& spconn)
109
{
110
  if (!fspConn && !spconn) return;          // allow 0 = 0 ...
111
  if (fspConn)
112
    throw Rexception("RlinkServer::SetConnect()",
113
                     "Bad state: fspConn already set");
114
  if (!spconn)
115
    throw Rexception("RlinkServer::SetConnect()", "Bad args: spconn==0");
116
 
117
  fspConn = spconn;
118
  fELoop.SetLogFile(fspConn->LogFileSPtr());
119
  fspConn->SetServer(this);
120
  return;
121
}
122
 
123
//------------------------------------------+-----------------------------------
124
//! FIXME_docs
125
 
126
void RlinkServer::AddAttnHandler(const attnhdl_t& attnhdl, uint16_t mask,
127
                                 void* cdata)
128
{
129
  if (mask == 0)
130
    throw Rexception("RlinkServer::AddAttnHandler()", "Bad args: mask == 0");
131
 
132
  boost::lock_guard<RlinkConnect> lock(*fspConn);
133
 
134
  AttnId id(mask, cdata);
135
  for (size_t i=0; i<fAttnDsc.size(); i++) {
136
    if (fAttnDsc[i].fId == id) {
137
      throw Rexception("RlinkServer::AddAttnHandler()",
138
                       "Bad args: duplicate handler");
139
    }
140
  }
141
  fAttnDsc.push_back(AttnDsc(attnhdl, id));
142
 
143
  return;
144
}
145
 
146
//------------------------------------------+-----------------------------------
147
//! FIXME_docs
148
 
149
void RlinkServer::RemoveAttnHandler(uint16_t mask, void* cdata)
150
{
151
  boost::lock_guard<RlinkConnect> lock(*fspConn);
152
 
153
  AttnId id(mask, cdata);
154
  for (size_t i=0; i<fAttnDsc.size(); i++) {
155
    if (fAttnDsc[i].fId == id) {
156
      fAttnDsc.erase(fAttnDsc.begin()+i);
157
      return;
158
    }
159
  }
160
 
161
  throw Rexception("RlinkServer::RemoveAttnHandler()",
162
                   "Bad args: unknown handler");
163
}
164
 
165
//------------------------------------------+-----------------------------------
166
//! FIXME_docs
167
 
168
void RlinkServer::QueueAction(const actnhdl_t& actnhdl)
169
{
170
  boost::lock_guard<RlinkConnect> lock(*fspConn);
171
  fActnList.push_back(actnhdl);
172
  if (IsActiveOutside()) Wakeup();
173
  return;
174
}
175
 
176
//------------------------------------------+-----------------------------------
177
//! FIXME_docs
178
 
179
void RlinkServer::AddPollHandler(const pollhdl_t& pollhdl,
180
                                        int fd, short events)
181
{
182
  boost::lock_guard<RlinkConnect> lock(*fspConn);
183
  fELoop.AddPollHandler(pollhdl, fd, events);
184
  if (IsActiveOutside()) Wakeup();
185
  return;
186
}
187
 
188
//------------------------------------------+-----------------------------------
189
//! FIXME_docs
190
 
191
bool RlinkServer::TestPollHandler(int fd, short events)
192
{
193
  boost::lock_guard<RlinkConnect> lock(*fspConn);
194
  return fELoop.TestPollHandler(fd, events);
195
}
196
 
197
//------------------------------------------+-----------------------------------
198
//! FIXME_docs
199
 
200
void RlinkServer::RemovePollHandler(int fd, short events, bool nothrow)
201
{
202
  boost::lock_guard<RlinkConnect> lock(*fspConn);
203
  fELoop.RemovePollHandler(fd, events,nothrow);
204
  if (IsActiveOutside()) Wakeup();
205
  return;
206
}
207
 
208
//------------------------------------------+-----------------------------------
209
//! FIXME_docs
210
 
211
void RlinkServer::RemovePollHandler(int fd)
212
{
213
  boost::lock_guard<RlinkConnect> lock(*fspConn);
214
  fELoop.RemovePollHandler(fd);
215
  if (IsActiveOutside()) Wakeup();
216
  return;
217
}
218
 
219
//------------------------------------------+-----------------------------------
220
//! FIXME_docs
221
 
222
void RlinkServer::Start()
223
{
224 20 wfjm
  StartOrResume(false);
225 19 wfjm
  return;
226
}
227
 
228
//------------------------------------------+-----------------------------------
229
//! FIXME_docs
230
 
231
void RlinkServer::Stop()
232
{
233
  fELoop.Stop();
234
  Wakeup();
235
  fServerThread.join();
236
  return;
237
}
238
 
239
//------------------------------------------+-----------------------------------
240
//! FIXME_docs
241
 
242 20 wfjm
void RlinkServer::Resume()
243
{
244
  StartOrResume(true);
245
  return;
246
}
247
 
248
//------------------------------------------+-----------------------------------
249
//! FIXME_docs
250
 
251 19 wfjm
void RlinkServer::Wakeup()
252
{
253
  uint64_t one(1);
254
  int irc = write(fWakeupEvent, &one, sizeof(one));
255
  if (irc < 0)
256
    throw Rexception("RlinkServer::Wakeup()",
257
                     "write() to eventfd failed: ", errno);
258
  return;
259
}
260
 
261
//------------------------------------------+-----------------------------------
262
//! FIXME_docs
263
 
264
void RlinkServer::SignalAttn()
265
{
266
  boost::lock_guard<RlinkConnect> lock(*fspConn);
267
  fAttnSeen = true;
268
  Wakeup();
269
  return;
270
}
271
 
272
//------------------------------------------+-----------------------------------
273
//! FIXME_docs
274
 
275
bool RlinkServer::IsActive() const
276
{
277
  return fServerThread.get_id() != boost::thread::id();
278
}
279
 
280
//------------------------------------------+-----------------------------------
281
//! FIXME_docs
282
 
283
bool RlinkServer::IsActiveInside() const
284
{
285
  return IsActive() && boost::this_thread::get_id() == fServerThread.get_id();
286
}
287
 
288
//------------------------------------------+-----------------------------------
289
//! FIXME_docs
290
 
291
bool RlinkServer::IsActiveOutside() const
292
{
293
  return IsActive() && boost::this_thread::get_id() != fServerThread.get_id();
294
}
295
 
296
//------------------------------------------+-----------------------------------
297
//! FIXME_docs
298
 
299 21 wfjm
void RlinkServer::SetTraceLevel(uint32_t level)
300 19 wfjm
{
301
  fTraceLevel = level;
302
  fELoop.SetTraceLevel(level);
303
  return;
304
}
305
 
306
//------------------------------------------+-----------------------------------
307
//! FIXME_docs
308
 
309
void RlinkServer::Print(std::ostream& os) const
310
{
311
  os << "RlinkServer::Print(std::ostream& os)" << endl;
312
  return;
313
}
314
 
315
//------------------------------------------+-----------------------------------
316
//! FIXME_docs
317
 
318
void RlinkServer::Dump(std::ostream& os, int ind, const char* text) const
319
{
320
  // FIXME_code: is that thread safe ??? fActnList.size() ???
321
  RosFill bl(ind);
322
  os << bl << (text?text:"--") << "RlinkServer @ " << this << endl;
323
  os << bl << "  fspConn:         " <<  fspConn << endl;
324
 
325
  os << bl << "  fAttnDsc:        " << endl;
326
  for (size_t i=0; i<fAttnDsc.size(); i++)
327
    os << bl << "    [" << RosPrintf(i,"d",3) << "]: "
328
       << RosPrintBvi(fAttnDsc[i].fId.fMask,16)
329
       << ", " << fAttnDsc[i].fId.fCdata << endl;
330
  os << bl << "  fActnList.size:  " << fActnList.size() << endl;
331
  fELoop.Dump(os, ind+2, "fELoop");
332
  os << bl << "  fServerThread:   " << fServerThread.get_id() << endl;
333
  os << bl << "  fAttnSeen:       " << fAttnSeen << endl;
334
  os << bl << "  fAttnPatt:       " << RosPrintBvi(fAttnPatt,16) << endl;
335
  fStats.Dump(os, ind+2, "fStats: ");
336
  return;
337
}
338
 
339
//------------------------------------------+-----------------------------------
340
//! FIXME_docs
341
 
342 20 wfjm
void RlinkServer::StartOrResume(bool resume)
343
{
344
  if (IsActive())
345
    throw Rexception("RlinkServer::StartOrResume()",
346
                     "Bad state: server thread already running");
347
  if (!fspConn->IsOpen())
348
    throw Rexception("RlinkServer::StartOrResume()",
349
                     "Bad state: RlinkConnect not open");
350
 
351
  boost::lock_guard<RlinkConnect> lock(Connect());
352
  // enable attn comma send
353
  RlinkCommandList clist;
354
  if (!resume) clist.AddAttn();
355
  clist.AddInit(RlinkCommand::kRbaddr_IInt, RlinkCommand::kIInt_M_AnEna);
356
  Exec(clist);
357
 
358
  // setup poll handler for Rlink traffic
359
  int rlinkfd = fspConn->Port()->FdRead();
360
  if (!fELoop.TestPollHandler(rlinkfd, POLLIN))
361
    fELoop.AddPollHandler(boost::bind(&RlinkServer::RlinkHandler, this, _1),
362
                          rlinkfd, POLLIN);
363
 
364
  // and start server thread
365
  fServerThread = boost::thread(boost::bind(&RlinkServerEventLoop::EventLoop,
366
                                            &fELoop));
367
 
368
  if (resume) {
369
    RerrMsg emsg;
370
    if (!Connect().SndAttn(emsg)) {
371
      RlogMsg lmsg(LogFile(), 'E');
372
      lmsg << "attn send for server resume failed:" << emsg;
373
    }
374
  }
375
 
376
  return;
377
}
378
 
379
//------------------------------------------+-----------------------------------
380
//! FIXME_docs
381
 
382 19 wfjm
void RlinkServer::CallAttnHandler()
383
{
384
  if (fAttnSeen) {
385
    boost::lock_guard<RlinkConnect> lock(*fspConn);
386
    RlinkCommandList clist;
387
    clist.AddAttn();
388
    fStats.Inc(kStatNAttnRead);
389
    Exec(clist);
390
    // FIXME_code: handle errors: bool ok = 
391
    uint16_t nattn = clist[0].Data();
392
    fAttnPatt |= nattn;
393
    for (size_t i=0; i<16; i++) {
394
      if (nattn & (uint16_t(1)<<i)) fStats.Inc(kStatNAttn00+i);
395
    }
396
    fAttnSeen = false;
397
  }
398
 
399
  // multiple handlers may be called for one attn bit
400
  uint16_t hdone = 0;
401
  for (size_t i=0; i<fAttnDsc.size(); i++) {
402
    uint16_t hmatch = fAttnPatt & fAttnDsc[i].fId.fMask;
403
    if (hmatch) {
404
      AttnArgs args(fAttnPatt, fAttnDsc[i].fId.fMask);
405
      // FIXME_code: return code not used, yet
406
      boost::lock_guard<RlinkConnect> lock(*fspConn);
407
      fAttnDsc[i].fHandler(args);
408
      hdone |= hmatch;
409
    }
410
  }
411
  fAttnPatt &= ~hdone;                      // clear handled bits
412
 
413
  if (fAttnPatt && fTraceLevel>0) {
414
    RlogMsg lmsg(LogFile(), 'I');
415
    lmsg << "eloop: unhandled attn, mask="
416
         << RosPrintBvi(fAttnPatt,16) << endl;
417
  }
418
 
419
  fAttnPatt = 0;
420
 
421
  return;
422
}
423
 
424
//------------------------------------------+-----------------------------------
425
//! FIXME_docs
426
 
427
void RlinkServer::CallActnHandler()
428
{
429
  if (!ActnPending()) return;
430
 
431
  // call first action
432
  boost::lock_guard<RlinkConnect> lock(*fspConn);
433
 
434
  int irc = fActnList.front()();
435
 
436 20 wfjm
  // if irc>0 requeue to end, otherwise drop
437
  if (irc > 0) {
438 19 wfjm
    fActnList.splice(fActnList.end(), fActnList, fActnList.begin());
439
  } else {
440
    fActnList.pop_front();
441
  }
442
 
443
  return;
444
}
445
 
446
//------------------------------------------+-----------------------------------
447
//! FIXME_docs
448
 
449
int RlinkServer::WakeupHandler(const pollfd& pfd)
450
{
451
  fStats.Inc(kStatNWakeupEvt);
452
 
453
  // bail-out and cancel handler if poll returns an error event
454
  if (pfd.revents & (~pfd.events)) return -1;
455
 
456
  uint64_t buf;
457
  int irc = read(fWakeupEvent, &buf, sizeof(buf));
458
  if (irc < 0)
459
    throw Rexception("RlinkServer::WakeupHandler()",
460
                     "read() from eventfd failed: ", errno);
461
  return 0;
462
}
463
 
464
//------------------------------------------+-----------------------------------
465
//! FIXME_docs
466
 
467
int RlinkServer::RlinkHandler(const pollfd& pfd)
468
{
469
  fStats.Inc(kStatNRlinkEvt);
470
 
471
  // bail-out and cancel handler if poll returns an error event
472
  if (pfd.revents & (~pfd.events)) return -1;
473
 
474
  boost::lock_guard<RlinkConnect> lock(*fspConn);
475
  RerrMsg emsg;
476
  int irc = fspConn->PollAttn(emsg);
477
  if (irc > 0) {
478
    fAttnSeen = true;
479
  }
480
 
481
  return 0;
482
}
483
 
484
} // end namespace Retro

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.