Skip to content

Commit

Permalink
Implemented intercore message passing using MemoryChannel (libipc).
Browse files Browse the repository at this point in the history
  • Loading branch information
nieklinnenbank committed Sep 17, 2015
1 parent 01f25c9 commit d421cad
Show file tree
Hide file tree
Showing 19 changed files with 542 additions and 99 deletions.
2 changes: 2 additions & 0 deletions kernel/API/SystemInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Error SystemInfoHandler(SystemInformation *info)
info->bootImageAddress = core->bootImageAddress;
info->bootImageSize = core->bootImageSize;
info->timerCounter = core->timerCounter;
info->coreChannelAddress = core->coreChannelAddress;
info->coreChannelSize = core->coreChannelSize;

MemoryBlock::copy(info->cmdline, coreInfo.kernelCommand, 64);
return API::Success;
Expand Down
3 changes: 3 additions & 0 deletions kernel/API/SystemInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ typedef struct SystemInformation
/** BootImage size */
Size bootImageSize;

Address coreChannelAddress;
Size coreChannelSize;

/** Timer counter */
uint timerCounter;
}
Expand Down
4 changes: 4 additions & 0 deletions kernel/Kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ Kernel::Kernel(CoreInfo *info)
for (Size i = 0; i < m_coreInfo->bootImageSize; i += PAGESIZE)
m_alloc->allocate(m_coreInfo->bootImageAddress + i);

// Reserve CoreChannel memory
for (Size i = 0; i < m_coreInfo->coreChannelSize; i += PAGESIZE)
m_alloc->allocate(m_coreInfo->coreChannelAddress + i);

// Clear interrupts table
m_interrupts.fill(ZERO);
}
Expand Down
15 changes: 13 additions & 2 deletions lib/libarch/CoreInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

// TODO: needed by IntelBoot16.S.
// TODO: warning depends on sizeof(Memory::Access) which is an emum
#define COREINFO_SIZE (KERNEL_PATHLEN + (7 * 4) + (4 * 4) + (4 * 4))
#define COREINFO_SIZE (KERNEL_PATHLEN + (8 * 4) + (4 * 4) + (4 * 4))

#ifndef __ASSEMBLER__

Expand All @@ -47,10 +47,21 @@ typedef struct CoreInfo

Address bootImageAddress;
Address bootImageSize;
Address coreChannelBase;
Address coreChannelAddress;
Size coreChannelSize;

/** Arch-specific timer counter */
uint timerCounter;

// TODO: fix this in libstd. we should not need to do this for Index.
bool operator == (const struct CoreInfo & info) const
{
return false;
}
bool operator != (const struct CoreInfo & info) const
{
return true;
}
}
CoreInfo;

Expand Down
31 changes: 31 additions & 0 deletions lib/libarch/arm/ARMIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,37 @@ class ARMIO : public IO
return data;
}

/**
* Read a number of 32-bit values.
*
* @param addr Address of the starting 32-bit value.
* @param count Number of bytes to read.
* @param buf Output buffer.
*/
inline void read(Address addr, Size count, void *buf)
{
for (Size i = 0; i < count; i+= sizeof(u32))
{
*(u32 *)(((u8 *)buf) + i) = read(addr + i);
}
}

/**
* Write a number of 32-bit values.
*
* @param addr Address of the starting 32-bit value.
* @param count Number of bytes to write.
* @param buf Input buffer.
*/
inline void write(Address addr, Size count, void *buf)
{
for (Size i = 0; i < count; i+= sizeof(u32))
{
write(addr + i, *(u32 *) (((u8 *)buf) + i));
}
}


/**
* Set bits in memory mapped register.
*
Expand Down
30 changes: 30 additions & 0 deletions lib/libarch/intel/IntelIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,21 @@ class IntelIO : public IO
return *(volatile u32 *) addr;
}

/**
* Read a number of 32-bit values.
*
* @param addr Address of the starting 32-bit value.
* @param count Number of bytes to read.
* @param buf Output buffer.
*/
inline void read(Address addr, Size count, void *buf)
{
for (Size i = 0; i < count; i+= sizeof(u32))
{
*(u32 *)(((u8 *)buf) + i) = read(addr + i);
}
}

/**
* Write memory mapped register.
*
Expand All @@ -111,6 +126,21 @@ class IntelIO : public IO
*(volatile u32 *) addr = data;
}

/**
* Write a number of 32-bit values.
*
* @param addr Address of the starting 32-bit value.
* @param count Number of bytes to write.
* @param buf Input buffer.
*/
inline void write(Address addr, Size count, void *buf)
{
for (Size i = 0; i < count; i+= sizeof(u32))
{
write(addr + i, *(u32 *) (((u8 *)buf) + i));
}
}

