Annotation of prex/sys/ipc/object.c, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005-2007, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * object.c - object service
32: */
33:
34: /*
35: * General Design:
36: *
37: * An object represents service, state, or policies etc. To
38: * manipulate objects, kernel provide 3 functions: create, delete,
39: * lookup. Prex task will create an object to provide its interface
40: * to other tasks. The tasks will communicate by sending a message
41: * to the object each other. For example, a server task creates some
42: * objects and client task will send a request message to it.
43: *
44: * A substance of object is stored in kernel space, and it is
45: * protected from user mode code. Each object data is managed with
46: * the hash table by using its name string. Usually, an object has
47: * a unique name within a system. Before a task sends a message to
48: * the specific object, it must obtain the object ID by looking up
49: * the name of the target object.
50: *
51: * An object can be created without its name. These object can be
52: * used as private objects that are used by threads in same task.
53: */
54:
55: #include <kernel.h>
56: #include <queue.h>
57: #include <kmem.h>
58: #include <sched.h>
59: #include <task.h>
60: #include <ipc.h>
61:
62: #define OBJ_MAXBUCKETS 32 /* Size of object hash buckets */
63:
64: /*
65: * Object hash table
66: *
67: * All objects are hashed by its name string. If an object
68: * has no name, it is linked to index zero. The scheduler
69: * must be locked when this table is touched.
70: */
71: static struct list obj_table[OBJ_MAXBUCKETS];
72:
73: /*
74: * Calculate the hash index for specified name string.
75: * The name can be NULL if the object does not have its
76: * name.
77: */
78: static u_int
79: object_hash(const char *name)
80: {
81: u_int h = 0;
82:
83: if (name == NULL)
84: return 0;
85: while (*name)
86: h = ((h << 5) + h) + *name++;
87: return h & (OBJ_MAXBUCKETS - 1);
88: }
89:
90: /*
91: * Helper function to find the object from the specified name.
92: * Returns NULL if not found.
93: */
94: static object_t
95: object_find(const char *name)
96: {
97: list_t head, n;
98: object_t obj = NULL;
99:
100: head = &obj_table[object_hash(name)];
101:
102: for (n = list_first(head); n != head; n = list_next(n)) {
103: obj = list_entry(n, struct object, hash_link);
104: if (!strncmp(obj->name, name, MAXOBJNAME))
105: break;
106: }
107: if (n == head)
108: return NULL;
109: return obj;
110: }
111:
112: /*
113: * Search an object in the object name space. The object
114: * name must be null-terminated string. The object ID is
115: * returned in obj on success.
116: */
117: int
118: object_lookup(const char *name, object_t *objp)
119: {
120: object_t obj;
121: size_t len;
122: char str[MAXOBJNAME];
123:
124: if (umem_strnlen(name, MAXOBJNAME, &len))
125: return EFAULT;
126: if (len == 0 || len >= MAXOBJNAME)
127: return ESRCH;
128: if (umem_copyin(name, str, len + 1))
129: return EFAULT;
130:
131: sched_lock();
132: obj = object_find(str);
133: sched_unlock();
134:
135: if (obj == NULL)
136: return ENOENT;
137: if (umem_copyout(&obj, objp, sizeof(object_t)))
138: return EFAULT;
139: return 0;
140: }
141:
142: /*
143: * Create a new object.
144: *
145: * The ID of the new object is stored in pobj on success.
146: * The name of the object must be unique in the system.
147: * Or, the object can be created without name by setting
148: * NULL as name argument. This object can be used as a
149: * private object which can be accessed only by threads in
150: * same task.
151: */
152: int
153: object_create(const char *name, object_t *objp)
154: {
155: object_t obj = 0;
156: char str[MAXOBJNAME];
157: task_t self;
158: size_t len = 0;
159:
160: if (name != NULL) {
161: if (umem_strnlen(name, MAXOBJNAME, &len))
162: return EFAULT;
163: if (len >= MAXOBJNAME)
164: return ENAMETOOLONG;
165: if (umem_copyin(name, str, len + 1))
166: return EFAULT;
167: }
168: str[len] = '\0';
169: sched_lock();
170:
171: /*
172: * Check user buffer first. This can reduce the error
173: * recovery for the subsequence resource allocations.
174: */
175: if (umem_copyout(&obj, objp, sizeof(object_t))) {
176: sched_unlock();
177: return EFAULT;
178: }
179: if (object_find(str) != NULL) {
180: sched_unlock();
181: return EEXIST;
182: }
183: if ((obj = kmem_alloc(sizeof(struct object))) == NULL) {
184: sched_unlock();
185: return ENOMEM;
186: }
187: if (name != NULL)
188: strlcpy(obj->name, str, len + 1);
189:
190: self = cur_task();
191: obj->owner = self;
192: obj->magic = OBJECT_MAGIC;
193: queue_init(&obj->sendq);
194: queue_init(&obj->recvq);
195: list_insert(&obj_table[object_hash(name)], &obj->hash_link);
196: list_insert(&self->objects, &obj->task_link);
197:
198: umem_copyout(&obj, objp, sizeof(object_t));
199: sched_unlock();
200: return 0;
201: }
202:
203: /*
204: * Destroy an object.
205: *
206: * A thread can delete the object only when the target
207: * object is created by the thread of the same task. All
208: * pending messages related to the deleted object are
209: * automatically canceled.
210: */
211: int
212: object_destroy(object_t obj)
213: {
214: int err = 0;
215:
216: sched_lock();
217: if (!object_valid(obj)) {
218: err = EINVAL;
219: } else if (obj->owner != cur_task()) {
220: err = EACCES;
221: } else {
222: obj->magic = 0;
223: msg_cancel(obj);
224: list_remove(&obj->task_link);
225: list_remove(&obj->hash_link);
226: kmem_free(obj);
227: }
228: sched_unlock();
229: return err;
230: }
231:
232: void
233: object_init(void)
234: {
235: int i;
236:
237: for (i = 0; i < OBJ_MAXBUCKETS; i++)
238: list_init(&obj_table[i]);
239: }
CVSweb