version 1.1.1.1, 2008/06/03 10:38:46 |
version 1.1.1.1.2.1, 2008/08/13 17:12:31 |
|
|
*/ |
*/ |
|
|
/* |
/* |
* An object represents service, state, or policies etc. To manipulate |
* General Design: |
* 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 |
* An object represents service, state, or policies etc. To |
* from user mode code. Each object data is managed with the hash table |
* manipulate objects, kernel provide 3 functions: create, delete, |
* by using its name string. Usually, an object has a unique name within |
* lookup. Prex task will create an object to provide its interface |
* a system. Before a task sends a message to the specific object, it must |
* to other tasks. The tasks will communicate by sending a message |
* obtain the object ID by looking up the name of the target object. |
* to the object each other. For example, a server task creates some |
|
* objects and client task will send a request message to it. |
* |
* |
* An object can be created without its name. These object can be used as |
* A substance of object is stored in kernel space, and it is |
* private objects that are used by threads in same task. |
* 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 <kernel.h> |
|
|
/* |
/* |
* Object hash table |
* Object hash table |
* |
* |
* All objects are hashed by its name string. If an object has no |
* All objects are hashed by its name string. If an object |
* name, it is linked to index zero. |
* has no name, it is linked to index zero. The scheduler |
* The scheduler must be locked when this table is touched. |
* must be locked when this table is touched. |
*/ |
*/ |
static struct list obj_table[OBJ_MAXBUCKETS]; |
static struct list obj_table[OBJ_MAXBUCKETS]; |
|
|
/* |
/* |
* Calculate the hash index for specified name string. |
* Calculate the hash index for specified name string. |
* The name can be NULL if the object does not have name. |
* The name can be NULL if the object does not have its |
|
* name. |
*/ |
*/ |
static u_int |
static u_int |
object_hash(const char *name) |
object_hash(const char *name) |
|
|
object_t obj = NULL; |
object_t obj = NULL; |
|
|
head = &obj_table[object_hash(name)]; |
head = &obj_table[object_hash(name)]; |
|
|
for (n = list_first(head); n != head; n = list_next(n)) { |
for (n = list_first(head); n != head; n = list_next(n)) { |
obj = list_entry(n, struct object, name_link); |
obj = list_entry(n, struct object, hash_link); |
ASSERT(obj->magic == OBJECT_MAGIC); |
|
if (!strncmp(obj->name, name, MAXOBJNAME)) |
if (!strncmp(obj->name, name, MAXOBJNAME)) |
break; |
break; |
} |
} |
|
|
} |
} |
|
|
/* |
/* |
* Search an object in the object name space. The object name must |
* Search an object in the object name space. The object |
* be null-terminated string. The object ID is returned in obj |
* name must be null-terminated string. The object ID is |
* on success. |
* returned in obj on success. |
*/ |
*/ |
int |
int |
object_lookup(const char *name, object_t *objp) |
object_lookup(const char *name, object_t *objp) |
|
|
return EFAULT; |
return EFAULT; |
if (len == 0 || len >= MAXOBJNAME) |
if (len == 0 || len >= MAXOBJNAME) |
return ESRCH; |
return ESRCH; |
if (umem_copyin((void *)name, str, len + 1)) |
if (umem_copyin(name, str, len + 1)) |
return EFAULT; |
return EFAULT; |
|
|
sched_lock(); |
sched_lock(); |
|
|
* Create a new object. |
* Create a new object. |
* |
* |
* The ID of the new object is stored in pobj on success. |
* 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 |
* The name of the object must be unique in the system. |
* object can be created without name by setting NULL as name |
* Or, the object can be created without name by setting |
* argument. This object can be used as a private object which |
* NULL as name argument. This object can be used as a |
* can be accessed only by threads in same task. |
* private object which can be accessed only by threads in |
|
* same task. |
*/ |
*/ |
int |
int |
object_create(const char *name, object_t *objp) |
object_create(const char *name, object_t *objp) |
{ |
{ |
object_t obj = 0; |
object_t obj = 0; |
char str[MAXOBJNAME]; |
char str[MAXOBJNAME]; |
size_t len; |
task_t self; |
|
size_t len = 0; |
|
|
if (name != NULL) { |
if (name != NULL) { |
if (umem_strnlen(name, MAXOBJNAME, &len)) |
if (umem_strnlen(name, MAXOBJNAME, &len)) |
return EFAULT; |
return EFAULT; |
if (len >= MAXOBJNAME) |
if (len >= MAXOBJNAME) |
return ENAMETOOLONG; |
return ENAMETOOLONG; |
if (umem_copyin((void *)name, str, len + 1)) |
if (umem_copyin(name, str, len + 1)) |
return EFAULT; |
return EFAULT; |
str[len] = '\0'; |
|
} |
} |
|
str[len] = '\0'; |
sched_lock(); |
sched_lock(); |
|
|
/* |
/* |
|
|
if (name != NULL) |
if (name != NULL) |
strlcpy(obj->name, str, len + 1); |
strlcpy(obj->name, str, len + 1); |
|
|
|
self = cur_task(); |
|
obj->owner = self; |
|
obj->magic = OBJECT_MAGIC; |
queue_init(&obj->sendq); |
queue_init(&obj->sendq); |
queue_init(&obj->recvq); |
queue_init(&obj->recvq); |
obj->owner = cur_task(); |
list_insert(&obj_table[object_hash(name)], &obj->hash_link); |
obj->magic = OBJECT_MAGIC; |
list_insert(&self->objects, &obj->task_link); |
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)); |
umem_copyout(&obj, objp, sizeof(object_t)); |
sched_unlock(); |
sched_unlock(); |
|
|
/* |
/* |
* Destroy an object. |
* Destroy an object. |
* |
* |
* A thread can delete the object only when the target object is |
* A thread can delete the object only when the target |
* created by the thread of the same task. |
* object is created by the thread of the same task. All |
* All pending messages related to the deleted object are |
* pending messages related to the deleted object are |
* automatically canceled. |
* automatically canceled. |
*/ |
*/ |
int |
int |
|
|
sched_lock(); |
sched_lock(); |
if (!object_valid(obj)) { |
if (!object_valid(obj)) { |
err = EINVAL; |
err = EINVAL; |
} |
} else if (obj->owner != cur_task()) { |
else if (obj->owner != cur_task()) { |
|
err = EACCES; |
err = EACCES; |
} |
} else { |
else { |
|
obj->magic = 0; |
obj->magic = 0; |
msg_cancel(obj); |
msg_cancel(obj); |
list_remove(&obj->task_link); |
list_remove(&obj->task_link); |
list_remove(&obj->name_link); |
list_remove(&obj->hash_link); |
kmem_free(obj); |
kmem_free(obj); |
} |
} |
sched_unlock(); |
sched_unlock(); |
return err; |
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 |
void |
object_init(void) |
object_init(void) |