Project

General

Profile

Statistics
| Branch: | Revision:

root / prex-0.9.0 / sys / ipc / object.c @ 03e9c04a

History | View | Annotate | Download (6.19 KB)

1
/*-
2
 * Copyright (c) 2005-2008, 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
 * IPC object:
36
 *
37
 * An object represents service, state, or policies etc. To manipulate
38
 * objects, kernel provide 3 functions: create, destroy and lookup.
39
 * Prex task will create an object to provide its services to other
40
 * tasks. The tasks will communicate by sending a message to the
41
 * object each other. In typical case, a server task creates an object
42
 * and client tasks will send a request message to it.
43
 *
44
 * A substance of object is stored in kernel space, and so it's protected
45
 * from user mode code.  Usually, an object has a unique name within a
46
 * system. Before a task sends a message to the specific object, it must
47
 * obtain the object ID by looking up the name of the target object.
48
 *
49
 * A task can create a private object which does not have name. Since
50
 * another task can not obtain the ID of such object, the IPC operations
51
 * for the private object are limited to the threads in the same task.
52
 *
53
 * The object name started with '!' means that it is a protected object.
54
 * The protected object can be created only by the task which has
55
 * CAP_PROTSERV capability. Since this capability is given to the known
56
 * system servers, the client task can always trust the object owner.
57
 */
58

    
59
#include <kernel.h>
60
#include <kmem.h>
61
#include <sched.h>
62
#include <task.h>
63
#include <ipc.h>
64

    
65
/* forward declarations */
66
static object_t        object_find(const char *);
67

    
68
static struct list        object_list;        /* list of all objects */
69

    
70
/*
71
 * Create a new object.
72
 *
73
 * The ID of the new object is stored in objp on success.
74
 * The name of the object must be unique in the system.
75
 * Or, the object can be created without name by setting
76
 * NULL as name argument. This object can be used as a
77
 * private object which can be accessed only by threads in
78
 * same task.
79
 */
80
int
81
object_create(const char *name, object_t *objp)
82
{
83
        struct object *obj = 0;
84
        char str[MAXOBJNAME];
85
        int error;
86

    
87
        if (name == NULL)
88
                str[0] = '\0';
89
        else {
90
                error = copyinstr(name, str, MAXOBJNAME);
91
                if (error)
92
                        return error;
93

    
94
                /* Check capability if name is protected object. */
95
                if (name[0] == '!' && !task_capable(CAP_PROTSERV))
96
                        return EPERM;
97
        }
98
        sched_lock();
99

    
100
        if (curtask->nobjects >= MAXOBJECTS) {
101
                sched_unlock();
102
                return EAGAIN;
103
        }
104
        /*
105
         * Check user buffer first. This can reduce the error
106
         * recovery for the subsequence resource allocations.
107
         */
108
        if (copyout(&obj, objp, sizeof(obj))) {
109
                sched_unlock();
110
                return EFAULT;
111
        }
112
        if (object_find(str) != NULL) {
113
                sched_unlock();
114
                return EEXIST;
115
        }
116
        if ((obj = kmem_alloc(sizeof(*obj))) == NULL) {
117
                sched_unlock();
118
                return ENOMEM;
119
        }
120
        if (name != NULL)
121
                strlcpy(obj->name, str, MAXOBJNAME);
122

    
123
        obj->owner = curtask;
124
        queue_init(&obj->sendq);
125
        queue_init(&obj->recvq);
126
        list_insert(&curtask->objects, &obj->task_link);
127
        curtask->nobjects++;
128
        list_insert(&object_list, &obj->link);
129
        copyout(&obj, objp, sizeof(obj));
130

    
131
        sched_unlock();
132
        return 0;
133
}
134

    
135
/*
136
 * Search an object in the object name space. The object
137
 * name must be null-terminated string.
138
 */
139
int
140
object_lookup(const char *name, object_t *objp)
141
{
142
        object_t obj;
143
        char str[MAXOBJNAME];
144
        int error;
145

    
146
        error = copyinstr(name, str, MAXOBJNAME);
147
        if (error)
148
                return error;
149

    
150
        sched_lock();
151
        obj = object_find(str);
152
        sched_unlock();
153

    
154
        if (obj == NULL)
155
                return ENOENT;
156

    
157
        if (copyout(&obj, objp, sizeof(obj)))
158
                return EFAULT;
159
        return 0;
160
}
161

    
162
int
163
object_valid(object_t obj)
164
{
165
        object_t tmp;
166
        list_t n;
167

    
168
        for (n = list_first(&object_list); n != &object_list;
169
             n = list_next(n)) {
170
                tmp = list_entry(n, struct object, link);
171
                if (tmp == obj)
172
                        return 1;
173
        }
174
        return 0;
175
}
176

    
177
static object_t
178
object_find(const char *name)
179
{
180
        object_t obj;
181
        list_t n;
182

    
183
        for (n = list_first(&object_list); n != &object_list;
184
             n = list_next(n)) {
185
                obj = list_entry(n, struct object, link);
186
                if (!strncmp(obj->name, name, MAXOBJNAME))
187
                        return obj;
188
        }
189
        return 0;
190
}
191

    
192
/*
193
 * Deallocate an object-- the internal version of object_destory.
194
 */
195
static void
196
object_deallocate(object_t obj)
197
{
198

    
199
        msg_abort(obj);
200
        obj->owner->nobjects--;
201
        list_remove(&obj->task_link);
202
        list_remove(&obj->link);
203
        kmem_free(obj);
204
}
205

    
206
/*
207
 * Destroy an object.
208
 *
209
 * All pending messages related to the target object are
210
 * automatically cancelled.
211
 */
212
int
213
object_destroy(object_t obj)
214
{
215

    
216
        sched_lock();
217
        if (!object_valid(obj)) {
218
                sched_unlock();
219
                return EINVAL;
220
        }
221
        if (obj->owner != curtask) {
222
                sched_unlock();
223
                return EACCES;
224
        }
225
        object_deallocate(obj);
226
        sched_unlock();
227
        return 0;
228
}
229

    
230
/*
231
 * Clean up for task termination.
232
 */
233
void
234
object_cleanup(task_t task)
235
{
236
        object_t obj;
237

    
238
        while (!list_empty(&task->objects)) {
239
                obj = list_entry(list_first(&task->objects),
240
                                 struct object, task_link);
241
                object_deallocate(obj);
242
        }
243
}
244

    
245
void
246
object_init(void)
247
{
248

    
249
        list_init(&object_list);
250
}