84 |
return kr; |
return kr; |
85 |
} |
} |
86 |
|
|
87 |
|
/* Obtain reference to PORT. */ |
88 |
|
void |
89 |
|
ipc_port_reference (struct ipc_port *port) |
90 |
|
{ |
91 |
|
thread_lock_write (&port->lock); |
92 |
|
port->ref_count++; |
93 |
|
thread_lock_unlock (&port->lock); |
94 |
|
} |
95 |
|
|
96 |
|
/* Release reference to PORT. If reference counter drops to |
97 |
|
zero, release all port and all it's resources. */ |
98 |
|
void |
99 |
|
ipc_port_release (struct ipc_port *port) |
100 |
|
{ |
101 |
|
int free_p; |
102 |
|
|
103 |
|
thread_lock_write (&port->lock); |
104 |
|
free_p = --port->ref_count == 0; |
105 |
|
thread_lock_unlock (&port->lock); |
106 |
|
|
107 |
|
if (! free_p) |
108 |
|
return; |
109 |
|
trace_printf ("implement"); |
110 |
|
} |
111 |
|
|
112 |
/* Allocate a new port. Receive rights are returned in PORTP. */ |
/* Allocate a new port. Receive rights are returned in PORTP. */ |
113 |
kern_return_t |
kern_return_t |
114 |
port_allocate (struct task *task, rtmk_port_t *portp) |
port_allocate (struct task *task, rtmk_port_t *portp) |
220 |
return kr; |
return kr; |
221 |
} |
} |
222 |
assert (entry && entry->ie_port); |
assert (entry && entry->ie_port); |
223 |
|
|
224 |
|
thread_lock_write (& entry->ie_port->lock); |
225 |
entry->ie_port->active_p = 0; |
entry->ie_port->active_p = 0; |
226 |
|
thread_lock_unlock (& entry->ie_port->lock); |
227 |
ipc_object_unlock (task->ipc_object); |
ipc_object_unlock (task->ipc_object); |
228 |
|
|
229 |
|
ipc_port_release (entry->ie_port); |
230 |
|
|
231 |
kmem_cache_free (ipc_entry_cache, entry); |
kmem_cache_free (ipc_entry_cache, entry); |
232 |
return KERN_SUCCESS; |
return KERN_SUCCESS; |
233 |
} |
} |
266 |
return port_destroy (task, a->name); |
return port_destroy (task, a->name); |
267 |
} |
} |
268 |
|
|
269 |
|
/* Deallocate user reference to right NAME. If reference counter |
270 |
|
drops to zero, we destroy the right and release reference to port. */ |
271 |
|
kern_return_t |
272 |
|
port_deallocate (struct task *task, rtmk_port_name_t name) |
273 |
|
{ |
274 |
|
struct ipc_entry *entry; |
275 |
|
kern_return_t kr; |
276 |
|
int dealloc_p; |
277 |
|
|
278 |
|
ipc_object_lock (task->ipc_object); |
279 |
|
kr = ipc_object_lookup (task->ipc_object, name, &entry); |
280 |
|
if (kr != KERN_SUCCESS) |
281 |
|
{ |
282 |
|
ipc_object_unlock (task->ipc_object); |
283 |
|
return kr; |
284 |
|
} |
285 |
|
|
286 |
|
thread_lock_write (&entry->ie_port->lock); |
287 |
|
switch (IE_BITS_RIGHTS (entry->ie_bits)) |
288 |
|
{ |
289 |
|
case RTMK_PORT_TYPE_SEND | RTMK_PORT_TYPE_RECEIVE: |
290 |
|
case RTMK_PORT_TYPE_SEND: |
291 |
|
--entry->ie_port->srights; |
292 |
|
break; |
293 |
|
|
294 |
|
case RTMK_PORT_TYPE_SEND_ONCE | RTMK_PORT_TYPE_RECEIVE: |
295 |
|
case RTMK_PORT_TYPE_SEND_ONCE: |
296 |
|
--entry->ie_port->sorights; |
297 |
|
break; |
298 |
|
|
299 |
|
case RTMK_PORT_TYPE_RECEIVE: |
300 |
|
thread_lock_unlock (&entry->ie_port->lock); |
301 |
|
ipc_object_unlock (task->ipc_object); |
302 |
|
return KERN_FAILURE; /* ??? what about this one? */ |
303 |
|
break; |
304 |
|
|
305 |
|
default: |
306 |
|
trace_printf ("unknown right: %d", IE_BITS_RIGHTS (entry->ie_bits)); |
307 |
|
break; |
308 |
|
} |
309 |
|
thread_lock_unlock (&entry->ie_port->lock); |
310 |
|
|
311 |
|
/* Release user reference to right. If user reference counter |
312 |
|
drops to zero we destroy the right, right here, right now. */ |
313 |
|
dealloc_p = --entry->ie_urefs == 0; |
314 |
|
if (dealloc_p) |
315 |
|
{ |
316 |
|
struct ipc_entry *tabled; |
317 |
|
|
318 |
|
kr = ipc_object_remove (task->ipc_object, & tabled, name); |
319 |
|
if (kr != KERN_SUCCESS) |
320 |
|
{ |
321 |
|
ipc_object_unlock (task->ipc_object); |
322 |
|
return kr; |
323 |
|
} |
324 |
|
|
325 |
|
ipc_port_release (entry->ie_port); |
326 |
|
} |
327 |
|
ipc_object_unlock (task->ipc_object); |
328 |
|
return KERN_SUCCESS; |
329 |
|
} |
330 |
|
|
331 |
|
/* Syscall version of function above. */ |
332 |
|
struct port_deallocate_args |
333 |
|
{ |
334 |
|
rtmk_port_t task_name; |
335 |
|
rtmk_port_name_t name; |
336 |
|
}; |
337 |
|
|
338 |
|
kern_return_t |
339 |
|
syscall_port_deallocate (struct port_deallocate_args *a) |
340 |
|
{ |
341 |
|
struct ipc_entry *entry; |
342 |
|
struct task *task; |
343 |
|
kern_return_t kr; |
344 |
|
|
345 |
|
ipc_object_lock (THREAD_CURRENT()->task->ipc_object); |
346 |
|
kr = ipc_object_lookup (THREAD_CURRENT()->task->ipc_object, a->task_name, |
347 |
|
&entry); |
348 |
|
if (kr != KERN_SUCCESS) |
349 |
|
{ |
350 |
|
ipc_object_unlock (THREAD_CURRENT()->task->ipc_object); |
351 |
|
return kr; |
352 |
|
} |
353 |
|
|
354 |
|
if (entry->ie_port->kobject.type != IPC_KOBJECT_TYPE_TASK) |
355 |
|
{ |
356 |
|
ipc_object_unlock (THREAD_CURRENT()->task->ipc_object); |
357 |
|
return KERN_INVALID_TASK; |
358 |
|
} |
359 |
|
task = (struct task *) entry->ie_port->kobject.port; |
360 |
|
ipc_object_unlock (THREAD_CURRENT()->task->ipc_object); |
361 |
|
|
362 |
|
return port_deallocate (task, a->name); |
363 |
|
} |
364 |
|
|
365 |
/* Create a new kernel port. This port have not message queue since |
/* Create a new kernel port. This port have not message queue since |
366 |
all messages sent to it will be demuxed by the kernel demuxer. */ |
all messages sent to it will be demuxed by the kernel demuxer. */ |
|
|
|
367 |
struct ipc_port * |
struct ipc_port * |
368 |
ipc_port_create_kernel (void) |
ipc_port_create_kernel (void) |
369 |
{ |
{ |
382 |
} |
} |
383 |
|
|
384 |
/* Set kernel object for PORT to OBJECT. TYPE is type of kernel object. */ |
/* Set kernel object for PORT to OBJECT. TYPE is type of kernel object. */ |
|
|
|
385 |
void |
void |
386 |
ipc_port_set_kobject (struct ipc_port *port, enum ipc_kobject_type type, |
ipc_port_set_kobject (struct ipc_port *port, enum ipc_kobject_type type, |
387 |
void *object) |
void *object) |