FreeNOS
ChannelServer.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef __LIBIPC_CHANNELSERVER_H
19 #define __LIBIPC_CHANNELSERVER_H
20 
21 #include <FreeNOS/User.h>
22 #include <FreeNOS/ProcessManager.h>
23 #include <FreeNOS/ProcessEvent.h>
24 #include <FreeNOS/ProcessShares.h>
25 #include <HashIterator.h>
26 #include <Timer.h>
27 #include <Vector.h>
28 #include "MemoryChannel.h"
29 #include "ChannelClient.h"
30 #include "ChannelRegistry.h"
31 
43 template <class Func> struct MessageHandler
44 {
51  MessageHandler(const Func func, const bool reply)
52  : exec(func)
53  , sendReply(reply)
54  {
55  }
56 
57  const bool operator == (const struct MessageHandler<Func> & h) const
58  {
59  return false;
60  }
61 
62  const bool operator != (const struct MessageHandler<Func> & h) const
63  {
64  return false;
65  }
66 
68  const Func exec;
69 
71  const bool sendReply;
72 };
73 
79 template <class Base, class MsgType> class ChannelServer
80 {
81  private:
82 
84  static const Size MaximumHandlerCount = 255u;
85 
86  protected:
87 
89  typedef void (Base::*IPCHandlerFunction)(MsgType *);
90 
92  typedef void (Base::*IRQHandlerFunction)(Size);
93 
94  public:
95 
99  enum Result
100  {
105  };
106 
107  public:
108 
113  : m_instance(inst)
114  , m_client(ChannelClient::instance())
115  , m_registry(m_client->getRegistry())
116  , m_kernelEvent(Channel::Consumer, sizeof(ProcessEvent))
117  , m_ipcHandlers()
118  , m_irqHandlers()
119  {
120  m_self = ProcessCtl(SELF, GetPID, 0);
121 
122  // Reset timeout values
123  m_expiry.frequency = 0;
124  m_expiry.ticks = 0;
125 
126  // Setup kernel event channel
127  const SystemInformation info;
129  share.pid = KERNEL_PID;
130  share.coreId = info.coreId;
131  share.tagId = 0;
132 
133  if (VMShare(SELF, API::Read, &share) != API::Success)
134  {
135  FATAL("failed to get kernel event channel");
136  }
137  else
138  {
140  share.range.virt + PAGESIZE, false);
141  }
142 
143  // Try to recover channels after a restart
144  recoverChannels();
145  }
146 
150  virtual ~ChannelServer()
151  {
154  }
155 
161  int run()
162  {
163  // Enter loop
164  while (true)
165  {
166  processAll();
168  }
169 
170  // Satify compiler
171  return 0;
172  }
173 
179  void setTimeout(const uint msec)
180  {
181  DEBUG("msec = " << msec);
182 
184  {
185  ERROR("failed to retrieve system timer info");
186  return;
187  }
188 
189  const Size msecPerTick = 1000 / m_time.frequency;
191  m_expiry.ticks = m_time.ticks + ((msec / msecPerTick) + 1);
192  }
193 
194  protected:
195 
203  void addIPCHandler(const Size slot, IPCHandlerFunction h, const bool sendReply = true)
204  {
206  }
207 
215  {
217  }
218 
222  virtual void timeout()
223  {
224  DEBUG("");
225 
227  }
228 
234  virtual bool retryRequests()
235  {
236  return false;
237  }
238 
244  virtual void onProcessTerminated(const ProcessID pid)
245  {
246  }
247 
252  {
253  while (m_instance->retryRequests())
254  ;
255  }
256 
257  private:
258 
262  inline void processAll()
263  {
264  // Process kernel events
266 
267  // Process user messages
268  readChannels();
269 
270  // Retry requests until all served (EAGAIN or return value)
272  }
273 
277  inline void sleepUntilWakeup()
278  {
279  // Sleep with timeout or return in case the process is
280  // woken up by an external (wakeup) interrupt.
281  DEBUG("EnterSleep");
282  Address expiry = 0;
283 
284  if (m_expiry.frequency)
285  expiry = (Address) &m_expiry;
286 
287  const Error r = ProcessCtl(SELF, EnterSleep, expiry, (Address) (m_expiry.frequency ? &m_time : 0));
288  DEBUG("EnterSleep returned: " << (int)r);
289 
290  // Check for sleep timeout
291  if (m_expiry.frequency)
292  {
294  {
295  ERROR("failed to retrieve system timer");
296  }
297  else if (m_expiry.ticks < m_time.ticks)
298  {
299  m_expiry.frequency = 0;
300  timeout();
301  }
302  }
303  }
304 
315  const Memory::Range range,
316  const bool hardReset = true)
317  {
318  Address prodAddr, consAddr;
319 
320  // ProcessID's determine where the producer/consumer is placed
321  if (m_self < pid)
322  {
323  prodAddr = range.virt;
324  consAddr = range.virt + (PAGESIZE * 2);
325  }
326  else
327  {
328  prodAddr = range.virt + (PAGESIZE * 2);
329  consAddr = range.virt;
330  }
331 
332  // Create consumer
333  if (!m_registry.getConsumer(pid))
334  {
335  MemoryChannel *consumer = new MemoryChannel(Channel::Consumer, sizeof(MsgType));
336  assert(consumer != NULL);
337  consumer->setVirtual(consAddr, consAddr + PAGESIZE, hardReset);
338  m_registry.registerConsumer(pid, consumer);
339  }
340 
341  // Create producer
342  if (!m_registry.getProducer(pid))
343  {
344  MemoryChannel *producer = new MemoryChannel(Channel::Producer, sizeof(MsgType));
345  assert(producer != NULL);
346  producer->setVirtual(prodAddr,
347  prodAddr + PAGESIZE,
348  hardReset);
349  m_registry.registerProducer(pid, producer);
350  }
351 
352  // Done
353  return Success;
354  }
355 
360  {
361  const SystemInformation info;
362 
363  for (ProcessID i = 0; i < MAX_PROCS; i++)
364  {
365  if (i != m_self && i != KERNEL_PID)
366  {
368  share.pid = i;
369  share.coreId = info.coreId;
370  share.tagId = 0;
371 
372  const API::Result result = VMShare(SELF, API::Read, &share);
373  if (result == API::Success)
374  {
375  const Result r = accept(i, share.range, false);
376  if (r != Success)
377  {
378  ERROR("failed to recover share for PID " << i << ": " << (int)r);
379  }
380  }
381  }
382  }
383  }
384 
391  {
392  ProcessEvent event;
394 
395  // Try to read a message on the kernel event channel
396  while (m_kernelEvent.read(&event) == Channel::Success)
397  {
398  DEBUG(m_self << ": got kernel event: " << (int) event.type);
399 
400  switch (event.type)
401  {
402  case ShareCreated:
403  {
404  DEBUG(m_self << ": share created for PID: " << event.share.pid);
405  accept(event.share.pid, event.share.range);
406  break;
407  }
408  case InterruptEvent:
409  {
410  DEBUG(m_self << ": interrupt: " << event.number);
411 
413  if (h)
414  {
415  (m_instance->*h->exec) (event.number);
416  }
417  else
418  {
419  ERROR(m_self << ": unhandled IRQ raised: " << event.number);
420  }
421  break;
422  }
423  case ProcessTerminated:
424  {
425  DEBUG(m_self << ": process terminated: PID " << event.number);
426  result = m_registry.unregisterConsumer(event.number);
427  if (result != ChannelRegistry::Success)
428  {
429  ERROR("failed to unregister consumer for PID " <<
430  event.number << ": " << (int)result);
431  }
432 
433  result = m_registry.unregisterProducer(event.number);
434  if (result != ChannelRegistry::Success)
435  {
436  ERROR("failed to unregister producer for PID " <<
437  event.number << ": " << (int)result);
438  }
439 
440  // cleanup the VMShare area now for that process
441  const API::Result shareResult = VMShare(event.number, API::Delete, ZERO);
442  if (shareResult != API::Success)
443  {
444  ERROR("failed to remove shares with VMShare for PID " <<
445  event.number << ": " << (int)shareResult);
446  }
447 
449  break;
450  }
451  default:
452  WARNING(m_self << ": unknown event.type: " << event.type);
453  break;
454  }
455  }
456  return Success;
457  }
458 
465  {
466  MsgType msg;
467 
468  // Try to receive message on each consumer channel
470  {
471  Channel *ch = i.current();
472  DEBUG(m_self << ": trying to receive from PID " << i.key());
473 
474  // Read all messages in the consumer channel
475  while (ch->read(&msg) == Channel::Success)
476  {
477  DEBUG(m_self << ": received message");
478  msg.from = i.key();
479 
480  // Is the message a response from earlier client request?
481  if (msg.type == ChannelMessage::Response)
482  {
483  if (m_client->processResponse(msg.from, &msg) != ChannelClient::Success)
484  {
485  ERROR(m_self << ": failed to process client response from PID " <<
486  msg.from << " with identifier " << msg.identifier);
487  }
488  }
489  // Message is a request to us
490  else
491  {
493  if (h)
494  {
495  (m_instance->*h->exec) (&msg);
496 
497  // Send reply
498  if (h->sendReply)
499  {
500  Channel *ch = m_registry.getProducer(i.key());
501  if (!ch)
502  {
503  ERROR(m_self << ": no producer channel found for PID: " << i.key());
504  }
505  else if (ch->write(&msg) != Channel::Success)
506  {
507  ERROR(m_self << ": failed to send reply message to PID: " << i.key());
508  }
509  else
510  ProcessCtl(i.key(), Wakeup, 0);
511  }
512  }
513  else
514  {
515  ERROR(m_self << ": invalid action " << (int)msg.action << " from PID " << i.key());
516  }
517  }
518  }
519  }
520  return Success;
521  }
522 
523  protected:
524 
527 
530 
533 
536 
539 
542 
545 
548 
551 };
552 
558 #endif /* __LIBIPC_CHANNELSERVER_H */
ChannelServer::m_ipcHandlers
Index< MessageHandler< IPCHandlerFunction >, MaximumHandlerCount > m_ipcHandlers
IPC handler functions.
Definition: ChannelServer.h:538
Channel
Unidirectional point-to-point messaging channel.
Definition: Channel.h:34
ChannelServer::readKernelEvents
Result readKernelEvents()
Read and process kernel events.
Definition: ChannelServer.h:390
ProcessShares::MemoryShare::tagId
Size tagId
Share tag id is defined by the application.
Definition: ProcessShares.h:57
Index::insertAt
virtual bool insertAt(const Size position, T *item)
Inserts the given item at the given position.
Definition: Index.h:113
Channel::Success
@ Success
Definition: Channel.h:43
Memory::Range
Memory range.
Definition: Memory.h:55
ChannelRegistry.h
ChannelClient.h
ProcessShares::MemoryShare
Definition: ProcessShares.h:48
API::Result
Result
Enumeration of generic kernel API result codes.
Definition: API.h:68
Vector.h
ProcessShares::MemoryShare::pid
ProcessID pid
Remote process id for this share.
Definition: ProcessShares.h:51
MemoryChannel::setVirtual
Result setVirtual(const Address data, const Address feedback, const bool hardReset=true)
Set memory pages by virtual address.
Definition: MemoryChannel.cpp:54
ChannelServer::Success
@ Success
Definition: ChannelServer.h:101
WARNING
#define WARNING(msg)
Output a warning message.
Definition: Log.h:68
ChannelServer::accept
Result accept(const ProcessID pid, const Memory::Range range, const bool hardReset=true)
Accept new channel connection.
Definition: ChannelServer.h:314
ChannelServer::~ChannelServer
virtual ~ChannelServer()
Destructor function.
Definition: ChannelServer.h:150
ChannelServer::recoverChannels
void recoverChannels()
Read existing shares to recover MemoryChannels after restart.
Definition: ChannelServer.h:359
ChannelServer::ChannelServer
ChannelServer(Base *inst)
Constructor function.
Definition: ChannelServer.h:112
HashIterator
Iterate through a HashTable.
Definition: HashIterator.h:39
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
ChannelServer::sleepUntilWakeup
void sleepUntilWakeup()
Let this process sleep until more events are raised.
Definition: ChannelServer.h:277
ChannelServer::m_registry
ChannelRegistry & m_registry
Contains registered channels.
Definition: ChannelServer.h:532
HashIterator.h
Index
Index is a N-sized array of pointers to items of type T.
Definition: Index.h:36
ChannelServer::addIRQHandler
void addIRQHandler(const Size slot, IRQHandlerFunction h)
Register a new IRQ message vector handler.
Definition: ChannelServer.h:214
MessageHandler
Message handler function (dummy) container.
Definition: ChannelServer.h:43
ProcessID
u32 ProcessID
Process Identification Number.
Definition: Types.h:140
ChannelServer::IRQHandlerFunction
void(Base::* IRQHandlerFunction)(Size)
Member function pointer inside Base, to handle interrupts.
Definition: ChannelServer.h:92
Timer::Info::frequency
Size frequency
Definition: Timer.h:45
Wakeup
@ Wakeup
Definition: ProcessCtl.h:53
ChannelClient::Success
@ Success
Definition: ChannelClient.h:83
Address
unsigned long Address
A memory address.
Definition: Types.h:131
Number::Base
Base
Numeral system base type.
Definition: Types.h:168
ChannelServer::run
int run()
Enters an infinite loop, serving incoming requests.
Definition: ChannelServer.h:161
VMShare
API::Result VMShare(const ProcessID pid, const API::Operation op, ProcessShares::MemoryShare *share)
Prototype for user applications.
Definition: VMShare.h:41
ChannelServer::retryRequests
virtual bool retryRequests()
Retry any pending requests.
Definition: ChannelServer.h:234
ProcessShares::MemoryShare::range
Memory::Range range
Physical memory address range.
Definition: ProcessShares.h:60
MessageHandler::MessageHandler
MessageHandler(const Func func, const bool reply)
Constructor function.
Definition: ChannelServer.h:51
KERNEL_PID
#define KERNEL_PID
Definition: ProcessID.h:36
SystemInformation::coreId
uint coreId
Core Identifier.
Definition: SystemInfo.h:105
ProcessCtl
API::Result ProcessCtl(const ProcessID proc, const ProcessOperation op, const Address addr=0, const Address output=0)
Prototype for user applications.
Definition: ProcessCtl.h:93
Timer::Info
Timer information structure.
Definition: Timer.h:42
MessageHandler::sendReply
const bool sendReply
Whether to send a reply or not.
Definition: ChannelServer.h:71
ChannelServer::IPCHandlerFunction
void(Base::* IPCHandlerFunction)(MsgType *)
Member function pointer inside Base, to handle IPC messages.
Definition: ChannelServer.h:89
ProcessShares::MemoryShare::coreId
Size coreId
CoreId for the other process.
Definition: ProcessShares.h:54
ChannelRegistry::getConsumer
Channel * getConsumer(const ProcessID pid)
Get one consumer.
Definition: ChannelRegistry.cpp:35
ChannelRegistry::Success
@ Success
Definition: ChannelRegistry.h:46
ChannelRegistry::registerConsumer
Result registerConsumer(const ProcessID pid, Channel *channel)
Register consumer channel.
Definition: ChannelRegistry.cpp:63
ProcessTerminated
@ ProcessTerminated
Definition: ProcessEvent.h:34
uint
unsigned int uint
Unsigned integer number.
Definition: Types.h:44
Index::deleteAll
void deleteAll()
Removes and delete()'s all items.
Definition: Index.h:166
Channel::read
virtual Result read(void *buffer)
Read a message.
Definition: Channel.cpp:35
API::Read
@ Read
Definition: API.h:98
ChannelServer::InvalidSize
@ InvalidSize
Definition: ChannelServer.h:103
MessageHandler::exec
const Func exec
Handler function.
Definition: ChannelServer.h:68
SELF
#define SELF
Definition: ProcessID.h:35
ChannelServer::m_self
ProcessID m_self
ProcessID of ourselves.
Definition: ChannelServer.h:544
InterruptEvent
@ InterruptEvent
Definition: ProcessEvent.h:32
InfoTimer
@ InfoTimer
Definition: ProcessCtl.h:49
ChannelServer::m_instance
Base * m_instance
Server object instance.
Definition: ChannelServer.h:526
FATAL
#define FATAL(msg)
Output a critical message and terminate program immediatly.
Definition: Log.h:50
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
ChannelServer::readChannels
Result readChannels()
Read each Channel for messages.
Definition: ChannelServer.h:464
Timer.h
Channel::write
virtual Result write(const void *buffer)
Write a message.
Definition: Channel.cpp:40
ProcessEvent
Represents a process which may run on the host.
Definition: ProcessEvent.h:40
ChannelServer< DatastoreServer, DatastoreMessage >::Result
Result
Result codes.
Definition: ChannelServer.h:99
ChannelServer::IOError
@ IOError
Definition: ChannelServer.h:104
GetPID
@ GetPID
Definition: ProcessCtl.h:41
ChannelRegistry::getConsumers
HashTable< ProcessID, Channel * > & getConsumers()
Get all consumers.
Definition: ChannelRegistry.cpp:53
MAX_PROCS
#define MAX_PROCS
Maximum number of processes.
Definition: ProcessManager.h:39
ChannelServer::timeout
virtual void timeout()
Called when sleep timeout is reached.
Definition: ChannelServer.h:222
Error
slong Error
Error code defined in Error.h.
Definition: Types.h:159
NULL
#define NULL
NULL means zero.
Definition: Macros.h:39
Channel::Consumer
@ Consumer
Definition: Channel.h:59
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
ChannelServer::setTimeout
void setTimeout(const uint msec)
Set a sleep timeout.
Definition: ChannelServer.h:179
MemoryChannel
Unidirectional point-to-point channel using shared memory.
Definition: MemoryChannel.h:43
EnterSleep
@ EnterSleep
Definition: ProcessCtl.h:51
ProcessEvent::number
Size number
Definition: ProcessEvent.h:43
ChannelRegistry::registerProducer
Result registerProducer(const ProcessID pid, Channel *channel)
Register producer channel.
Definition: ChannelRegistry.cpp:71
ChannelRegistry::unregisterProducer
Result unregisterProducer(const ProcessID pid)
Unregister producer channel.
Definition: ChannelRegistry.cpp:91
ChannelServer::m_kernelEvent
MemoryChannel m_kernelEvent
Kernel event channel.
Definition: ChannelServer.h:535
Index::get
virtual T * get(const Size position) const
Returns the item at the given position.
Definition: Index.h:187
Channel::Producer
@ Producer
Definition: Channel.h:58
MemoryChannel::read
virtual Result read(void *buffer)
Read a message.
Definition: MemoryChannel.cpp:116
Timer::Info::ticks
u32 ticks
Definition: Timer.h:44
ProcessEvent::share
ProcessShares::MemoryShare share
Definition: ProcessEvent.h:44
ChannelServer::retryAllRequests
void retryAllRequests()
Keep retrying requests until all served.
Definition: ChannelServer.h:251
ChannelServer
Template class which serves incoming messages from Channels using MessageHandlers.
Definition: ChannelServer.h:79
ShareCreated
@ ShareCreated
Definition: ProcessEvent.h:33
ChannelClient
Client for using Channels on the local processor.
Definition: ChannelClient.h:44
API::Delete
@ Delete
Definition: API.h:94
assert
#define assert(exp)
Insert program diagnostics.
Definition: assert.h:60
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
SystemInformation
System information structure.
Definition: SystemInfo.h:79
MessageHandler::operator!=
const bool operator!=(const struct MessageHandler< Func > &h) const
Definition: ChannelServer.h:62
ChannelServer::m_expiry
Timer::Info m_expiry
System timer expiration value.
Definition: ChannelServer.h:550
ChannelServer::m_client
ChannelClient * m_client
Client for sending replies.
Definition: ChannelServer.h:529
API::Success
@ Success
Definition: API.h:70
ChannelRegistry
Registration for Channels.
Definition: ChannelRegistry.h:37
ChannelServer::m_time
Timer::Info m_time
System timer value.
Definition: ChannelServer.h:547
MessageHandler::operator==
const bool operator==(const struct MessageHandler< Func > &h) const
Definition: ChannelServer.h:57
ChannelServer::addIPCHandler
void addIPCHandler(const Size slot, IPCHandlerFunction h, const bool sendReply=true)
Register a new IPC message action handler.
Definition: ChannelServer.h:203
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
ChannelServer::MaximumHandlerCount
static const Size MaximumHandlerCount
Maximum number of IPC/IRQ handlers.
Definition: ChannelServer.h:84
MemoryChannel.h
HashIterator::hasCurrent
virtual bool hasCurrent() const
Check if there is a current item.
Definition: HashIterator.h:83
ChannelServer::processAll
void processAll()
Process all current events and channels.
Definition: ChannelServer.h:262
ChannelMessage::Response
@ Response
Definition: ChannelMessage.h:44
ChannelRegistry::getProducer
Channel * getProducer(const ProcessID pid)
Get one producer.
Definition: ChannelRegistry.cpp:44
ProcessEvent::type
ProcessEventType type
Definition: ProcessEvent.h:42
ChannelRegistry::unregisterConsumer
Result unregisterConsumer(const ProcessID pid)
Unregister consumer channel.
Definition: ChannelRegistry.cpp:79
ChannelServer::onProcessTerminated
virtual void onProcessTerminated(const ProcessID pid)
Called whenever another Process is terminated.
Definition: ChannelServer.h:244
ChannelServer::m_irqHandlers
Index< MessageHandler< IRQHandlerFunction >, MaximumHandlerCount > m_irqHandlers
IRQ handler functions.
Definition: ChannelServer.h:541
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
ChannelClient::processResponse
virtual Result processResponse(const ProcessID pid, ChannelMessage *msg)
Process a response message.
Definition: ChannelClient.cpp:220
ChannelRegistry::Result
Result
Result codes.
Definition: ChannelRegistry.h:44
ChannelServer::InvalidArgument
@ InvalidArgument
Definition: ChannelServer.h:102