Added an extended ipc return library function.

This commit is contained in:
Bahadir Balban
2009-10-08 15:35:54 +03:00
parent cb561ab262
commit 72c6ca1ed0
9 changed files with 112 additions and 36 deletions

View File

@@ -110,6 +110,23 @@ static inline void l4_set_tag(unsigned int tag)
write_mr(MR_TAG, tag_flags);
}
/* Servers:
* Sets the message register for returning errors back to client task.
* These are usually posix error codes.
*/
static inline void l4_set_retval(int retval)
{
write_mr(MR_RETURN, retval);
}
/* Clients:
* Learn result of request.
*/
static inline int l4_get_retval(void)
{
return read_mr(MR_RETURN);
}
/*
* If we're about to do another ipc, this saves the last ipc's
* parameters such as the sender and tag information.
@@ -195,6 +212,39 @@ static inline int l4_receive_extended(l4id_t from, unsigned int size, void *buf)
return l4_ipc(L4_NILTHREAD, from, flags);
}
/*
* Return result value as extended IPC.
*
* Extended IPC copies up to 2KB user address space buffers.
* Along with such an ipc, a return value is sent using a primary
* mr that is used as the return register.
*
* It may not be desirable to return a payload on certain conditions,
* (such as an error return value) So a nopayload field is provided.
*/
static inline int l4_return_extended(int retval, unsigned int size,
void *buf, int nopayload)
{
unsigned int flags = 0;
l4id_t sender = l4_get_sender();
l4_set_retval(retval);
/* Set up flags word for extended ipc */
flags = l4_set_ipc_flags(flags, L4_IPC_FLAGS_EXTENDED);
flags = l4_set_ipc_msg_index(flags, L4SYS_ARG0);
/* Write buffer pointer to MR index that we specified */
write_mr(L4SYS_ARG0, (unsigned long)buf);
if (nopayload)
flags = l4_set_ipc_size(flags, 0);
else
flags = l4_set_ipc_size(flags, size);
return l4_ipc(sender, L4_NILTHREAD, flags);
}
static inline int l4_sendrecv_extended(l4id_t to, l4id_t from,
unsigned int tag, void *buf)
{
@@ -226,23 +276,6 @@ static inline int l4_receive(l4id_t from)
return l4_ipc(L4_NILTHREAD, from, 0);
}
/* Servers:
* Sets the message register for returning errors back to client task.
* These are usually posix error codes.
*/
static inline void l4_set_retval(int retval)
{
write_mr(MR_RETURN, retval);
}
/* Clients:
* Learn result of request.
*/
static inline int l4_get_retval(void)
{
return read_mr(MR_RETURN);
}
static inline void l4_print_mrs()
{
printf("Message registers: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
@@ -259,7 +292,7 @@ static inline int l4_ipc_return(int retval)
l4_set_retval(retval);
/* Setting the tag may overwrite retval so we l4_send without tagging */
/* Setting the tag would overwrite retval so we l4_send without tagging */
return l4_ipc(sender, L4_NILTHREAD, 0);
}

View File

@@ -24,8 +24,6 @@ static inline int l4_chdir(const char *pathname)
utcb_full_strcpy_from(pathname);
write_mr(L4SYS_ARG0, (unsigned long)utcb_full_buffer());
/* Call pager with shmget() request. Check ipc error. */
if ((fd = l4_sendrecv_full(VFS_TID, VFS_TID, L4_IPC_TAG_CHDIR)) < 0) {
print_err("%s: L4 IPC Error: %d.\n", __FUNCTION__, fd);

View File

@@ -26,8 +26,7 @@ static inline int l4_mkdir(const char *pathname, mode_t mode)
// write_mr(L4SYS_ARG0, (unsigned long)pathname);
utcb_full_strcpy_from(pathname);
write_mr(L4SYS_ARG0, (unsigned long)utcb_full_buffer());
write_mr(L4SYS_ARG1, (u32)mode);
write_mr(L4SYS_ARG0, (u32)mode);
/* Call pager with shmget() request. Check ipc error. */
if ((fd = l4_sendrecv_full(PAGER_TID, PAGER_TID, L4_IPC_TAG_MKDIR)) < 0) {

View File

@@ -15,7 +15,7 @@
#include <l4lib/os/posix/readdir.h>
#include <l4/macros.h>
#include INC_GLUE(memory.h)
#include <shpage.h>
#include INC_GLUE(message.h)
#include <libposix.h>
/*
@@ -29,6 +29,37 @@
* Or do it just like read()
*/
static inline int l4_readdir(int fd, void *buf, size_t count)
{
int cnt, err;
write_mr(L4SYS_ARG0, fd);
write_mr(L4SYS_ARG1, count);
/* Call pager with readdir() request. Check ipc error. */
if ((err = l4_send(PAGER_TID, L4_IPC_TAG_READDIR)) < 0) {
print_err("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
return err;
}
/* Call pager with readdir() request. Check ipc error. */
if ((err = l4_receive_extended(PAGER_TID,
L4_IPC_EXTENDED_MAX_SIZE,
buf)) < 0) {
print_err("%s: L4 Extended IPC error: %d.\n", __FUNCTION__, err);
return err;
}
/* Check if syscall itself was successful */
if ((cnt = l4_get_retval()) < 0) {
print_err("%s: READDIR Error: %d.\n", __FUNCTION__, (int)cnt);
return cnt;
}
return cnt;
}
#if 0
static inline int l4_readdir(int fd, void *buf, size_t count)
{
int cnt;
@@ -50,7 +81,7 @@ static inline int l4_readdir(int fd, void *buf, size_t count)
return cnt;
}
#endif
static inline int l4_read(int fd, void *buf, size_t count)
{
int cnt;

View File

@@ -38,7 +38,7 @@ void sys_exit(struct tcb *task, int status);
/* Posix calls */
int sys_open(struct tcb *sender, const char *pathname, int flags, u32 mode);
int sys_readdir(struct tcb *sender, int fd, void *buf, int count);
int sys_readdir(struct tcb *sender, int fd, int count, char *dirbuf);
int sys_mkdir(struct tcb *sender, const char *pathname, unsigned int mode);
int sys_chdir(struct tcb *sender, const char *pathname);

View File

@@ -148,26 +148,32 @@ void handle_requests(void)
ret = sys_execve(sender, (char *)mr[0],
(char **)mr[1], (char **)mr[2]);
if (ret < 0)
break; /* We origy for errors */
break; /* We reply for errors */
else
return; /* else we're done */
}
/* FIXME: Fix all these syscalls to read any buffer data from the caller task's utcb. */
/*
* FIXME: Fix all these syscalls to read any
* buffer data from the caller task's utcb.
*/
/* FS0 System calls */
case L4_IPC_TAG_OPEN:
ret = sys_open(sender, utcb_full_buffer(), (int)mr[0], (unsigned int)mr[1]);
break;
case L4_IPC_TAG_MKDIR:
ret = sys_mkdir(sender, (const char *)mr[0], (unsigned int)mr[1]);
ret = sys_mkdir(sender, utcb_full_buffer(), (unsigned int)mr[0]);
break;
case L4_IPC_TAG_CHDIR:
ret = sys_chdir(sender, (const char *)mr[0]);
ret = sys_chdir(sender, utcb_full_buffer());
break;
case L4_IPC_TAG_READDIR:
ret = sys_readdir(sender, (int)mr[0], (void *)mr[1], (int)mr[2]);
break;
case L4_IPC_TAG_READDIR: {
char dirbuf[L4_IPC_EXTENDED_MAX_SIZE];
ret = sys_readdir(sender, (int)mr[0], (int)mr[1], dirbuf);
l4_return_extended(ret, L4_IPC_EXTENDED_MAX_SIZE, dirbuf, ret < 0);
return;
}
default:
printf("%s: Unrecognised ipc tag (%d) "
"received from (%d). Full mr reading: "

View File

@@ -31,6 +31,8 @@
#include <path.h>
#include <syscalls.h>
#include INC_GLUE(message.h)
/* Copy from one page's buffer into another page */
int page_copy(struct page *dst, struct page *src,
unsigned long dst_offset, unsigned long src_offset,
@@ -1173,17 +1175,22 @@ int fill_dirent(void *buf, unsigned long vnum, int offset, char *name)
*
* FIXME: Ensure buf is in shared utcb, and count does not exceed it.
*/
int sys_readdir(struct tcb *t, int fd, void *buf, int count)
int sys_readdir(struct tcb *t, int fd, int count, char *dirbuf)
{
int dirent_size = sizeof(struct dirent);
int total = 0, nbytes = 0;
unsigned long vnum;
struct vnode *v;
struct dentry *d;
char *buf = dirbuf;
// printf("%s/%s\n", __TASKNAME__, __FUNCTION__);
BUG(); /* Do this by extended ipc !!! */
/*
* FIXME:
* Add dirbuf overflow checking
*/
/* Check address is in task's utcb */
if (fd < 0 || fd > TASK_FILES_MAX || !t->files->fd[fd].vnum)

View File

@@ -85,7 +85,7 @@
#define L4_IPC_EXTENDED_MAX_SIZE (SZ_1K*2)
/* Primaries aren't used for memcopy. Those ops use this as a parameter */
#define L4_UTCB_FULL_BUFFER_SIZE (MR_REST * sizeof(int))
#define L4_UTCB_FULL_BUFFER_SIZE (MR_REST * sizeof(int))
#include INC_GLUE(memlayout.h)

View File

@@ -131,6 +131,8 @@ int ipc_msg_copy(struct ktcb *to, struct ktcb *from)
break;
case IPC_FLAGS_EXTENDED:
if (send_ipc_type == IPC_FLAGS_EXTENDED)
/* We do a short copy as well. */
ret = ipc_short_copy(to, from);
ret = ipc_extended_copy(to, from);
if (send_ipc_type == IPC_FLAGS_SHORT)
ret = -ENOIPC;