File: [local] / prex-old / sys / ipc / object.c (download)
Revision 1.1.1.1 (vendor branch), Tue Jun 3 09:38:46 2008 UTC (16 years, 2 months ago) by nbrk
Branch: MAIN, KOHSUKE
CVS Tags: PREX_0_7_BASE, HEAD Branch point for: PREX_0_8_BASE
Changes since 1.1: +0 -0 lines
Yeah, this is an initial import of Prex, portable real-time microkernel
operating system. I wanna hack it for non-profit but fun, so let it in.
|
/*-
* Copyright (c) 2005-2007, Kohsuke Ohtani
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* object.c - object service
*/
/*
* An object represents service, state, or policies etc. To manipulate
* objects, kernel provide 3 functions: create, delete, lookup.
* Prex task will create an object to provide its interface to other
* tasks. The tasks will communicate by sending a message to the object
* each other. For example, a server task creates some objects and client
* task will send a request message to it.
*
* A substance of object is stored in kernel space, and it is protected
* from user mode code. Each object data is managed with the hash table
* by using its name string. Usually, an object has a unique name within
* a system. Before a task sends a message to the specific object, it must
* obtain the object ID by looking up the name of the target object.
*
* An object can be created without its name. These object can be used as
* private objects that are used by threads in same task.
*/
#include <kernel.h>
#include <queue.h>
#include <kmem.h>
#include <sched.h>
#include <task.h>
#include <ipc.h>
#define OBJ_MAXBUCKETS 32 /* Size of object hash buckets */
/*
* Object hash table
*
* All objects are hashed by its name string. If an object has no
* name, it is linked to index zero.
* The scheduler must be locked when this table is touched.
*/
static struct list obj_table[OBJ_MAXBUCKETS];
/*
* Calculate the hash index for specified name string.
* The name can be NULL if the object does not have name.
*/
static u_int
object_hash(const char *name)
{
u_int h = 0;
if (name == NULL)
return 0;
while (*name)
h = ((h << 5) + h) + *name++;
return h & (OBJ_MAXBUCKETS - 1);
}
/*
* Helper function to find the object from the specified name.
* Returns NULL if not found.
*/
static object_t
object_find(const char *name)
{
list_t head, n;
object_t obj = NULL;
head = &obj_table[object_hash(name)];
for (n = list_first(head); n != head; n = list_next(n)) {
obj = list_entry(n, struct object, name_link);
ASSERT(obj->magic == OBJECT_MAGIC);
if (!strncmp(obj->name, name, MAXOBJNAME))
break;
}
if (n == head)
return NULL;
return obj;
}
/*
* Search an object in the object name space. The object name must
* be null-terminated string. The object ID is returned in obj
* on success.
*/
int
object_lookup(const char *name, object_t *objp)
{
object_t obj;
size_t len;
char str[MAXOBJNAME];
if (umem_strnlen(name, MAXOBJNAME, &len))
return EFAULT;
if (len == 0 || len >= MAXOBJNAME)
return ESRCH;
if (umem_copyin((void *)name, str, len + 1))
return EFAULT;
sched_lock();
obj = object_find(str);
sched_unlock();
if (obj == NULL)
return ENOENT;
if (umem_copyout(&obj, objp, sizeof(object_t)))
return EFAULT;
return 0;
}
/*
* Create a new object.
*
* The ID of the new object is stored in pobj on success.
* The name of the object must be unique in the system. Or, the
* object can be created without name by setting NULL as name
* argument. This object can be used as a private object which
* can be accessed only by threads in same task.
*/
int
object_create(const char *name, object_t *objp)
{
object_t obj = 0;
char str[MAXOBJNAME];
size_t len;
if (name != NULL) {
if (umem_strnlen(name, MAXOBJNAME, &len))
return EFAULT;
if (len >= MAXOBJNAME)
return ENAMETOOLONG;
if (umem_copyin((void *)name, str, len + 1))
return EFAULT;
str[len] = '\0';
}
sched_lock();
/*
* Check user buffer first. This can reduce the error
* recovery for the subsequence resource allocations.
*/
if (umem_copyout(&obj, objp, sizeof(object_t))) {
sched_unlock();
return EFAULT;
}
if (object_find(str) != NULL) {
sched_unlock();
return EEXIST;
}
if ((obj = kmem_alloc(sizeof(struct object))) == NULL) {
sched_unlock();
return ENOMEM;
}
if (name != NULL)
strlcpy(obj->name, str, len + 1);
queue_init(&obj->sendq);
queue_init(&obj->recvq);
obj->owner = cur_task();
obj->magic = OBJECT_MAGIC;
list_insert(&obj_table[object_hash(name)], &obj->name_link);
list_insert(&(cur_task()->objects), &obj->task_link);
umem_copyout(&obj, objp, sizeof(object_t));
sched_unlock();
return 0;
}
/*
* Destroy an object.
*
* A thread can delete the object only when the target object is
* created by the thread of the same task.
* All pending messages related to the deleted object are
* automatically canceled.
*/
int
object_destroy(object_t obj)
{
int err = 0;
sched_lock();
if (!object_valid(obj)) {
err = EINVAL;
}
else if (obj->owner != cur_task()) {
err = EACCES;
}
else {
obj->magic = 0;
msg_cancel(obj);
list_remove(&obj->task_link);
list_remove(&obj->name_link);
kmem_free(obj);
}
sched_unlock();
return err;
}
#if defined(DEBUG) && defined(CONFIG_KDUMP)
void
object_dump(void)
{
int i;
list_t head, n;
object_t obj;
printk("Object dump:\n");
printk(" object owner task name\n");
printk(" -------- ---------- ----------------\n");
for (i = 0; i < OBJ_MAXBUCKETS; i++) {
head = &obj_table[i];
for (n = list_first(head); n != head; n = list_next(n)) {
obj = list_entry(n, struct object, name_link);
printk(" %08x %08x %s\n", obj, obj->owner,
(obj->name ? obj->name : "NoName"));
}
}
}
#endif
void
object_init(void)
{
int i;
for (i = 0; i < OBJ_MAXBUCKETS; i++)
list_init(&obj_table[i]);
}