/**
* Set bits in memory mapped register.
*
Expand Down
42 changes: 42 additions & 0 deletions lib/libipc/Channel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2015 Niek Linnenbank
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "Channel.h"

Channel::Channel()
{
m_mode = Consumer;
m_messageSize = 0;
m_maximumMessages = 0;
}

Size Channel::getMaximumMessages()
{
return m_maximumMessages;
}

Channel::Result Channel::setMode(Channel::Mode mode)
{
m_mode = mode;
return Success;
}

Channel::Result Channel::setMessageSize(Size size)
{
m_messageSize = size;
return Success;
}
79 changes: 78 additions & 1 deletion lib/libipc/Channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,89 @@
#ifndef __LIBIPC_CHANNEL_H
#define __LIBIPC_CHANNEL_H

/**
* Unidirectional point-to-point messaging channel.
*/
class Channel
{
public:

private:
/**
* Result codes.
*/
enum Result
{
Success,
InvalidArgument,
InvalidMode,
InvalidSize,
IOError,
ChannelFull
};

/**
* Channel modes.
*/
enum Mode
{
Producer,
Consumer
};

/**
* Constructor.
*/
Channel();

/**
* Get maximum message count.
*
* @return Maximum message count.
*/
Size getMaximumMessages();

/**
* Set mode.
*
* @param mode Channel mode.
* @return Result code.
*/
Result setMode(Mode mode);

/**
* Set message size.
*
* @param size New message size.
* @return Result code.
*/
Result setMessageSize(Size size);

/**
* Read a message.
*
* @param buffer Output buffer for the message.
* @return Result code.
*/
virtual Result read(void *buffer) = 0;

/**
* Write a message.
*
* @param buffer Input buffer for the message.
* @return Result code.
*/
virtual Result write(void *buffer) = 0;

protected:

/** Channel mode. */
Mode m_mode;

/** Message size. */
Size m_messageSize;

/** Maximum number of message that the Channel can hold. */
Size m_maximumMessages;
};

#endif /* __LIBIPC_CHANNEL_H */
92 changes: 92 additions & 0 deletions lib/libipc/MemoryChannel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (C) 2015 Niek Linnenbank
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <FreeNOS/System.h>
#include "MemoryChannel.h"

MemoryChannel::MemoryChannel()
: Channel()
{
MemoryBlock::set(&m_head, 0, sizeof(m_head));
}

MemoryChannel::Result MemoryChannel::setData(Address addr)
{
if (m_messageSize < sizeof(RingHead) || m_messageSize > (PAGESIZE / 2))
return InvalidArgument;

if (m_data.map(addr, PAGESIZE) != IO::Success)
return IOError;

m_maximumMessages = (PAGESIZE / m_messageSize) - 1;

if (m_mode == Producer)
m_data.write(0, sizeof(m_head), &m_head);
return Success;
}

MemoryChannel::Result MemoryChannel::setFeedback(Address addr)
{
if (m_feedback.map(addr, PAGESIZE) != IO::Success)
return IOError;

if (m_mode == Consumer)
m_feedback.write(0, sizeof(m_head), &m_head);
return Success;
}

MemoryChannel::Result MemoryChannel::read(void *buffer)
{
RingHead head;

// busy wait until a message comes in
while (true)
{
m_data.read(0, sizeof(head), &head);

if (head.index != m_head.index)
break;
}
// Read one message
m_data.read((m_head.index+1) * m_messageSize, m_messageSize, buffer);

// Increment head index
m_head.index = (m_head.index + 1) % m_maximumMessages;

// Update read index
m_feedback.write(0, sizeof(m_head), &m_head);
return Success;
}

MemoryChannel::Result MemoryChannel::write(void *buffer)
{
RingHead reader;

// Check for buffer space
m_feedback.read(0, sizeof(RingHead), &reader);

if (((m_head.index + 1) % m_maximumMessages) == reader.index)
return ChannelFull;

// write the message
m_data.write((m_head.index+1) * m_messageSize, m_messageSize, buffer);

// Increment write index
m_head.index = (m_head.index + 1) % m_maximumMessages;
m_data.write(0, sizeof(m_head), &m_head);
return Success;
}
Loading

0 comments on commit d421cad

Please sign in to comment.