1 /* $NetBSD: mach_port.c,v 1.65 2008/04/28 20:23:44 martin Exp $ */
4 * Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include "opt_compat_darwin.h"
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: mach_port.c,v 1.65 2008/04/28 20:23:44 martin Exp $");
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/signal.h>
42 #include <sys/queue.h>
43 #include <sys/malloc.h>
46 #include <compat/mach/mach_types.h>
47 #include <compat/mach/mach_message.h>
48 #include <compat/mach/mach_port.h>
49 #include <compat/mach/mach_iokit.h>
50 #include <compat/mach/mach_clock.h>
51 #include <compat/mach/mach_exec.h>
52 #include <compat/mach/mach_errno.h>
53 #include <compat/mach/mach_notify.h>
54 #include <compat/mach/mach_services.h>
55 #include <compat/mach/mach_syscallargs.h>
58 #include <compat/darwin/darwin_exec.h>
61 /* Right and port pools, list of all rights and its lock */
62 static struct pool mach_port_pool
;
63 static struct pool mach_right_pool
;
65 struct mach_port
*mach_bootstrap_port
;
66 struct mach_port
*mach_clock_port
;
67 struct mach_port
*mach_io_master_port
;
68 struct mach_port
*mach_saved_bootstrap_port
;
71 mach_sys_reply_port(struct lwp
*l
, const void *v
, register_t
*retval
)
73 struct mach_right
*mr
;
75 mr
= mach_right_get(mach_port_get(), l
, MACH_PORT_TYPE_RECEIVE
, 0);
76 *retval
= (register_t
)mr
->mr_name
;
82 mach_sys_thread_self_trap(struct lwp
*l
, const void *v
, register_t
*retval
)
84 struct mach_lwp_emuldata
*mle
;
85 struct mach_right
*mr
;
88 mr
= mach_right_get(mle
->mle_kernel
, l
, MACH_PORT_TYPE_SEND
, 0);
89 *retval
= (register_t
)mr
->mr_name
;
96 mach_sys_task_self_trap(struct lwp
*l
, const void *v
, register_t
*retval
)
98 struct mach_emuldata
*med
;
99 struct mach_right
*mr
;
101 med
= (struct mach_emuldata
*)l
->l_proc
->p_emuldata
;
102 mr
= mach_right_get(med
->med_kernel
, l
, MACH_PORT_TYPE_SEND
, 0);
103 *retval
= (register_t
)mr
->mr_name
;
110 mach_sys_host_self_trap(struct lwp
*l
, const void *v
, register_t
*retval
)
112 struct mach_emuldata
*med
;
113 struct mach_right
*mr
;
115 med
= (struct mach_emuldata
*)l
->l_proc
->p_emuldata
;
116 mr
= mach_right_get(med
->med_host
, l
, MACH_PORT_TYPE_SEND
, 0);
117 *retval
= (register_t
)mr
->mr_name
;
123 mach_port_deallocate(struct mach_trap_args
*args
)
125 mach_port_deallocate_request_t
*req
= args
->smsg
;
126 mach_port_deallocate_reply_t
*rep
= args
->rmsg
;
127 size_t *msglen
= args
->rsize
;
128 struct lwp
*l
= args
->l
;
130 struct mach_right
*mr
;
133 if ((mr
= mach_right_check(mn
, l
, MACH_PORT_TYPE_REF_RIGHTS
)) != NULL
)
134 mach_right_put(mr
, MACH_PORT_TYPE_REF_RIGHTS
);
136 *msglen
= sizeof(*rep
);
137 mach_set_header(rep
, req
, *msglen
);
141 mach_set_trailer(rep
, *msglen
);
147 mach_port_destroy(struct mach_trap_args
*args
)
149 mach_port_destroy_request_t
*req
= args
->smsg
;
150 mach_port_destroy_reply_t
*rep
= args
->rmsg
;
151 size_t *msglen
= args
->rsize
;
152 struct lwp
*l
= args
->l
;
154 struct mach_right
*mr
;
157 printf("mach_port_destroy mn = %x\n", req
->req_name
);
160 if ((mr
= mach_right_check(mn
,
161 l
, MACH_PORT_TYPE_ALL_RIGHTS
)) != NULL
) {
162 MACH_PORT_UNREF(mr
->mr_port
);
164 mach_right_put(mr
, MACH_PORT_TYPE_ALL_RIGHTS
);
167 *msglen
= sizeof(*rep
);
168 mach_set_header(rep
, req
, *msglen
);
172 mach_set_trailer(rep
, *msglen
);
178 mach_port_allocate(struct mach_trap_args
*args
)
180 mach_port_allocate_request_t
*req
= args
->smsg
;
181 mach_port_allocate_reply_t
*rep
= args
->rmsg
;
182 size_t *msglen
= args
->rsize
;
183 struct lwp
*l
= args
->l
;
184 struct mach_right
*mr
;
185 struct mach_port
*mp
;
187 switch (req
->req_right
) {
188 case MACH_PORT_RIGHT_RECEIVE
:
189 mp
= mach_port_get();
190 mr
= mach_right_get(mp
, l
, MACH_PORT_TYPE_RECEIVE
, 0);
193 case MACH_PORT_RIGHT_DEAD_NAME
:
194 mr
= mach_right_get(NULL
, l
, MACH_PORT_TYPE_DEAD_NAME
, 0);
197 case MACH_PORT_RIGHT_PORT_SET
:
198 mr
= mach_right_get(NULL
, l
, MACH_PORT_TYPE_PORT_SET
, 0);
202 uprintf("mach_port_allocate: unknown right %x\n",
204 return mach_msg_error(args
, EINVAL
);
208 *msglen
= sizeof(*rep
);
209 mach_set_header(rep
, req
, *msglen
);
212 rep
->rep_name
= (mach_port_name_t
)mr
->mr_name
;
214 mach_set_trailer(rep
, *msglen
);
220 mach_port_insert_right(struct mach_trap_args
*args
)
222 mach_port_insert_right_request_t
*req
= args
->smsg
;
223 mach_port_insert_right_reply_t
*rep
= args
->rmsg
;
224 size_t *msglen
= args
->rsize
;
225 struct lwp
*l
= args
->l
;
228 struct mach_right
*mr
;
229 struct mach_right
*nmr
;
231 name
= req
->req_name
;
232 right
= req
->req_poly
.name
;
235 mr
= mach_right_check(right
, l
, MACH_PORT_TYPE_ALL_RIGHTS
);
237 return mach_msg_error(args
, EPERM
);
239 switch (req
->req_poly
.disposition
) {
240 case MACH_MSG_TYPE_MAKE_SEND
:
241 case MACH_MSG_TYPE_MOVE_SEND
:
242 case MACH_MSG_TYPE_COPY_SEND
:
243 nmr
= mach_right_get(mr
->mr_port
,
244 l
, MACH_PORT_TYPE_SEND
, name
);
247 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
248 case MACH_MSG_TYPE_MOVE_SEND_ONCE
:
249 nmr
= mach_right_get(mr
->mr_port
,
250 l
, MACH_PORT_TYPE_SEND_ONCE
, name
);
253 case MACH_MSG_TYPE_MOVE_RECEIVE
:
254 nmr
= mach_right_get(mr
->mr_port
,
255 l
, MACH_PORT_TYPE_RECEIVE
, name
);
259 uprintf("mach_port_insert_right: unknown right %x\n",
260 req
->req_poly
.disposition
);
264 *msglen
= sizeof(*rep
);
265 mach_set_header(rep
, req
, *msglen
);
269 mach_set_trailer(rep
, *msglen
);
275 mach_port_type(struct mach_trap_args
*args
)
277 mach_port_type_request_t
*req
= args
->smsg
;
278 mach_port_type_reply_t
*rep
= args
->rmsg
;
279 size_t *msglen
= args
->rsize
;
280 struct lwp
*l
= args
->l
;
282 struct mach_right
*mr
;
285 if ((mr
= mach_right_check(mn
, l
, MACH_PORT_TYPE_ALL_RIGHTS
)) == NULL
)
286 return mach_msg_error(args
, EPERM
);
288 *msglen
= sizeof(*rep
);
289 mach_set_header(rep
, req
, *msglen
);
292 rep
->rep_ptype
= mr
->mr_type
;
294 mach_set_trailer(rep
, *msglen
);
300 mach_port_set_attributes(struct mach_trap_args
*args
)
302 mach_port_set_attributes_request_t
*req
= args
->smsg
;
303 mach_port_set_attributes_reply_t
*rep
= args
->rmsg
;
304 size_t *msglen
= args
->rsize
;
307 /* Sanity check req->req_count */
308 end_offset
= req
->req_count
;
309 if (MACH_REQMSG_OVERFLOW(args
, req
->req_port_info
[end_offset
]))
310 return mach_msg_error(args
, EINVAL
);
312 switch(req
->req_flavor
) {
313 case MACH_PORT_LIMITS_INFO
:
314 case MACH_PORT_RECEIVE_STATUS
:
315 case MACH_PORT_DNREQUESTS_SIZE
:
318 uprintf("mach_port_set_attributes: unknown flavor %d\n",
323 *msglen
= sizeof(*rep
);
324 mach_set_header(rep
, req
, *msglen
);
328 mach_set_trailer(rep
, *msglen
);
334 mach_port_get_attributes(struct mach_trap_args
*args
)
336 mach_port_get_attributes_request_t
*req
= args
->smsg
;
337 mach_port_get_attributes_reply_t
*rep
= args
->rmsg
;
338 size_t *msglen
= args
->rsize
;
339 struct lwp
*l
= args
->l
;
341 struct mach_right
*mr
;
343 /* Sanity check req_count */
344 if (req
->req_count
> 10)
345 return mach_msg_error(args
, EINVAL
);
347 mn
= req
->req_msgh
.msgh_remote_port
;
348 if ((mr
= mach_right_check(mn
, l
, MACH_PORT_TYPE_ALL_RIGHTS
)) == NULL
)
349 return mach_msg_error(args
, EPERM
);
351 switch (req
->req_flavor
) {
352 case MACH_PORT_LIMITS_INFO
: {
353 struct mach_port_limits
*mpl
;
355 if (req
->req_count
< (sizeof(*mpl
) / sizeof(rep
->rep_info
[0])))
356 return mach_msg_error(args
, EINVAL
);
358 mpl
= (struct mach_port_limits
*)&rep
->rep_info
[0];
359 mpl
->mpl_qlimit
= MACH_PORT_QLIMIT_DEFAULT
; /* XXX fake limit */
361 rep
->rep_count
= sizeof(*mpl
);
366 case MACH_PORT_RECEIVE_STATUS
: {
367 struct mach_port_status
*mps
;
368 struct mach_port
*mp
;
370 if (req
->req_count
< (sizeof(*mps
) / sizeof(rep
->rep_info
[0])))
371 return mach_msg_error(args
, EINVAL
);
373 mps
= (struct mach_port_status
*)&rep
->rep_info
[0];
374 memset(mps
, 0, sizeof(*mps
));
376 if (mr
->mr_sethead
!= NULL
)
377 mps
->mps_pset
= mr
->mr_sethead
->mr_name
;
378 mps
->mps_seqno
= 0; /* XXX */
379 mps
->mps_qlimit
= MACH_PORT_QLIMIT_DEFAULT
; /* XXX fake limit */
380 if ((mp
= mr
->mr_port
) != NULL
) {
381 mps
->mps_mscount
= mp
->mp_refcount
; /* XXX */
382 mps
->mps_msgcount
= mp
->mp_count
;
384 mps
->mps_mscount
= 0;
385 mps
->mps_msgcount
= 0;
387 mps
->mps_sorights
= 0; /* XXX */
388 mps
->mps_srights
= 0; /* XXX */
389 if (mr
->mr_notify_destroyed
!= NULL
)
390 mps
->mps_pdrequest
= 1;
391 if (mr
->mr_notify_no_senders
!= NULL
)
392 mps
->mps_nsrequest
= 1;
393 mps
->mps_flags
= 0; /* XXX */
395 rep
->rep_count
= sizeof(*mps
);
400 printf("mach_port_get_attributes: unknown flavor %d\n",
402 return mach_msg_error(args
, EINVAL
);
407 *msglen
= sizeof(*rep
) - 10 + rep
->rep_count
;
408 mach_set_header(rep
, req
, *msglen
);
412 mach_set_trailer(rep
, *msglen
);
417 /* XXX insert a recv right into a port set without removing it from another */
419 mach_port_insert_member(struct mach_trap_args
*args
)
421 mach_port_insert_member_request_t
*req
= args
->smsg
;
422 mach_port_insert_member_reply_t
*rep
= args
->rmsg
;
423 size_t *msglen
= args
->rsize
;
425 uprintf("Unimplemented mach_port_insert_member\n");
427 *msglen
= sizeof(*rep
);
428 mach_set_header(rep
, req
, *msglen
);
432 mach_set_trailer(rep
, *msglen
);
438 mach_port_move_member(struct mach_trap_args
*args
)
440 mach_port_move_member_request_t
*req
= args
->smsg
;
441 mach_port_move_member_reply_t
*rep
= args
->rmsg
;
442 size_t *msglen
= args
->rsize
;
443 struct lwp
*l
= args
->l
;
444 struct mach_emuldata
*med
= l
->l_proc
->p_emuldata
;
445 mach_port_t member
= req
->req_member
;
446 mach_port_t after
= req
->req_after
;
447 struct mach_right
*mrr
;
448 struct mach_right
*mrs
;
450 mrr
= mach_right_check(member
, l
, MACH_PORT_TYPE_RECEIVE
);
452 return mach_msg_error(args
, EPERM
);
454 mrs
= mach_right_check(after
, l
, MACH_PORT_TYPE_PORT_SET
);
456 return mach_msg_error(args
, EPERM
);
458 rw_enter(&med
->med_rightlock
, RW_WRITER
);
460 /* Remove it from an existing port set */
461 if (mrr
->mr_sethead
!= mrr
)
462 LIST_REMOVE(mrr
, mr_setlist
);
464 /* Insert it into the new port set */
465 LIST_INSERT_HEAD(&mrs
->mr_set
, mrr
, mr_setlist
);
466 mrr
->mr_sethead
= mrs
;
468 rw_exit(&med
->med_rightlock
);
470 *msglen
= sizeof(*rep
);
471 mach_set_header(rep
, req
, *msglen
);
475 mach_set_trailer(rep
, *msglen
);
481 mach_port_request_notification(struct mach_trap_args
*args
)
483 mach_port_request_notification_request_t
*req
= args
->smsg
;
484 mach_port_request_notification_reply_t
*rep
= args
->rmsg
;
485 struct lwp
*l
= args
->l
;
486 size_t *msglen
= args
->rsize
;
488 struct mach_right
*nmr
;
489 struct mach_right
*tmr
;
490 struct mach_right
*oldnmr
;
494 printf("mach_port_request_notification, notify = %08x, target = %08x\n",
495 req
->req_notify
.name
, mn
= req
->req_name
);
497 mn
= req
->req_notify
.name
;
498 if ((nmr
= mach_right_check(mn
, l
, MACH_PORT_TYPE_ALL_RIGHTS
)) == NULL
)
499 return mach_msg_error(args
, EINVAL
);
502 if ((tmr
= mach_right_check(mn
, l
, MACH_PORT_TYPE_ALL_RIGHTS
)) == NULL
)
503 return mach_msg_error(args
, EINVAL
);
506 if (nmr
->mr_port
== NULL
) {
507 printf("Notification right without a port\n");
508 printf("mr->mr_port = %p, mr = %08x\n", nmr
->mr_port
, nmr
->mr_name
);
509 return mach_msg_error(args
, EINVAL
);
515 switch(req
->req_msgid
) {
516 case MACH_NOTIFY_DESTROYED_MSGID
:
517 oldnmr
= tmr
->mr_notify_destroyed
;
518 tmr
->mr_notify_destroyed
= mach_right_get(nmr
->mr_port
,
519 l
, MACH_PORT_TYPE_SEND_ONCE
, req
->req_notify
.name
);
522 case MACH_NOTIFY_NO_SENDERS_MSGID
:
523 oldnmr
= tmr
->mr_notify_no_senders
;
524 tmr
->mr_notify_no_senders
= mach_right_get(nmr
->mr_port
,
525 l
, MACH_PORT_TYPE_SEND_ONCE
, req
->req_notify
.name
);
526 tmr
->mr_notify_no_senders
->mr_port
->mp_datatype
=
528 tmr
->mr_notify_no_senders
->mr_port
->mp_data
= (void *)
532 case MACH_NOTIFY_DEAD_NAME_MSGID
:
533 oldnmr
= tmr
->mr_notify_dead_name
;
534 tmr
->mr_notify_dead_name
= mach_right_get(nmr
->mr_port
,
535 l
, MACH_PORT_TYPE_SEND_ONCE
, req
->req_notify
.name
);
538 case MACH_NOTIFY_SEND_ONCE_MSGID
:
539 case MACH_NOTIFY_DELETED_MSGID
:
542 printf("unsupported notify request %d\n", req
->req_msgid
);
543 return mach_msg_error(args
, EINVAL
);
548 if (oldnmr
!= NULL
) {
549 oldnmr
->mr_refcount
++;
550 oldmn
= oldnmr
->mr_name
;
552 oldmn
= (mach_port_t
)MACH_PORT_NULL
;
555 *msglen
= sizeof(*rep
);
556 mach_set_header(rep
, req
, *msglen
);
557 mach_add_port_desc(rep
, oldmn
);
558 mach_set_trailer(rep
, *msglen
);
564 mach_port_get_refs(struct mach_trap_args
*args
)
566 mach_port_get_refs_request_t
*req
= args
->smsg
;
567 mach_port_get_refs_reply_t
*rep
= args
->rmsg
;
568 size_t *msglen
= args
->rsize
;
569 struct lwp
*l
= args
->l
;
571 struct mach_right
*mr
;
572 mach_port_right_t right
= req
->req_right
;
575 if ((mr
= mach_right_check(mn
, l
, right
)) == NULL
)
576 return mach_msg_error(args
, EINVAL
);
578 *msglen
= sizeof(*rep
);
579 mach_set_header(rep
, req
, *msglen
);
582 rep
->rep_refs
= mr
->mr_refcount
;
584 mach_set_trailer(rep
, *msglen
);
590 mach_port_mod_refs(struct mach_trap_args
*args
)
592 mach_port_mod_refs_request_t
*req
= args
->smsg
;
593 mach_port_mod_refs_reply_t
*rep
= args
->rmsg
;
594 size_t *msglen
= args
->rsize
;
596 struct lwp
*l
= args
->l
;
598 struct mach_right
*mr
;
599 mach_port_right_t right
= req
->req_right
;
602 if ((mr
= mach_right_check(mn
, l
, right
)) == NULL
)
603 return mach_msg_error(args
, EINVAL
);
606 * Changing the refcount is likely to cause crashes,
607 * as we will free a right which might still be referenced
608 * within the kernel. Add a user refcount field?
610 mr
->mr_refcount
+= req
->req_delta
;
611 if (mr
->mr_refcount
<= 0)
612 mach_right_put(mr
, right
);
615 *msglen
= sizeof(*rep
);
616 mach_set_header(rep
, req
, *msglen
);
620 mach_set_trailer(rep
, *msglen
);
628 pool_init(&mach_port_pool
, sizeof (struct mach_port
),
629 0, 0, 0, "mach_port_pool", NULL
, IPL_NONE
);
630 pool_init(&mach_right_pool
, sizeof (struct mach_right
),
631 0, 0, 0, "mach_right_pool", NULL
, IPL_NONE
);
633 mach_bootstrap_port
= mach_port_get();
634 mach_clock_port
= mach_port_get();
635 mach_io_master_port
= mach_port_get();
637 mach_bootstrap_port
->mp_flags
|= MACH_MP_INKERNEL
;
638 mach_clock_port
->mp_flags
|= MACH_MP_INKERNEL
;
639 mach_io_master_port
->mp_flags
|= MACH_MP_INKERNEL
;
641 mach_saved_bootstrap_port
= mach_bootstrap_port
;
649 struct mach_port
*mp
;
651 mp
= (struct mach_port
*)pool_get(&mach_port_pool
, PR_WAITOK
);
652 memset(mp
, 0, sizeof(*mp
));
656 mp
->mp_datatype
= MACH_MP_NONE
;
658 TAILQ_INIT(&mp
->mp_msglist
);
659 rw_init(&mp
->mp_msglock
);
665 mach_port_put(struct mach_port
*mp
)
667 struct mach_message
*mm
;
670 if (mp
->mp_refcount
> 0) {
671 uprintf("mach_port_put: trying to free a referenced port\n");
676 rw_enter(&mp
->mp_msglock
, RW_WRITER
);
677 while ((mm
= TAILQ_FIRST(&mp
->mp_msglist
)) != NULL
)
678 mach_message_put_exclocked(mm
);
679 rw_exit(&mp
->mp_msglock
);
680 rw_destroy(&mp
->mp_msglock
);
682 if (mp
->mp_flags
& MACH_MP_DATA_ALLOCATED
)
683 free(mp
->mp_data
, M_EMULDATA
);
685 pool_put(&mach_port_pool
, mp
);
691 mach_right_get(struct mach_port
*mp
, struct lwp
*l
, int type
, mach_port_t hint
)
693 struct mach_right
*mr
;
694 struct mach_emuldata
*med
;
699 uprintf("mach_right_get: right = 0\n");
701 med
= (struct mach_emuldata
*)l
->l_proc
->p_emuldata
;
706 /* Send and receive right must return an existing right */
707 rights
= (MACH_PORT_TYPE_SEND
| MACH_PORT_TYPE_RECEIVE
);
709 rw_enter(&med
->med_rightlock
, RW_READER
);
710 LIST_FOREACH(mr
, &med
->med_right
, mr_list
) {
711 if ((mr
->mr_port
== mp
) && (mr
->mr_type
& rights
))
714 rw_exit(&med
->med_rightlock
);
718 if (type
& MACH_PORT_TYPE_SEND
)
724 mr
= pool_get(&mach_right_pool
, PR_WAITOK
);
731 mr
->mr_notify_destroyed
= NULL
;
732 mr
->mr_notify_dead_name
= NULL
;
733 mr
->mr_notify_no_senders
= NULL
;
735 LIST_INIT(&mr
->mr_set
);
737 /* Insert the right in the right lists */
738 if (type
& MACH_PORT_TYPE_ALL_RIGHTS
) {
739 rw_enter(&med
->med_rightlock
, RW_WRITER
);
740 mr
->mr_name
= mach_right_newname(l
, hint
);
741 #ifdef DEBUG_MACH_RIGHT
742 printf("mach_right_get: insert right %x(%x)\n",
743 mr
->mr_name
, mr
->mr_type
);
745 LIST_INSERT_HEAD(&med
->med_right
, mr
, mr_list
);
746 rw_exit(&med
->med_rightlock
);
750 if (type
& MACH_PORT_TYPE_RECEIVE
) {
752 * Destroy the former receive right on this port, and
753 * register the new right.
755 if (mr
->mr_port
->mp_recv
!= NULL
)
756 mach_right_put(mr
->mr_port
->mp_recv
,
757 MACH_PORT_TYPE_RECEIVE
);
758 mr
->mr_port
->mp_recv
= mr
;
764 mach_right_put(struct mach_right
*mr
, int right
)
766 struct mach_emuldata
*med
= mr
->mr_lwp
->l_proc
->p_emuldata
;
768 rw_enter(&med
->med_rightlock
, RW_WRITER
);
769 mach_right_put_exclocked(mr
, right
);
770 rw_exit(&med
->med_rightlock
);
776 mach_right_put_shlocked(struct mach_right
*mr
, int right
)
778 struct mach_emuldata
*med
= mr
->mr_lwp
->l_proc
->p_emuldata
;
780 if (!rw_tryupgrade(&med
->med_rightlock
)) {
782 rw_exit(&med
->med_rightlock
);
783 rw_enter(&med
->med_rightlock
, RW_WRITER
);
785 mach_right_put_exclocked(mr
, right
);
786 rw_downgrade(&med
->med_rightlock
);
792 mach_right_put_exclocked(struct mach_right
*mr
, int right
)
794 struct mach_right
*cmr
;
795 struct mach_emuldata
*med
;
799 med
= mr
->mr_lwp
->l_proc
->p_emuldata
;
801 #ifdef DEBUG_MACH_RIGHT
802 printf("mach_right_put: mr = %p\n", mr
);
803 printf("right %x(%x) refcount %d, deallocate %x\n",
804 mr
->mr_name
, mr
->mr_type
, mr
->mr_refcount
, right
);
805 if ((mr
->mr_type
& right
) == 0)
806 printf("mach_right_put: dropping nonexistant right %x on %x\n",
808 LIST_FOREACH(cmr
, &med
->med_right
, mr_list
)
812 printf("mach_right_put: dropping already dropped right %x\n",
819 /* When receive right is deallocated, the port should die */
820 lright
= (right
& MACH_PORT_TYPE_RECEIVE
);
821 #ifdef DEBUG_MACH_RIGHT
822 printf("mr->mr_type = %x, lright = %x, right = %x, refcount = %d\n",
823 mr
->mr_type
, lright
, right
, mr
->mr_refcount
);
825 if (mr
->mr_type
& lright
) {
826 if (mr
->mr_refcount
<= 0) {
827 mr
->mr_type
&= ~MACH_PORT_TYPE_RECEIVE
;
830 mr
->mr_type
&= ~MACH_PORT_TYPE_RECEIVE
;
831 mr
->mr_type
|= MACH_PORT_TYPE_DEAD_NAME
;
832 mach_notify_port_dead_name(mr
->mr_lwp
, mr
);
834 if (mr
->mr_port
!= NULL
) {
835 /* There is no more receiver */
837 if (mr
->mr_port
->mp_recv
!= mr
)
838 printf("several receiver on a single port\n");
840 mr
->mr_port
->mp_recv
= NULL
;
842 MACH_PORT_UNREF(mr
->mr_port
);
847 /* send, send_once and dead_name */
848 lright
= (right
& MACH_PORT_TYPE_REF_RIGHTS
);
849 if (mr
->mr_type
& lright
) {
852 mach_notify_port_no_senders(mr
->mr_lwp
, mr
);
854 if (mr
->mr_refcount
<= 0) {
855 mr
->mr_type
&= ~MACH_PORT_TYPE_REF_RIGHTS
;
856 if ((mr
->mr_type
& MACH_PORT_TYPE_RECEIVE
) == 0)
861 lright
= (right
& MACH_PORT_TYPE_PORT_SET
);
862 if ((mr
->mr_type
& lright
) || (kill_right
== 1)) {
863 while ((cmr
= LIST_FIRST(&mr
->mr_set
)) != NULL
) {
864 LIST_REMOVE(cmr
, mr_setlist
);
865 cmr
->mr_sethead
= cmr
;
867 mr
->mr_type
&= ~MACH_PORT_TYPE_PORT_SET
;
868 if ((mr
->mr_type
& MACH_PORT_TYPE_RECEIVE
) == 0)
872 /* Should we kill it? */
873 if (kill_right
== 1) {
874 #ifdef DEBUG_MACH_RIGHT
875 printf("mach_right_put: kill name %x\n", mr
->mr_name
);
877 /* If the right is used for an IO notification, remove it */
878 mach_iokit_cleanup_notify(mr
);
880 mach_notify_port_destroyed(mr
->mr_lwp
, mr
);
881 LIST_REMOVE(mr
, mr_list
);
882 pool_put(&mach_right_pool
, mr
);
888 * Check that a process has a given right.
891 mach_right_check(mach_port_t mn
, struct lwp
*l
, int type
)
893 struct mach_right
*cmr
;
894 struct mach_emuldata
*med
;
896 if ((mn
== 0) || (mn
== -1) || (l
== NULL
))
899 med
= (struct mach_emuldata
*)l
->l_proc
->p_emuldata
;
901 rw_enter(&med
->med_rightlock
, RW_READER
);
903 #ifdef DEBUG_MACH_RIGHT
904 printf("mach_right_check: type = %x, mn = %x\n", type
, mn
);
906 LIST_FOREACH(cmr
, &med
->med_right
, mr_list
) {
907 #ifdef DEBUG_MACH_RIGHT
908 printf("cmr = %p, cmr->mr_name = %x, cmr->mr_type = %x\n",
909 cmr
, cmr
->mr_name
, cmr
->mr_type
);
911 if (cmr
->mr_name
!= mn
)
913 if (type
& cmr
->mr_type
)
917 rw_exit(&med
->med_rightlock
);
924 * Find an usnused port name in a given lwp.
925 * Right lists should be locked.
928 mach_right_newname(struct lwp
*l
, mach_port_t hint
)
930 struct mach_emuldata
*med
;
931 struct mach_right
*mr
;
932 mach_port_t newname
= -1;
934 med
= l
->l_proc
->p_emuldata
;
937 hint
= med
->med_nextright
;
939 while (newname
== -1) {
940 LIST_FOREACH(mr
, &med
->med_right
, mr_list
)
941 if (mr
->mr_name
== hint
)
948 med
->med_nextright
= hint
;
955 mach_debug_port(void)
957 struct mach_emuldata
*med
;
958 struct mach_right
*mr
;
959 struct mach_right
*mrs
;
962 PROCLIST_FOREACH(p
, &allproc
) {
963 if ((p
->p_emul
!= &emul_mach
) &&
965 (p
->p_emul
!= &emul_darwin
) &&
971 LIST_FOREACH(mr
, &med
->med_right
, mr_list
) {
972 if ((mr
->mr_type
& MACH_PORT_TYPE_PORT_SET
) == 0) {
973 printf("pid %d: %p(%x)=>%p",
974 p
->p_pid
, mr
, mr
->mr_type
, mr
->mr_port
);
975 if (mr
->mr_port
&& mr
->mr_port
->mp_recv
)
977 mr
->mr_port
->mp_recv
->mr_sethead
);
985 printf("pid %d: set %p(%x) ",
986 p
->p_pid
, mr
, mr
->mr_type
);
987 LIST_FOREACH(mrs
, &mr
->mr_set
, mr_setlist
) {
989 mrs
, mrs
->mr_type
, mrs
->mr_port
);
990 if (mrs
->mr_port
&& mrs
->mr_port
->mp_recv
)
992 mrs
->mr_port
->mp_recv
->mr_sethead
);
1004 #endif /* DEBUG_MACH */