From 6fbb83c9c2ed7e15e286b6058ca48bcacc5166d2 Mon Sep 17 00:00:00 2001 From: Aleksander Kaminski Date: Wed, 13 Sep 2023 18:00:55 +0200 Subject: [PATCH] msg: Return a handle instead of kernel pointer in msgRevc Breaking API change! Add idtree from libphoenix, some MISRA improvements JIRA: RTOS-606 --- include/msg.h | 3 + lib/Makefile | 2 +- lib/idtree.c | 154 ++++++++++++++++++++++++++++++++++ lib/idtree.h | 53 ++++++++++++ lib/lib.h | 1 + lib/rb.h | 8 +- proc/msg-nommu.c | 64 ++++++++++---- proc/msg.c | 211 ++++++++++++++++++++++++++++++----------------- proc/msg.h | 9 +- proc/ports.c | 44 +++++++++- proc/ports.h | 22 +++-- syscalls.c | 8 +- test/msg.c | 2 +- usrv.c | 2 +- 14 files changed, 475 insertions(+), 108 deletions(-) create mode 100644 lib/idtree.c create mode 100644 lib/idtree.h diff --git a/include/msg.h b/include/msg.h index 4bc17941d..9af1b5d39 100644 --- a/include/msg.h +++ b/include/msg.h @@ -16,6 +16,9 @@ #ifndef _PHOENIX_MSG_H_ #define _PHOENIX_MSG_H_ +/* Return id, allocated in msgReceive, used in msgRespond */ +typedef unsigned int msg_rid_t; + /* * Message types */ diff --git a/lib/Makefile b/lib/Makefile index f69aed68e..de858b25d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -5,5 +5,5 @@ # Author: Pawel Pisarczyk # -OBJS += $(addprefix $(PREFIX_O)lib/, assert.o printf.o bsearch.o rand.o strtoul.o rb.o list.o cbuffer.o strutil.o) +OBJS += $(addprefix $(PREFIX_O)lib/, assert.o printf.o bsearch.o rand.o strtoul.o rb.o list.o cbuffer.o strutil.o idtree.o) diff --git a/lib/idtree.c b/lib/idtree.c new file mode 100644 index 000000000..a15685e73 --- /dev/null +++ b/lib/idtree.c @@ -0,0 +1,154 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * id allocating tree + * + * Copyright 2018 Phoenix Systems + * Author: Jan Sikorski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#include "lib.h" + + +static int lib_idtreeCmp(rbnode_t *n1, rbnode_t *n2) +{ + idnode_t *i1 = lib_treeof(idnode_t, linkage, n1); + idnode_t *i2 = lib_treeof(idnode_t, linkage, n2); + + return (i1->id - i2->id); +} + + +static int lib_idtreeGapcmp(rbnode_t *n1, rbnode_t *n2) +{ + idnode_t *r1 = lib_treeof(idnode_t, linkage, n1); + idnode_t *r2 = lib_treeof(idnode_t, linkage, n2); + rbnode_t *child = NULL; + int ret = 1; + + if (r1->lmaxgap > 0 && r1->rmaxgap > 0) { + if (r2->id > r1->id) { + child = n1->right; + ret = -1; + } + else { + child = n1->left; + ret = 1; + } + } + else if (r1->lmaxgap > 0) { + child = n1->left; + ret = 1; + } + else if (r1->rmaxgap > 0) { + child = n1->right; + ret = -1; + } + + if (child == NULL) + return 0; + + return ret; +} + + +static void lib_idtreeAugment(rbnode_t *node) +{ + rbnode_t *it; + idnode_t *n = lib_treeof(idnode_t, linkage, node); + idnode_t *p = n, *r, *l; + + if (node->left == NULL) { + for (it = node; it->parent != NULL; it = it->parent) { + p = lib_treeof(idnode_t, linkage, it->parent); + if (it->parent->right == it) + break; + } + + n->lmaxgap = (n->id <= p->id) ? n->id : n->id - p->id - 1; + } + else { + l = lib_treeof(idnode_t, linkage, node->left); + n->lmaxgap = max(l->lmaxgap, l->rmaxgap); + } + + if (node->right == NULL) { + for (it = node; it->parent != NULL; it = it->parent) { + p = lib_treeof(idnode_t, linkage, it->parent); + if (it->parent->left == it) + break; + } + + n->rmaxgap = (n->id >= p->id) ? (unsigned)-1 - n->id - 1 : p->id - n->id - 1; + } + else { + r = lib_treeof(idnode_t, linkage, node->right); + n->rmaxgap = max(r->lmaxgap, r->rmaxgap); + } + + for (it = node; it->parent != NULL; it = it->parent) { + n = lib_treeof(idnode_t, linkage, it); + p = lib_treeof(idnode_t, linkage, it->parent); + + if (it->parent->left == it) + p->lmaxgap = max(n->lmaxgap, n->rmaxgap); + else + p->rmaxgap = max(n->lmaxgap, n->rmaxgap); + } +} + + +void lib_idtreeInit(idtree_t *tree) +{ + lib_rbInit(tree, lib_idtreeCmp, lib_idtreeAugment); +} + + +idnode_t *lib_idtreeFind(idtree_t *tree, int id) +{ + idnode_t n; + n.id = id; + return lib_treeof(idnode_t, linkage, lib_rbFind(tree, &n.linkage)); +} + + +void lib_idtreeRemove(idtree_t *tree, idnode_t *node) +{ + lib_rbRemove(tree, &node->linkage); +} + + +int lib_idtreeId(idnode_t *node) +{ + return node->id; +} + + +int lib_idtreeAlloc(idtree_t *tree, idnode_t *n) +{ + idnode_t *f; + + n->id = 0; + if (tree->root != NULL) { + f = lib_treeof(idnode_t, linkage, lib_rbFindEx(tree->root, &n->linkage, lib_idtreeGapcmp)); + + if (f != NULL) { + if (f->lmaxgap > 0) + n->id = f->id - 1; + else + n->id = f->id + 1; + } + else { + return -1; + } + } + + lib_rbInsert(tree, &n->linkage); + return n->id; +} diff --git a/lib/idtree.h b/lib/idtree.h new file mode 100644 index 000000000..a603cca51 --- /dev/null +++ b/lib/idtree.h @@ -0,0 +1,53 @@ +/* + * Phoenix-RTOS + * + * Operating system kernel + * + * id allocating tree + * + * Copyright 2018 Phoenix Systems + * Author: Jan Sikorski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + +#ifndef _PHOENIX_IDTREE_H_ +#define _PHOENIX_IDTREE_H_ + +#include "rb.h" + + +typedef rbtree_t idtree_t; + + +typedef struct { + rbnode_t linkage; + unsigned int lmaxgap, rmaxgap; + unsigned int id; +} idnode_t; + + +#define lib_idtreeof(type, node_field, node) ({ \ + long _off = (long)&(((type *) 0)->node_field); \ + idnode_t *tmpnode = (node); \ + (type *)((tmpnode == NULL) ? NULL : ((void *) tmpnode - _off)); \ +}) + + +void lib_idtreeInit(idtree_t *tree); + + +idnode_t *lib_idtreeFind(idtree_t *tree, int id); + + +void lib_idtreeRemove(idtree_t *tree, idnode_t *node); + + +int lib_idtreeId(idnode_t *node); + + +int lib_idtreeAlloc(idtree_t *tree, idnode_t *n); + +#endif diff --git a/lib/lib.h b/lib/lib.h index 01456e802..33f05cb08 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -26,6 +26,7 @@ #include "list.h" #include "assert.h" #include "strutil.h" +#include "idtree.h" #define lib_atomicIncrement(ptr) __atomic_add_fetch(ptr, 1, __ATOMIC_RELAXED) diff --git a/lib/rb.h b/lib/rb.h index d4f2af347..0c8556087 100644 --- a/lib/rb.h +++ b/lib/rb.h @@ -19,10 +19,10 @@ //#include "../hal/hal.h" -#define lib_treeof(type, node_field, node) ({ \ - long _off = (long) &(((type *) 0)->node_field); \ - rbnode_t *tmpnode = (node); \ - (type *) ((tmpnode == NULL) ? NULL : ((void *) tmpnode - _off)); \ +#define lib_treeof(type, node_field, node) ({ \ + long _off = (long)&(((type *) 0)->node_field); \ + rbnode_t *tmpnode = (node); \ + (type *)((tmpnode == NULL) ? NULL : ((void *) tmpnode - _off)); \ }) diff --git a/proc/msg-nommu.c b/proc/msg-nommu.c index 262f78417..95ee00b38 100644 --- a/proc/msg-nommu.c +++ b/proc/msg-nommu.c @@ -35,8 +35,10 @@ int proc_send(u32 port, msg_t *msg) thread_t *sender; spinlock_ctx_t sc; - if ((p = proc_portGet(port)) == NULL) + p = proc_portGet(port); + if (p == NULL) { return -EINVAL; + } sender = proc_current(); @@ -55,11 +57,22 @@ int proc_send(u32 port, msg_t *msg) } else { LIST_ADD(&p->kmessages, &kmsg); - proc_threadWakeup(&p->threads); - while (kmsg.state != msg_responded && kmsg.state != msg_rejected) - err = proc_threadWait(&kmsg.threads, &p->spinlock, 0, &sc); + while ((kmsg.state != msg_responded) && (kmsg.state != msg_rejected)) { + err = proc_threadWaitInterruptible(&kmsg.threads, &p->spinlock, 0, &sc); + + if (err != EOK) { + if (kmsg.state == msg_waiting) { + LIST_REMOVE(&p->kmessages, &kmsg); + } + break; + } + } + + if (kmsg.state == msg_responded) { + err = EOK; /* Don't report EINTR if we got the response already */ + } } hal_spinlockClear(&p->spinlock, &sc); @@ -70,19 +83,23 @@ int proc_send(u32 port, msg_t *msg) } -int proc_recv(u32 port, msg_t *msg, unsigned long int *rid) +int proc_recv(u32 port, msg_t *msg, msg_rid_t *rid) { port_t *p; kmsg_t *kmsg; spinlock_ctx_t sc; + int err; - if ((p = proc_portGet(port)) == NULL) + p = proc_portGet(port); + if (p == NULL) { return -EINVAL; + } hal_spinlockSet(&p->spinlock, &sc); - while (p->kmessages == NULL && !p->closed) - proc_threadWait(&p->threads, &p->spinlock, 0, &sc); + while ((p->kmessages == NULL) && (p->closed == 0) && (err != -EINTR)) { + err = proc_threadWaitInterruptible(&p->threads, &p->spinlock, 0, &sc); + } kmsg = p->kmessages; @@ -99,29 +116,47 @@ int proc_recv(u32 port, msg_t *msg, unsigned long int *rid) return -EINVAL; } + if (proc_portRidAlloc(p, kmsg) < 0) { + hal_spinlockSet(&p->spinlock, &sc); + kmsg->state = msg_rejected; + proc_threadWakeup(&kmsg->threads); + hal_spinlockClear(&p->spinlock, &sc); + + port_put(p, 0); + + return -ENOMEM; + } + kmsg->state = msg_received; LIST_REMOVE(&p->kmessages, kmsg); hal_spinlockClear(&p->spinlock, &sc); - /* (MOD) */ - (*rid) = (unsigned long)(kmsg); + *rid = lib_idtreeId(&kmsg->idlinkage); hal_memcpy(msg, kmsg->msg, sizeof(*msg)); - port_put(p, 0); + /* Don't dereference port until proc_respond */ + return EOK; } -int proc_respond(u32 port, msg_t *msg, unsigned long int rid) +int proc_respond(u32 port, msg_t *msg, msg_rid_t rid) { port_t *p; size_t s = 0; - kmsg_t *kmsg = (kmsg_t *)(unsigned long)rid; + kmsg_t *kmsg; spinlock_ctx_t sc; - if ((p = proc_portGet(port)) == NULL) + p = proc_portGet(port); + if (p == NULL) { return -EINVAL; + } + + kmsg = proc_portRidGet(p, rid); + if (kmsg == NULL) { + return -ENOENT; + } hal_memcpy(kmsg->msg->o.raw, msg->o.raw, sizeof(msg->o.raw)); @@ -131,6 +166,7 @@ int proc_respond(u32 port, msg_t *msg, unsigned long int rid) proc_threadWakeup(&kmsg->threads); hal_spinlockClear(&p->spinlock, &sc); port_put(p, 0); + port_put(p, 0); /* Extra to compensate for it's lack in proc_recv */ return s; } diff --git a/proc/msg.c b/proc/msg.c index 989af26d8..6c088b274 100644 --- a/proc/msg.c +++ b/proc/msg.c @@ -18,8 +18,8 @@ #include "proc.h" -#define FLOOR(x) ((x) & ~(SIZE_PAGE - 1)) -#define CEIL(x) (((x) + SIZE_PAGE - 1) & ~(SIZE_PAGE - 1)) +#define FLOOR(x) ((x) & ~(SIZE_PAGE - 1)) +#define CEIL(x) (((x) + SIZE_PAGE - 1) & ~(SIZE_PAGE - 1)) enum { msg_rejected = -1, msg_waiting = 0, msg_received, msg_responded }; @@ -42,14 +42,14 @@ static void *msg_map(int dir, kmsg_t *kmsg, void *data, size_t size, process_t * int flags; addr_t bpa, pa, epa; - if ((size == 0) || (data == NULL)) + if ((size == 0) || (data == NULL)) { return NULL; - + } attr = PGHD_PRESENT; prot = PROT_READ; - if (dir) { + if (dir != 0) { attr |= PGHD_WRITE; prot |= PROT_WRITE; } @@ -61,56 +61,76 @@ static void *msg_map(int dir, kmsg_t *kmsg, void *data, size_t size, process_t * boffs = (unsigned long)data & (SIZE_PAGE - 1); - if (FLOOR((unsigned long)data + size) > CEIL((unsigned long)data)) + if (FLOOR((unsigned long)data + size) > CEIL((unsigned long)data)) { n = (FLOOR((unsigned long)data + size) - CEIL((unsigned long)data)) / SIZE_PAGE; + } - if (boffs && (FLOOR((unsigned long)data) == FLOOR((unsigned long)data + size))) + if ((boffs != 0) && (FLOOR((unsigned long)data) == FLOOR((unsigned long)data + size))) { /* Data is on one page only and will be copied by boffs handler */ eoffs = 0; - else + } + else { eoffs = ((unsigned long)data + size) & (SIZE_PAGE - 1); + } srcmap = (from == NULL) ? msg_common.kmap : from->mapp; dstmap = (to == NULL) ? msg_common.kmap : to->mapp; - if (srcmap == dstmap && pmap_belongs(&dstmap->pmap, data)) + if ((srcmap == dstmap) && (pmap_belongs(&dstmap->pmap, data) != 0)) { return data; + } - if ((ml->w = w = vm_mapFind(dstmap, (void *)0, (!!boffs + !!eoffs + n) * SIZE_PAGE, MAP_NOINHERIT, prot)) == NULL) + w = vm_mapFind(dstmap, (void *)0, (!!boffs + !!eoffs + n) * SIZE_PAGE, MAP_NOINHERIT, prot); + ml->w = w; + if (w == NULL) { return NULL; + } - if (pmap_belongs(&srcmap->pmap, data)) + if (pmap_belongs(&srcmap->pmap, data) != 0) { flags = vm_mapFlags(srcmap, data); - else + } + else { flags = vm_mapFlags(msg_common.kmap, data); + } - if (flags < 0) + if (flags < 0) { return NULL; + } - if (flags & MAP_DEVICE) + if ((flags & MAP_DEVICE) != 0) { attr |= PGHD_DEV; + } - if (flags & MAP_UNCACHED) + if ((flags & MAP_UNCACHED) != 0) { attr |= PGHD_NOT_CACHED; + } if (boffs > 0) { ml->boffs = boffs; bpa = pmap_resolve(&srcmap->pmap, data) & ~(SIZE_PAGE - 1); - if ((ml->bp = nbp = vm_pageAlloc(SIZE_PAGE, PAGE_OWNER_APP)) == NULL) + nbp = vm_pageAlloc(SIZE_PAGE, PAGE_OWNER_APP); + ml->bp = nbp; + if (nbp == NULL) { return NULL; + } - if ((ml->bvaddr = vaddr = vm_mmap(msg_common.kmap, (void *)0, NULL, SIZE_PAGE, PROT_READ | PROT_WRITE, (void *)-1, bpa, flags)) == NULL) + vaddr = vm_mmap(msg_common.kmap, (void *)0, NULL, SIZE_PAGE, PROT_READ | PROT_WRITE, (void *)-1, bpa, flags); + ml->bvaddr = vaddr; + if (vaddr == NULL) { return NULL; + } /* Map new page into destination address space */ - if (page_map(&dstmap->pmap, w, nbp->addr, (attr | PGHD_WRITE) & ~PGHD_USER) < 0) + if (page_map(&dstmap->pmap, w, nbp->addr, (attr | PGHD_WRITE) & ~PGHD_USER) < 0) { return NULL; + } hal_memcpy(w + boffs, vaddr + boffs, min(size, SIZE_PAGE - boffs)); - if (page_map(&dstmap->pmap, w, nbp->addr, attr) < 0) + if (page_map(&dstmap->pmap, w, nbp->addr, attr) < 0) { return NULL; + } } /* Map pages */ @@ -118,8 +138,9 @@ static void *msg_map(int dir, kmsg_t *kmsg, void *data, size_t size, process_t * for (i = 0; i < n; i++, vaddr += SIZE_PAGE) { pa = pmap_resolve(&srcmap->pmap, vaddr) & ~(SIZE_PAGE - 1); - if (page_map(&dstmap->pmap, w + (i + !!boffs) * SIZE_PAGE, pa, attr) < 0) + if (page_map(&dstmap->pmap, w + (i + !!boffs) * SIZE_PAGE, pa, attr) < 0) { return NULL; + } } if (eoffs) { @@ -127,25 +148,33 @@ static void *msg_map(int dir, kmsg_t *kmsg, void *data, size_t size, process_t * vaddr = (void *)FLOOR((unsigned long)data + size); epa = pmap_resolve(&srcmap->pmap, vaddr) & ~(SIZE_PAGE - 1); - if (!boffs || (eoffs >= boffs)) { - if ((ml->ep = nep = vm_pageAlloc(SIZE_PAGE, PAGE_OWNER_APP)) == NULL) + if ((boffs == 0) || (eoffs >= boffs)) { + nep = vm_pageAlloc(SIZE_PAGE, PAGE_OWNER_APP); + ml->ep = nep; + if (nep == NULL) { return NULL; + } } else { nep = nbp; } - if ((ml->evaddr = vaddr = vm_mmap(msg_common.kmap, (void *)0, NULL, SIZE_PAGE, PROT_READ | PROT_WRITE, (void *)-1, epa, flags)) == NULL) + vaddr = vm_mmap(msg_common.kmap, (void *)0, NULL, SIZE_PAGE, PROT_READ | PROT_WRITE, (void *)-1, epa, flags); + ml->evaddr = vaddr; + if (vaddr == NULL) { return NULL; + } /* Map new page into destination address space */ - if (page_map(&dstmap->pmap, w + (n + !!boffs) * SIZE_PAGE, nep->addr, (attr | PGHD_WRITE) & ~PGHD_USER) < 0) + if (page_map(&dstmap->pmap, w + (n + !!boffs) * SIZE_PAGE, nep->addr, (attr | PGHD_WRITE) & ~PGHD_USER) < 0) { return NULL; + } hal_memcpy(w + (n + !!boffs) * SIZE_PAGE, vaddr, eoffs); - if (page_map(&dstmap->pmap, w + (n + !!boffs) * SIZE_PAGE, nep->addr, attr) < 0) + if (page_map(&dstmap->pmap, w + (n + !!boffs) * SIZE_PAGE, nep->addr, attr) < 0) { return NULL; + } } return (w + boffs); @@ -163,18 +192,22 @@ static void msg_release(kmsg_t *kmsg) kmsg->i.bp = NULL; } - if (kmsg->i.eoffs) { - if (kmsg->i.ep != NULL) + if (kmsg->i.eoffs != 0) { + if (kmsg->i.ep != NULL) { vm_pageFree(kmsg->i.ep); + } vm_munmap(msg_common.kmap, kmsg->i.evaddr, SIZE_PAGE); kmsg->i.eoffs = 0; kmsg->i.ep = NULL; } - if ((process = proc_current()->process) != NULL) + process = proc_current()->process; + if (process != NULL) { map = process->mapp; - else + } + else { map = msg_common.kmap; + } if (kmsg->i.w != NULL) { vm_munmap(map, kmsg->i.w, CEIL((unsigned long)kmsg->msg.i.data + kmsg->msg.i.size) - FLOOR((unsigned long)kmsg->msg.i.data)); @@ -188,8 +221,9 @@ static void msg_release(kmsg_t *kmsg) } if (kmsg->o.eoffs) { - if (kmsg->o.ep != NULL) + if (kmsg->o.ep != NULL) { vm_pageFree(kmsg->o.ep); + } vm_munmap(msg_common.kmap, kmsg->o.evaddr, SIZE_PAGE); kmsg->o.eoffs = 0; kmsg->o.ep = NULL; @@ -250,8 +284,9 @@ static void msg_ipack(kmsg_t *kmsg) return; } - if (kmsg->msg.i.size > sizeof(kmsg->msg.i.raw) - offset) + if (kmsg->msg.i.size > (sizeof(kmsg->msg.i.raw) - offset)) { return; + } hal_memcpy(kmsg->msg.i.raw + offset, kmsg->msg.i.data, kmsg->msg.i.size); kmsg->msg.i.data = kmsg->msg.i.raw + offset; @@ -263,8 +298,9 @@ static int msg_opack(kmsg_t *kmsg) { size_t offset; - if (kmsg->msg.o.data == NULL) + if (kmsg->msg.o.data == NULL) { return 0; + } switch (kmsg->msg.type) { case mtOpen: @@ -297,8 +333,9 @@ static int msg_opack(kmsg_t *kmsg) return 0; } - if (kmsg->msg.o.size > sizeof(kmsg->msg.o.raw) - offset) + if (kmsg->msg.o.size > (sizeof(kmsg->msg.o.raw) - offset)) { return 0; + } kmsg->msg.o.data = kmsg->msg.o.raw + offset; @@ -314,16 +351,18 @@ int proc_send(u32 port, msg_t *msg) thread_t *sender; spinlock_ctx_t sc; - if (msg == NULL) + /* TODO - check if msg pointer belongs to user vm_map */ + if (msg == NULL) { return -EINVAL; + } - if ((p = proc_portGet(port)) == NULL) + p = proc_portGet(port); + if (p == NULL) { return -EINVAL; + } sender = proc_current(); - /* TODO - check if msg pointer belongs to user vm_map */ - hal_memcpy(&kmsg.msg, msg, sizeof(msg_t)); kmsg.src = sender->process; kmsg.threads = NULL; @@ -336,57 +375,65 @@ int proc_send(u32 port, msg_t *msg) hal_spinlockSet(&p->spinlock, &sc); - if (p->closed) { + if (p->closed != 0) { err = -EINVAL; } else { LIST_ADD(&p->kmessages, &kmsg); proc_threadWakeup(&p->threads); - while (kmsg.state != msg_responded && kmsg.state != msg_rejected) { + while ((kmsg.state != msg_responded) && (kmsg.state != msg_rejected)) { err = proc_threadWaitInterruptible(&kmsg.threads, &p->spinlock, 0, &sc); - if ((err != EOK && kmsg.state == msg_waiting)) { - LIST_REMOVE(&p->kmessages, &kmsg); + if (err != EOK) { + if (kmsg.state == msg_waiting) { + LIST_REMOVE(&p->kmessages, &kmsg); + } break; } } - if (kmsg.state == msg_responded) + if (kmsg.state == msg_responded) { err = EOK; /* Don't report EINTR if we got the response already */ + } } hal_spinlockClear(&p->spinlock, &sc); port_put(p, 0); - if (err != EOK) + if (err != EOK) { return err; + } hal_memcpy(msg->o.raw, kmsg.msg.o.raw, sizeof(msg->o.raw)); /* If msg.o.data has been packed to msg.o.raw */ - if ((kmsg.msg.o.data > (void *)kmsg.msg.o.raw) && (kmsg.msg.o.data < (void *)kmsg.msg.o.raw + sizeof(kmsg.msg.o.raw))) + if ((kmsg.msg.o.data > (void *)kmsg.msg.o.raw) && (kmsg.msg.o.data < (void *)kmsg.msg.o.raw + sizeof(kmsg.msg.o.raw))) { hal_memcpy(msg->o.data, kmsg.msg.o.data, msg->o.size); + } return kmsg.state == msg_rejected ? -EINVAL : err; } -int proc_recv(u32 port, msg_t *msg, unsigned long int *rid) +int proc_recv(u32 port, msg_t *msg, msg_rid_t *rid) { port_t *p; kmsg_t *kmsg; - int ipacked = 0, opacked = 0, closed, err = EOK; + int ipacked = 0, opacked = 0, err = EOK; spinlock_ctx_t sc; - if ((p = proc_portGet(port)) == NULL) + p = proc_portGet(port); + if (p == NULL) { return -EINVAL; + } hal_spinlockSet(&p->spinlock, &sc); - while (p->kmessages == NULL && !p->closed && err != -EINTR) + while ((p->kmessages == NULL) && (p->closed == 0) && (err != -EINTR)) { err = proc_threadWaitInterruptible(&p->threads, &p->spinlock, 0, &sc); + } kmsg = p->kmessages; @@ -400,9 +447,11 @@ int proc_recv(u32 port, msg_t *msg, unsigned long int *rid) err = -EINVAL; } - else if (err == EOK) { - LIST_REMOVE(&p->kmessages, kmsg); - kmsg->state = msg_received; + else { + if (err == EOK) { + LIST_REMOVE(&p->kmessages, kmsg); + kmsg->state = msg_received; + } } hal_spinlockClear(&p->spinlock, &sc); @@ -411,9 +460,6 @@ int proc_recv(u32 port, msg_t *msg, unsigned long int *rid) return err; } - /* (MOD) */ - (*rid) = (unsigned long)(kmsg); - kmsg->i.bvaddr = NULL; kmsg->i.boffs = 0; kmsg->i.w = NULL; @@ -430,21 +476,24 @@ int proc_recv(u32 port, msg_t *msg, unsigned long int *rid) kmsg->o.eoffs = 0; kmsg->o.ep = NULL; - if ((kmsg->msg.i.data > (void *)kmsg->msg.i.raw) && (kmsg->msg.i.data < (void *)kmsg->msg.i.raw + sizeof(kmsg->msg.i.raw))) + if ((kmsg->msg.i.data > (void *)kmsg->msg.i.raw) && (kmsg->msg.i.data < (void *)kmsg->msg.i.raw + sizeof(kmsg->msg.i.raw))) { ipacked = 1; + } /* Map data in receiver space */ /* Don't map if msg is packed */ - if (!ipacked) + if (ipacked == 0) { kmsg->msg.i.data = msg_map(0, kmsg, kmsg->msg.i.data, kmsg->msg.i.size, kmsg->src, proc_current()->process); + } - if (!(opacked = msg_opack(kmsg))) + opacked = msg_opack(kmsg); + if (opacked == 0) { kmsg->msg.o.data = msg_map(1, kmsg, kmsg->msg.o.data, kmsg->msg.o.size, kmsg->src, proc_current()->process); + } - if ((kmsg->msg.i.size && kmsg->msg.i.data == NULL) || - (kmsg->msg.o.size && kmsg->msg.o.data == NULL) || - p->closed) { - closed = p->closed; + if (((kmsg->msg.i.size != 0) && (kmsg->msg.i.data == NULL)) || + ((kmsg->msg.o.size != 0) && (kmsg->msg.o.data == NULL)) || + (proc_portRidAlloc(p, kmsg) < 0)) { msg_release(kmsg); hal_spinlockSet(&p->spinlock, &sc); @@ -454,47 +503,60 @@ int proc_recv(u32 port, msg_t *msg, unsigned long int *rid) port_put(p, 0); - return closed ? -EINVAL : -ENOMEM; + return -ENOMEM; } + *rid = lib_idtreeId(&kmsg->idlinkage); + hal_memcpy(msg, &kmsg->msg, sizeof(*msg)); - if (ipacked) + if (ipacked != 0) { msg->i.data = msg->i.raw + (kmsg->msg.i.data - (void *)kmsg->msg.i.raw); + } - if (opacked) + if (opacked != 0) { msg->o.data = msg->o.raw + (kmsg->msg.o.data - (void *)kmsg->msg.o.raw); + } -/* lib_printf("proc_recv 3: %p %d ipacked:%d\n", kmsg, kmsg->i.eoffs, ipacked); */ + /* Don't dereference port until proc_respond */ - port_put(p, 0); return EOK; } -int proc_respond(u32 port, msg_t *msg, unsigned long int rid) +int proc_respond(u32 port, msg_t *msg, msg_rid_t rid) { port_t *p; size_t s = 0; - kmsg_t *kmsg = (kmsg_t *)(unsigned long)rid; + kmsg_t *kmsg; spinlock_ctx_t sc; - if ((p = proc_portGet(port)) == NULL) + p = proc_portGet(port); + if (p == NULL) { return -EINVAL; + } + + kmsg = proc_portRidGet(p, rid); + if (kmsg == NULL) { + return -ENOENT; + } /* Copy shadow pages */ - if (kmsg->i.bp != NULL) + if (kmsg->i.bp != NULL) { hal_memcpy(kmsg->i.bvaddr + kmsg->i.boffs, kmsg->i.w + kmsg->i.boffs, min(SIZE_PAGE - kmsg->i.boffs, kmsg->msg.i.size)); + } - if (kmsg->i.eoffs) + if (kmsg->i.eoffs) { hal_memcpy(kmsg->i.evaddr, kmsg->i.w + kmsg->i.boffs + kmsg->msg.i.size - kmsg->i.eoffs, kmsg->i.eoffs); + } - if (kmsg->o.bp != NULL) + if (kmsg->o.bp != NULL) { hal_memcpy(kmsg->o.bvaddr + kmsg->o.boffs, kmsg->o.w + kmsg->o.boffs, min(SIZE_PAGE - kmsg->o.boffs, kmsg->msg.o.size)); + } - - if (kmsg->o.eoffs) + if (kmsg->o.eoffs) { hal_memcpy(kmsg->o.evaddr, kmsg->o.w + kmsg->o.boffs + kmsg->msg.o.size - kmsg->o.eoffs, kmsg->o.eoffs); + } msg_release(kmsg); @@ -507,6 +569,7 @@ int proc_respond(u32 port, msg_t *msg, unsigned long int rid) hal_cpuReschedule(&p->spinlock, &sc); port_put(p, 0); + port_put(p, 0); /* Extra to compensate for it's lack in proc_recv */ return s; } diff --git a/proc/msg.h b/proc/msg.h index c5cf8e628..60a5447de 100644 --- a/proc/msg.h +++ b/proc/msg.h @@ -19,6 +19,7 @@ #include "../hal/hal.h" #include "../include/errno.h" #include "../include/msg.h" +#include "../lib/lib.h" #include "threads.h" @@ -31,9 +32,13 @@ typedef struct _kmsg_t { struct _kmsg_t *next; struct _kmsg_t *prev; + + idnode_t idlinkage; + thread_t *threads; process_t *src; volatile int state; + #ifndef NOMMU struct _kmsg_layout_t { void *bvaddr; @@ -57,10 +62,10 @@ typedef struct _kmsg_t { extern int proc_send(u32 port, msg_t *msg); -extern int proc_recv(u32 port, msg_t *msg, unsigned long int *rid); +extern int proc_recv(u32 port, msg_t *msg, msg_rid_t *rid); -extern int proc_respond(u32 port, msg_t *msg, unsigned long int rid); +extern int proc_respond(u32 port, msg_t *msg, msg_rid_t rid); extern void _msg_init(vm_map_t *kmap, vm_object_t *kernel); diff --git a/proc/ports.c b/proc/ports.c index 25175adf3..95ba287f2 100644 --- a/proc/ports.c +++ b/proc/ports.c @@ -14,6 +14,7 @@ */ #include "ports.h" +#include "../lib/lib.h" struct { @@ -27,7 +28,15 @@ static int ports_cmp(rbnode_t *n1, rbnode_t *n2) port_t *p1 = lib_treeof(port_t, linkage, n1); port_t *p2 = lib_treeof(port_t, linkage, n2); - return (p1->id - p2->id); + if (p1->id > p2->id) { + return 1; + } + else if (p2->id > p1->id) { + return -1; + } + else { + return 0; + } } @@ -137,6 +146,35 @@ static int _proc_portAlloc(u32 *id) } +int proc_portRidAlloc(port_t *p, kmsg_t *kmsg) +{ + int ret; + + proc_lockSet(&p->lock); + ret = lib_idtreeAlloc(&p->rid, &kmsg->idlinkage); + proc_lockClear(&p->lock); + + return ret; +} + + +kmsg_t *proc_portRidGet(port_t *p, unsigned int rid) +{ + kmsg_t *kmsg; + + proc_lockSet(&p->lock); + + kmsg = lib_idtreeof(kmsg_t, idlinkage, lib_idtreeFind(&p->rid, rid)); + if (kmsg != NULL) { + lib_idtreeRemove(&p->rid, &kmsg->idlinkage); + } + + proc_lockClear(&p->lock); + + return kmsg; +} + + port_t *proc_portGet(u32 id) { port_t *port; @@ -188,6 +226,7 @@ void port_put(port_t *p, int destroy) LIST_REMOVE(&p->owner->ports, p); proc_lockClear(&p->owner->lock); + proc_lockDone(&p->lock); hal_spinlockDestroy(&p->spinlock); vm_kfree(p); } @@ -215,6 +254,9 @@ int proc_portCreate(u32 *id) port->kmessages = NULL; hal_spinlockCreate(&port->spinlock, "port.spinlock"); + lib_idtreeInit(&port->rid); + proc_lockInit(&port->lock, "port.rid"); + port->threads = NULL; port->current = NULL; port->refs = 1; diff --git a/proc/ports.h b/proc/ports.h index 1c2f37fb0..9d319eb1e 100644 --- a/proc/ports.h +++ b/proc/ports.h @@ -17,6 +17,7 @@ #define _PROC_PORT_H_ #include "../hal/hal.h" +#include "../lib/lib.h" #include "msg.h" #include "process.h" #include "threads.h" @@ -27,6 +28,8 @@ typedef struct _port_t { struct _port_t *next; struct _port_t *prev; + idtree_t rid; + u32 id; u32 lmaxgap; u32 rmaxgap; @@ -35,27 +38,34 @@ typedef struct _port_t { int refs, closed; spinlock_t spinlock; + lock_t lock; thread_t *threads; msg_t *current; } port_t; -extern int proc_portCreate(u32 *port); +int proc_portCreate(u32 *port); + + +void proc_portDestroy(u32 port); + + +void proc_portsDestroy(process_t *proc); -extern void proc_portDestroy(u32 port); +port_t *proc_portGet(u32 id); -extern void proc_portsDestroy(process_t *proc); +void port_put(port_t *p, int destroy); -extern port_t *proc_portGet(u32 id); +int proc_portRidAlloc(port_t *p, kmsg_t *kmsg); -extern void port_put(port_t *p, int destroy); +kmsg_t *proc_portRidGet(port_t *p, unsigned int rid); -extern void _port_init(void); +void _port_init(void); #endif diff --git a/syscalls.c b/syscalls.c index caa24fc4a..60d47075e 100644 --- a/syscalls.c +++ b/syscalls.c @@ -629,11 +629,11 @@ int syscalls_msgRecv(void *ustack) { u32 port; msg_t *msg; - unsigned long int *rid; + msg_rid_t *rid; GETFROMSTACK(ustack, u32, port, 0); GETFROMSTACK(ustack, msg_t *, msg, 1); - GETFROMSTACK(ustack, unsigned long int *, rid, 2); + GETFROMSTACK(ustack, msg_rid_t *, rid, 2); return proc_recv(port, msg, rid); } @@ -643,11 +643,11 @@ int syscalls_msgRespond(void *ustack) { u32 port; msg_t *msg; - unsigned long int rid; + msg_rid_t rid; GETFROMSTACK(ustack, u32, port, 0); GETFROMSTACK(ustack, msg_t *, msg, 1); - GETFROMSTACK(ustack, unsigned long int, rid, 2); + GETFROMSTACK(ustack, msg_rid_t, rid, 2); return proc_respond(port, msg, rid); } diff --git a/test/msg.c b/test/msg.c index 5d0ba6630..c3d57d497 100644 --- a/test/msg.c +++ b/test/msg.c @@ -127,7 +127,7 @@ void test_ping(void *arg) void test_pong(void *arg) { msg_t msg; - unsigned long rid; + msg_rid_t rid; unsigned int port = (long)arg; lib_printf("test_msg/pong: starting\n"); diff --git a/usrv.c b/usrv.c index c6efd9f1f..f5fc01444 100644 --- a/usrv.c +++ b/usrv.c @@ -83,7 +83,7 @@ static int usrv_oidGet(const msg_t *msg, oid_t *oid) static void usrv_msgthr(void *arg) { msg_t msg; - unsigned long int rid; + msg_rid_t rid; oid_t oid = usrv_common.oid; for (;;) {