diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2010-06-24 15:51:29 -0500 |
---|---|---|
committer | Patrick Williams <iawillia@us.ibm.com> | 2010-06-24 15:51:29 -0500 |
commit | 8085c7634979f38c1b152d0a35b98c2447ce497a (patch) | |
tree | 844b3527d7b1e8770540f77d1f95c59254aaca60 /src | |
parent | f760d7d1b0a7872228870b84ebfa85ab9999eb54 (diff) | |
download | blackbird-hostboot-8085c7634979f38c1b152d0a35b98c2447ce497a.tar.gz blackbird-hostboot-8085c7634979f38c1b152d0a35b98c2447ce497a.zip |
Add messaging
Diffstat (limited to 'src')
-rw-r--r-- | src/include/kernel/msg.H | 28 | ||||
-rw-r--r-- | src/include/kernel/syscalls.H | 10 | ||||
-rw-r--r-- | src/include/string.h | 1 | ||||
-rw-r--r-- | src/include/sys/msg.h | 47 | ||||
-rw-r--r-- | src/include/util/locked/list.H | 153 | ||||
-rw-r--r-- | src/include/util/locked/queue.H | 2 | ||||
-rw-r--r-- | src/kernel/syscall.C | 154 | ||||
-rw-r--r-- | src/lib/makefile | 2 | ||||
-rw-r--r-- | src/lib/string.c | 21 | ||||
-rw-r--r-- | src/lib/syscall_msg.C | 65 | ||||
-rw-r--r-- | src/sys/init/init_main.C | 9 |
11 files changed, 490 insertions, 2 deletions
diff --git a/src/include/kernel/msg.H b/src/include/kernel/msg.H new file mode 100644 index 000000000..7a32197f5 --- /dev/null +++ b/src/include/kernel/msg.H @@ -0,0 +1,28 @@ +#ifndef __KERNEL_MSG_H +#define __KERNEL_MSG_H + +#include <kernel/types.h> +#include <sys/msg.h> +#include <util/locked/list.H> +#include <util/locked/queue.H> + +struct MessagePending +{ + typedef msg_t* key_type; + key_type key; + task_t* task; + + MessagePending* prev; + MessagePending* next; +}; + +class MessageQueue +{ + public: + Spinlock lock; + Util::Locked::List<MessagePending, MessagePending::key_type> messages; + Util::Locked::List<MessagePending, MessagePending::key_type> responses; + Util::Locked::Queue<task_t> waiting; +}; + +#endif diff --git a/src/include/kernel/syscalls.H b/src/include/kernel/syscalls.H index ebe7d0059..9a0672d63 100644 --- a/src/include/kernel/syscalls.H +++ b/src/include/kernel/syscalls.H @@ -15,6 +15,16 @@ namespace Systemcalls MUTEX_LOCK_CONTESTED, MUTEX_UNLOCK_CONTESTED, + MSGQ_CREATE, + MSGQ_DESTROY, + MSGQ_REGISTER_ROOT, + MSGQ_RESOLVE_ROOT, + + MSG_SEND, + MSG_SENDRECV, + MSG_RESPOND, + MSG_WAIT, + SYSCALL_MAX }; }; diff --git a/src/include/string.h b/src/include/string.h index f1465a4c0..a2b704067 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -9,6 +9,7 @@ extern "C" #endif void* memset(void* s, int c, size_t n); + int strcmp(const char* s1, const char* s2); #ifdef __cplusplus }; diff --git a/src/include/sys/msg.h b/src/include/sys/msg.h new file mode 100644 index 000000000..ca5dab7e6 --- /dev/null +++ b/src/include/sys/msg.h @@ -0,0 +1,47 @@ +#ifndef __SYS_MSG_H +#define __SYS_MSG_H + +#include <stdint.h> +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void* msg_q_t; + +struct msg_t +{ + uint32_t type; + uint32_t __reserved__async; + uint64_t data[2]; + void* extra_data; +}; + +// Message queue interfaces. +msg_q_t msg_q_create(); +int msg_q_destroy(); +int msg_q_register(msg_q_t q, char* name); +msg_q_t msg_q_resolve(char* name); + +// Message interfaces. +__attribute__((always_inline)) + inline msg_t* msg_allocate() { return (msg_t*)malloc(sizeof(msg_t)); } +__attribute__((always_inline)) + inline void msg_free(msg_t* m) { free(m); } + +int msg_send(msg_q_t q, msg_t* msg); +int msg_sendrecv(msg_q_t q, msg_t* msg); +int msg_respond(msg_q_t q, msg_t* msg); +msg_t* msg_wait(msg_q_t q); + +__attribute__((always_inline)) + inline uint32_t msg_is_async(msg_t* msg) + { return 0 == msg->__reserved__async; } + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/util/locked/list.H b/src/include/util/locked/list.H new file mode 100644 index 000000000..e4bc0f99c --- /dev/null +++ b/src/include/util/locked/list.H @@ -0,0 +1,153 @@ +#ifndef __UTIL_LOCKED_LIST_H +#define __UTIL_LOCKED_LIST_H + +#include <util/locked/lock.H> + +namespace Util +{ + namespace Locked + { + template <typename _T, typename _K, + bool locked = false, typename _S = int> + class List + { + public: + List() : head(NULL), tail(NULL), lock() {}; + ~List() {}; + + _T* remove(); + void insert(_T*); + + void erase(_T* node); + void erase(_K& key); + + _T* find(_K& key); + + protected: + _T* head; + _T* tail; + + _S lock; + + void __lock(); + void __unlock(); + }; + + template <typename _T, typename _K, bool locked, typename _S> + _T* List<_T,_K,locked,_S>::remove() + { + _T* item = NULL; + + __lock(); + + if (tail != NULL) + { + item = tail; + if (head == tail) + head = tail = NULL; + else + tail = item->prev; + } + + __unlock(); + + return item; + } + + template <typename _T, typename _K, bool locked, typename _S> + void List<_T,_K,locked,_S>::insert(_T* item) + { + __lock(); + + if (head == NULL) + { + item->next = item->prev = NULL; + head = tail = item; + } + else + { + item->prev = NULL; + item->next = head; + head = head->prev = item; + } + + __unlock(); + } + + template <typename _T, typename _K, bool locked, typename _S> + void List<_T,_K,locked,_S>::__lock() + { + Util::Locked::LockHelper<locked,_S>(lock).lock(); + } + + template <typename _T, typename _K, bool locked, typename _S> + void List<_T,_K,locked,_S>::__unlock() + { + Util::Locked::LockHelper<locked,_S>(lock).unlock(); + } + + template <typename _T, typename _K, bool locked, typename _S> + void List<_T,_K,locked,_S>::erase(_T* node) + { + __lock(); + + if (node == head) + head = node->next; + else + node->prev->next = node->next; + + if (node == tail) + tail = node->prev; + else + node->next->prev = node->prev; + + __unlock(); + } + + template <typename _T, typename _K, bool locked, typename _S> + void List<_T,_K,locked,_S>::erase(_K& key) + { + __lock(); + + _T* node = head; + + while((node != NULL) && (node->key != key)) + node = node->next; + + if (node != NULL) + { + if (node == head) + head = node->next; + else + node->prev->next = node->next; + + if (node == tail) + tail = node->prev; + else + node->next->prev = node->prev; + } + + __unlock(); + + return node; + } + + template <typename _T, typename _K, bool locked, typename _S> + _T* List<_T,_K,locked,_S>::find(_K& key) + { + __lock(); + + _T* node = head; + + while((node != NULL) && (node->key != key)) + node = node->next; + + __unlock(); + + return node; + } + } +} + + +#endif diff --git a/src/include/util/locked/queue.H b/src/include/util/locked/queue.H index 51d2c430e..651e24a80 100644 --- a/src/include/util/locked/queue.H +++ b/src/include/util/locked/queue.H @@ -17,7 +17,7 @@ namespace Util _T* remove(); void insert(_T*); - private: + protected: _T* head; _T* tail; diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index d3cff262c..b969745ca 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -7,6 +7,7 @@ #include <kernel/console.H> #include <kernel/pagemgr.H> #include <kernel/usermutex.H> +#include <kernel/msg.H> extern "C" void kernel_execute_decrementer() @@ -31,6 +32,14 @@ namespace Systemcalls void MutexDestroy(task_t*); void MutexLockCont(task_t*); void MutexUnlockCont(task_t*); + void MsgQCreate(task_t*); + void MsgQDestroy(task_t*); + void MsgQRegisterRoot(task_t*); + void MsgQResolveRoot(task_t*); + void MsgSend(task_t*); + void MsgSendRecv(task_t*); + void MsgRespond(task_t*); + void MsgWait(task_t*); syscall syscalls[] = { @@ -43,6 +52,16 @@ namespace Systemcalls &MutexDestroy, &MutexLockCont, &MutexUnlockCont, + + &MsgQCreate, + &MsgQDestroy, + &MsgQRegisterRoot, + &MsgQResolveRoot, + + &MsgSend, + &MsgSendRecv, + &MsgRespond, + &MsgWait, }; }; @@ -169,4 +188,139 @@ namespace Systemcalls m->lock.unlock(); TASK_SETRTN(t, 0); } + + void MsgQCreate(task_t* t) + { + TASK_SETRTN(t, (uint64_t) new MessageQueue()); + } + + void MsgQDestroy(task_t* t) + { + MessageQueue* mq = (MessageQueue*) TASK_GETARG0(t); + if (NULL != mq) + delete mq; + TASK_SETRTN(t, 0); + } + + static MessageQueue* msgQRoot = NULL; + + void MsgQRegisterRoot(task_t* t) + { + msgQRoot = (MessageQueue*) TASK_GETARG0(t); + TASK_SETRTN(t, 0); + } + + void MsgQResolveRoot(task_t* t) + { + TASK_SETRTN(t, (uint64_t) msgQRoot); + } + + void MsgSend(task_t* t) + { + MessageQueue* mq = (MessageQueue*) TASK_GETARG0(t); + msg_t* m = (msg_t*) TASK_GETARG1(t); + m->__reserved__async = 0; // set to async msg. + + mq->lock.lock(); + + // Get waiting (server) task. + task_t* waiter = mq->waiting.remove(); + if (NULL == waiter) // None found, add to 'messages' queue. + { + MessagePending* mp = new MessagePending(); + mp->key = m; + mp->task = t; + mq->messages.insert(mp); + } + else // Add waiter back to its scheduler. + { + TASK_SETRTN(waiter, (uint64_t) m); + waiter->cpu->scheduler->addTask(waiter); + } + + mq->lock.unlock(); + TASK_SETRTN(t, 0); + } + + void MsgSendRecv(task_t* t) + { + MessageQueue* mq = (MessageQueue*) TASK_GETARG0(t); + msg_t* m = (msg_t*) TASK_GETARG1(t); + m->__reserved__async = 1; // set to sync msg. + + mq->lock.lock(); + MessagePending* mp = new MessagePending(); + mp->key = m; + mp->task = t; + + // Get waiting (server) task. + task_t* waiter = mq->waiting.remove(); + if (NULL == waiter) // None found, add to 'messages' queue. + { + mq->messages.insert(mp); + } + else // Context switch to waiter. + { + TASK_SETRTN(waiter, (uint64_t) m); + mq->responses.insert(mp); + waiter->cpu = t->cpu; + TaskManager::setCurrentTask(waiter); + } + + mq->lock.unlock(); + TASK_SETRTN(t,0); + } + + void MsgRespond(task_t* t) + { + MessageQueue* mq = (MessageQueue*) TASK_GETARG0(t); + msg_t* m = (msg_t*) TASK_GETARG1(t); + + mq->lock.lock(); + MessagePending* mp = mq->responses.find(m); + if (NULL != mp) + { + task_t* waiter = mp->task; + + mq->responses.erase(mp); + delete mp; + + waiter->cpu = t->cpu; + TaskManager::setCurrentTask(waiter); + t->cpu->scheduler->addTask(t); + + TASK_SETRTN(t,0); + } + else + { + TASK_SETRTN(t, -1); + } + mq->lock.unlock(); + } + + void MsgWait(task_t* t) + { + MessageQueue* mq = (MessageQueue*) TASK_GETARG0(t); + + mq->lock.lock(); + MessagePending* mp = mq->messages.remove(); + + if (NULL == mp) + { + mq->waiting.insert(t); + t->cpu->scheduler->setNextRunnable(); + } + else + { + msg_t* m = mp->key; + if (m->__reserved__async) + mq->responses.insert(mp); + else + delete mp; + TASK_SETRTN(t, (uint64_t) m); + } + mq->lock.unlock(); + } + + }; diff --git a/src/lib/makefile b/src/lib/makefile index 718a8219e..febe3f27f 100644 --- a/src/lib/makefile +++ b/src/lib/makefile @@ -2,7 +2,7 @@ OBJDIR = ../../obj include ../../config.mk OBJS = string.o stdlib.o -OBJS += syscall_stub.o syscall_task.o syscall_mutex.o +OBJS += syscall_stub.o syscall_task.o syscall_mutex.o syscall_msg.o OBJECTS = $(addprefix ${OBJDIR}/, ${OBJS}) all: ${OBJECTS} diff --git a/src/lib/string.c b/src/lib/string.c index b84de213f..fb4d435ae 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -9,3 +9,24 @@ void* memset(void* s, int c, size_t n) _s++; n--; } } + +int strcmp(const char* a, const char* b) +{ + while((*a != '\0') && (*b != '\0')) + { + if (*a == *b) + { + a++; b++; + } + else + { + return (*a > *b) ? 1 : -1; + } + } + if (*a == *b) + return 0; + if (*a == '\0') + return -1; + else + return 1; +} diff --git a/src/lib/syscall_msg.C b/src/lib/syscall_msg.C new file mode 100644 index 000000000..774ddb0bb --- /dev/null +++ b/src/lib/syscall_msg.C @@ -0,0 +1,65 @@ +#include <sys/msg.h> +#include <sys/syscall.h> + +#include <string.h> + +using namespace Systemcalls; + +const char* VFS_ROOT = "/"; // TODO. + +msg_q_t msg_q_create() +{ + return (msg_q_t) _syscall0(MSGQ_CREATE); +} + +int msg_q_destroy(msg_q_t q) +{ + return (int64_t)_syscall1(MSGQ_DESTROY, q); +} + +int msg_q_register(msg_q_t q, char* name) +{ + if (0 == strcmp(VFS_ROOT, name)) + { + return (int64_t)_syscall1(MSGQ_REGISTER_ROOT, q); + } + else + { + // TODO. + return -1; + } +} + +msg_q_t msg_q_resolve(char* name) +{ + if (0 == strcmp(VFS_ROOT, name)) + { + return (msg_q_t)_syscall0(MSGQ_RESOLVE_ROOT); + } + else + { + // TODO. + return NULL; + } +} + +int msg_send(msg_q_t q, msg_t* msg) +{ + return (int64_t)_syscall2(MSG_SEND, q, msg); +} + +int msg_sendrecv(msg_q_t q, msg_t* msg) +{ + return (int64_t)_syscall2(MSG_SENDRECV, q, msg); +} + +int msg_respond(msg_q_t q, msg_t* msg) +{ + return (int64_t)_syscall2(MSG_RESPOND, q, msg); +} + +msg_t* msg_wait(msg_q_t q) +{ + return (msg_t*)_syscall1(MSG_WAIT, q); +} + diff --git a/src/sys/init/init_main.C b/src/sys/init/init_main.C index efeddcafd..c11b4ef97 100644 --- a/src/sys/init/init_main.C +++ b/src/sys/init/init_main.C @@ -2,6 +2,7 @@ #include <sys/task.h> #include <sys/mutex.h> +#include <sys/msg.h> mutex_t global_mutex; @@ -19,6 +20,14 @@ void init_main(void* unused) global_mutex = mutex_create(); + msg_q_t msgq = msg_q_create(); + msg_t* msg = msg_allocate(); + msg->type = 1; msg->data[0] = 0xDEADBEEF12345678; + msg_send(msgq, msg); + msg = msg_wait(msgq); + + printk("Got Message: %llx\n", msg->data[0]); + while(1) { mutex_lock(global_mutex); |