add support for crt{i,n} - required for powerpc EABI
[prex.git] / sys / ipc / object.c
blob1090d563459ea8629110841d54cc8961f23f297c
1 /*-
2 * Copyright (c) 2005-2007, Kohsuke Ohtani
3 * All rights reserved.
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.
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.
31 * object.c - object service
35 * An object represents service, state, or policies etc. To manipulate
36 * objects, kernel provide 3 functions: create, delete, lookup.
37 * Prex task will create an object to provide its interface to other tasks.
38 * The tasks will communicate by sending a message to the object each other.
39 * For example, a server task creates some objects and client task will send
40 * a request message to it.
42 * A substance of object is stored in kernel space, and it is protected
43 * from user mode code. Each object data is managed with the hash table
44 * by using its name string. Usually, an object has a unique name within
45 * a system. Before a task sends a message to the specific object, it must
46 * obtain the object ID by looking up the name of the target object.
48 * An object can be created without its name. These object can be used as
49 * private objects that are used by threads in same task.
52 #include <kernel.h>
53 #include <queue.h>
54 #include <list.h>
55 #include <kmem.h>
56 #include <sched.h>
57 #include <task.h>
58 #include <ipc.h>
60 #define OBJ_MAXBUCKETS 64 /* Size of object hash buckets */
63 * Object hash table
65 * All objects are hashed by its name string. If an object has no
66 * name, it is linked to index zero.
67 * The scheduler must be locked when this table is modified.
69 static struct list obj_table[OBJ_MAXBUCKETS];
72 * Calculate the hash index for specified name string.
73 * The name can be NULL if the object does not have name.
75 static u_int object_hash(const char *name)
77 u_int h = 0;
79 if (name == NULL)
80 return 0;
81 while (*name)
82 h = ((h << 5) + h) + *name++;
83 return h & (OBJ_MAXBUCKETS - 1);
87 * Find an object from the specified name.
89 static object_t object_find(char *name)
91 list_t head, n;
92 object_t obj = NULL;
94 head = &obj_table[object_hash(name)];
95 for (n = list_first(head); n != head; n = list_next(n)) {
96 obj = list_entry(n, struct object, name_link);
97 ASSERT(obj->magic == OBJECT_MAGIC);
98 if (!strncmp(obj->name, name, MAX_OBJNAME))
99 break;
101 if (n == head)
102 return NULL;
103 return obj;
107 * Search an object in the object name space. The object name must
108 * be null-terminated string. The object ID is returned in obj on
109 * success.
111 __syscall int object_lookup(char *name, object_t *pobj)
113 object_t obj;
114 size_t len;
115 char str[MAX_OBJNAME];
117 if (umem_strnlen(name, MAX_OBJNAME, &len))
118 return EFAULT;
119 if (len == 0 || len >= MAX_OBJNAME)
120 return ESRCH;
121 if (umem_copyin(name, str, len + 1))
122 return EFAULT;
124 sched_lock();
125 obj = object_find(str);
126 sched_unlock();
127 if (obj == NULL)
128 return ENOENT;
129 if (umem_copyout(&obj, pobj, sizeof(object_t)))
130 return EFAULT;
131 return 0;
135 * Create a new object.
137 * The ID of the new object is stored in obj on success.
138 * The name of the object must be unique in the system. Or, the
139 * object can be created without name by setting NULL as name
140 * argument. This object can be used as a private object which
141 * can be accessed only by threads in same task.
143 __syscall int object_create(char *name, object_t *pobj)
145 object_t obj = 0;
146 char str[MAX_OBJNAME];
147 size_t len;
149 if (name != NULL) {
150 if (umem_strnlen(name, MAX_OBJNAME, &len))
151 return EFAULT;
152 if (len >= MAX_OBJNAME)
153 return ENAMETOOLONG;
154 if (umem_copyin(name, str, len + 1))
155 return EFAULT;
156 str[len] = '\0';
158 sched_lock();
161 * Check user buffer first. This can reduce the error
162 * recovery for the following resource allocations.
164 if (umem_copyout(&obj, pobj, sizeof(object_t))) {
165 sched_unlock();
166 return EFAULT;
168 if ((obj = object_find(str)) != NULL) {
169 sched_unlock();
170 return EEXIST;
172 if ((obj = kmem_alloc(sizeof(struct object))) == NULL) {
173 sched_unlock();
174 return ENOMEM;
176 if (name != NULL) {
177 obj->name = kmem_alloc(len + 1);
178 if (obj->name == NULL) {
179 kmem_free(obj);
180 sched_unlock();
181 return ENOMEM;
183 strlcpy(obj->name, str, len + 1);
185 queue_init(&obj->sendq);
186 queue_init(&obj->recvq);
187 obj->owner = cur_task();
188 obj->magic = OBJECT_MAGIC;
189 list_insert(&obj_table[object_hash(name)], &obj->name_link);
190 list_insert(&(cur_task()->objects), &obj->task_link);
192 umem_copyout(&obj, pobj, sizeof(object_t));
193 sched_unlock();
194 return 0;
198 * Delete an object.
200 * A thread can delete the object only when the target object is created
201 * by the thread of the same task. All pending messages related to the
202 * deleted object are automatically canceled.
204 __syscall int object_delete(object_t obj)
206 sched_lock();
207 if (!object_valid(obj)) {
208 sched_unlock();
209 return EINVAL;
211 if (obj->owner != cur_task()) {
212 sched_unlock();
213 return EACCES;
215 obj->magic = 0;
216 msg_cancel(obj);
218 list_remove(&obj->task_link);
219 list_remove(&obj->name_link);
220 if (obj->name != NULL)
221 kmem_free(obj->name);
222 kmem_free(obj);
223 sched_unlock();
224 return 0;
227 #if defined(DEBUG) && defined(CONFIG_KDUMP)
228 void object_dump(void)
230 int i;
231 list_t head, n;
232 object_t obj;
234 printk("Object dump:\n");
235 printk(" object owner task name\n");
236 printk(" -------- ---------- ----------------\n");
238 for (i = 0; i < OBJ_MAXBUCKETS; i++) {
239 head = &obj_table[i];
240 for (n = list_first(head); n != head; n = list_next(n)) {
241 obj = list_entry(n, struct object, name_link);
242 printk(" %08x %08x %s\n", obj, obj->owner,
243 (obj->name ? obj->name : "NoName"));
247 #endif
249 void object_init(void)
251 int i;
253 /* Initialize object lookup table */
254 for (i = 0; i < OBJ_MAXBUCKETS; i++)
255 list_init(&obj_table[i]);