2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * bootstrap -- fundamental service initiator and port server
26 * Mike DeMoney, NeXT, Inc.
27 * Copyright, 1990. All rights reserved.
29 * bootstrap.c -- implementation of bootstrap main service loop
36 #import <mach/boolean.h>
37 #import <mach/message.h>
38 #import <mach/notify.h>
39 #import <mach/mig_errors.h>
40 #include <mach/mach_traps.h>
41 #include <mach/mach_interface.h>
42 #include <mach/bootstrap.h>
43 #include <mach/host_info.h>
44 #include <mach/mach_host.h>
45 #include <mach/exception.h>
53 #include "bootstrap.h"
55 #import "bootstrap_internal.h"
60 /* Mig should produce a declaration for this, but doesn't */
61 extern boolean_t
bootstrap_server(mach_msg_header_t
*InHeadP
, mach_msg_header_t
*OutHeadP
);
66 const char *program_name
; /* our name for error messages */
69 #define CONF_FILE "/etc/bootstrap.conf" /* default config file */
72 const char *conf_file
= CONF_FILE
;
74 const unsigned BOOTSTRAP_REPLY_TIMEOUT
= 10 * 1000; // 10 sec reply timeout
76 port_all_t backup_port
;
79 * Last resort configuration
81 * If we can't find a /etc/bootstrap.conf, we use this configuration.
82 * The services defined here are compatable with the old mach port stuff,
83 * and of course, the names for these services should not be modified without
84 * modifying mach_init in libc.
86 const char *default_conf
=
87 "init \"/sbin/init\";"
88 "services NetMessage;";
90 mach_port_t inherited_bootstrap_port
= MACH_PORT_NULL
;
91 boolean_t forward_ok
= FALSE
;
92 boolean_t debugging
= FALSE
;
93 boolean_t register_self
= FALSE
;
94 int init_priority
= BASEPRI_USER
;
95 char *register_name
= NULL
;
96 mach_port_t bootstrap_master_device_port
; /* local name */
97 mach_port_t bootstrap_master_host_port
; /* local name */
98 mach_port_t bootstrap_notification_port
; /* local name */
99 mach_port_t security_port
;
100 mach_port_t root_ledger_wired
;
101 mach_port_t root_ledger_paged
;
102 task_port_t bootstrap_self
;
111 #define NELEM(x) (sizeof(x)/sizeof(x[0]))
112 #define END_OF(x) (&(x)[NELEM(x)])
113 #define streq(a,b) (strcmp(a,b) == 0)
116 * Private declarations
118 static void add_init_arg(const char *arg
);
119 static void wait_for_go(mach_port_t init_notify_port
);
120 static void init_ports(void);
121 static void start_server(server_t
*serverp
);
122 static void unblock_init(task_port_t task
, mach_port_t newBootstrap
);
123 static void exec_server(server_t
*serverp
);
124 static char **argvize(const char *string
);
125 static void server_loop(void);
126 static void msg_destroy(mach_msg_header_t
*m
);
129 * Private ports we hold receive rights for. We also hold receive rights
130 * for all the privileged ports. Those are maintained in the server
133 mach_port_t bootstrap_port_set
;
134 mach_port_t notify_port
;
137 static int running_servers
;
138 static char init_args
[BOOTSTRAP_MAX_CMD_LEN
];
140 void _myExit(int arg
)
145 /* It was a bozo who made main return a value! Civil disobedience, here. */
147 main(int argc
, const char * const argv
[])
151 server_t
*init_serverp
;
153 mach_port_t init_notify_port
;
154 kern_return_t result
;
156 int force_fork
= FALSE
;
157 mach_port_t prev_port
;
158 #if defined(__APPLE__)
159 extern void exit(int);
161 /* signal (SIGUSR2, _myExit); */
164 /* Initialize error handling */
165 program_name
= rindex(*argv
, '/');
169 program_name
= *argv
;
173 init_errlog(init_pid
== 1);
176 * Get master host and device ports
179 result
= bootstrap_ports(bootstrap_port
,
180 &bootstrap_master_host_port
,
181 &bootstrap_master_device_port
,
185 if (result
!= KERN_SUCCESS
) {
186 printf("bootstrap_ports failed \n");
187 kern_error(result
, "bootstrap_ports");
191 * This task will become the bootstrap task.
193 bootstrap_self
= mach_task_self();
195 /* Initialize globals */
198 /* Parse command line args */
199 while (argc
> 0 && **argv
== '-') {
200 boolean_t init_arg
= FALSE
;
201 argp
= *argv
++ + 1; argc
--;
203 switch (c
= *argp
++) {
215 conf_file
= *argv
++; argc
--;
217 fatal("-f requires config file name");
223 register_self
= forward_ok
= TRUE
;
225 register_name
= *argv
++; argc
--;
227 fatal("-r requires name");
235 add_init_arg(argv
[-1]);
242 add_init_arg(*argv
++);
247 /* Parse the config file */
250 /* set_default_policy(bootstrap_master_host_port); */
253 * If we have to run init as pid 1, use notify port to
254 * synchronize init and bootstrap
256 if ((init_serverp
= find_init_server()) != NULL
) {
257 if (init_pid
!= 1 && ! debugging
)
258 fatal("Can't start init server if not pid 1");
259 result
= mach_port_allocate(bootstrap_self
, MACH_PORT_RIGHT_RECEIVE
,
261 if (result
!= KERN_SUCCESS
)
262 kern_fatal(result
, "mach_port_allocate");
263 result
= mach_port_insert_right(mach_task_self(), init_notify_port
, init_notify_port
, MACH_MSG_TYPE_MAKE_SEND
);
264 if (result
!= KERN_SUCCESS
)
265 kern_fatal(result
, "mach_port_insert_right");
266 task_set_bootstrap_port(bootstrap_self
, init_notify_port
);
267 if (result
!= KERN_SUCCESS
)
268 kern_fatal(result
, "task_set_bootstrap_port");
270 * XXX restart the service if it dies?
272 result
= mach_port_request_notification(mach_task_self(),
274 MACH_NOTIFY_DEAD_NAME
,
277 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
279 if (result
!= KERN_SUCCESS
)
280 kern_fatal(result
, "mach_port_request_notification");
281 debug("Set port %d for parent proc notify port",
283 } else if (init_args
[0] != '\0')
284 fatal("Extraneous command line arguments");
286 /* Fork if either not debugging or running /etc/init */
287 if (force_fork
|| !debugging
|| init_serverp
!= NULL
) {
294 /* Bootstrap service runs in child (if there is one) */
295 if (pid
== 0) { /* CHILD */
297 * If we're initiated by pid 1, we shouldn't get ever get
298 * killed; designate ourselves as an "init process".
300 * This should go away with new signal stuff!
305 /* Create declared service ports, our service port, etc */
308 /* Kick off all server processes */
309 for ( serverp
= FIRST(servers
)
310 ; !IS_END(serverp
, servers
)
311 ; serverp
= NEXT(serverp
))
312 start_server(serverp
);
315 * If our priority's to be changed, set it up here.
318 if (init_priority
>= 0) {
319 result
= task_priority(mach_task_self(), init_priority
,
321 if (result
!= KERN_SUCCESS
)
322 kern_error(result
, "task_priority %d",
326 /* Process bootstrap service requests */
327 server_loop(); /* Should never return */
332 if (init_serverp
!= NULL
) {
335 strncat(init_serverp
->cmd
,
337 sizeof(init_serverp
->cmd
));
339 * Wait, then either exec /etc/init or exit
340 * (which panics the system)
344 wait_for_go(init_notify_port
);
345 exec_server(init_serverp
);
352 add_init_arg(const char *arg
)
354 strncat(init_args
, " ", sizeof(init_args
));
355 strncat(init_args
, arg
, sizeof(init_args
));
359 wait_for_go(mach_port_t init_notify_port
)
362 mach_msg_header_t hdr
;
363 mach_msg_trailer_t trailer
;
365 kern_return_t result
;
368 * For now, we just blindly wait until we receive a message or
369 * timeout. We don't expect any notifications, and if we get one,
370 * it probably means something dire has happened; so we might as
371 * well give a shot at letting init run.
373 result
= mach_msg(&init_go_msg
.hdr
, MACH_RCV_MSG
, 0, sizeof(init_go_msg
), init_notify_port
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
374 if (result
!= KERN_SUCCESS
) {
375 kern_error(result
, "mach_msg(receive) failed in wait_for_go");
377 result
= task_set_bootstrap_port(mach_task_self(), init_go_msg
.hdr
.msgh_remote_port
);
378 if (result
!= KERN_SUCCESS
) {
379 kern_error(result
, "task_get_bootstrap_port()");
386 kern_return_t result
;
388 mach_port_name_t previous
;
392 * This task will become the bootstrap task.
394 bootstrap_self
= mach_task_self();
396 /* get inherited bootstrap port */
397 result
= task_get_bootstrap_port(bootstrap_self
,
398 &inherited_bootstrap_port
);
399 if (result
!= KERN_SUCCESS
)
400 kern_fatal(result
, "task_get_bootstrap_port");
402 /* We set this explicitly as we start each child */
403 task_set_bootstrap_port(bootstrap_self
, MACH_PORT_NULL
);
404 if (inherited_bootstrap_port
== MACH_PORT_NULL
)
407 /* Create port set that server loop listens to */
408 result
= mach_port_allocate(bootstrap_self
, MACH_PORT_RIGHT_PORT_SET
,
409 &bootstrap_port_set
);
410 if (result
!= KERN_SUCCESS
)
411 kern_fatal(result
, "port_set_allocate");
412 /* Create notify port and add to server port set */
413 result
= mach_port_allocate(bootstrap_self
, MACH_PORT_RIGHT_RECEIVE
,
415 if (result
!= KERN_SUCCESS
)
416 kern_fatal(result
, "mach_port_allocate");
418 result
= mach_port_request_notification(bootstrap_self
,
420 MACH_NOTIFY_DEAD_NAME
,
423 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
425 if (result
!= KERN_SUCCESS
)
426 kern_fatal(result
, "task_set_notify_port");
428 result
= mach_port_move_member(bootstrap_self
,
431 if (result
!= KERN_SUCCESS
)
432 kern_fatal(result
, "mach_port_move_member");
434 /* Create "self" port and add to server port set */
435 result
= mach_port_allocate(bootstrap_self
, MACH_PORT_RIGHT_RECEIVE
,
436 &bootstraps
.bootstrap_port
);
437 if (result
!= KERN_SUCCESS
)
438 kern_fatal(result
, "mach_port_allocate");
439 result
= mach_port_insert_right(mach_task_self(), bootstraps
.bootstrap_port
, bootstraps
.bootstrap_port
, MACH_MSG_TYPE_MAKE_SEND
);
440 if (result
!= KERN_SUCCESS
)
441 kern_fatal(result
, "mach_port_insert_right");
442 result
= mach_port_move_member(bootstrap_self
,
443 bootstraps
.bootstrap_port
,
445 if (result
!= KERN_SUCCESS
)
446 kern_fatal(result
, "mach_port_move_member");
448 /* register "self" port with anscestor */
449 if (register_self
&& forward_ok
) {
450 result
= bootstrap_register(inherited_bootstrap_port
, register_name
, bootstraps
.bootstrap_port
);
451 if (result
!= KERN_SUCCESS
)
452 kern_fatal(result
, "register self");
456 * Allocate service ports for declared services.
458 for ( servicep
= FIRST(services
)
459 ; ! IS_END(servicep
, services
)
460 ; servicep
= NEXT(servicep
))
462 switch (servicep
->servicetype
) {
464 result
= mach_port_allocate(bootstrap_self
, MACH_PORT_RIGHT_RECEIVE
,
466 if (result
!= KERN_SUCCESS
)
467 kern_fatal(result
, "mach_port_allocate");
468 result
= mach_port_insert_right(bootstrap_self
, servicep
->port
, servicep
->port
, MACH_MSG_TYPE_MAKE_SEND
);
469 if (result
!= KERN_SUCCESS
)
470 kern_fatal(result
, "mach_port_insert_right");
471 debug("Declared port %d for service %s",
475 result
= port_set_backup(task_self(),
479 if (result
!= KERN_SUCCESS
)
480 kern_fatal(result
, "port_set_backup");
484 servicep
->port
= bootstraps
.bootstrap_port
;
485 servicep
->server
= new_server(MACHINIT
,
486 program_name
, init_priority
);
487 info("Set port %d for self port",
488 bootstraps
.bootstrap_port
);
491 fatal("Can't allocate REGISTERED port!?!");
498 start_server(server_t
*serverp
)
500 kern_return_t result
;
501 mach_port_t old_port
;
502 task_port_t init_task
;
505 /* get rid of any old server port (this might be a restart) */
506 old_port
= serverp
->port
;
507 serverp
->port
= MACH_PORT_NULL
;
508 if (old_port
!= MACH_PORT_NULL
) {
509 msg_destroy_port(old_port
);
511 /* Allocate privileged port for requests from service */
512 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
,&serverp
->port
);
513 info("Allocating port %d for server %s", serverp
->port
, serverp
->cmd
);
514 if (result
!= KERN_SUCCESS
)
515 kern_fatal(result
, "port_allocate");
517 result
= mach_port_insert_right(mach_task_self(), serverp
->port
, serverp
->port
, MACH_MSG_TYPE_MAKE_SEND
);
518 if (result
!= KERN_SUCCESS
)
519 kern_fatal(result
, "mach_port_insert_right");
520 /* Add privileged server port to bootstrap port set */
521 result
= mach_port_move_member(mach_task_self(),
524 if (result
!= KERN_SUCCESS
)
525 kern_fatal(result
, "mach_port_move_member");
528 * Do what's appropriate to get bootstrap port setup in server task
530 switch (serverp
->servertype
) {
533 * This is pid 1 init program -- need to punch stuff
534 * back into pid 1 task rather than create a new task
536 result
= task_for_pid(mach_task_self(), init_pid
, &init_task
);
537 if (result
!= KERN_SUCCESS
)
538 kern_fatal(result
, "task_for_pid");
539 serverp
->task_port
= init_task
;
540 unblock_init(init_task
, serverp
->port
);
548 /* Give trusted service a unique bootstrap port */
549 result
= task_set_bootstrap_port(mach_task_self(), serverp
->port
);
550 if (result
!= KERN_SUCCESS
)
551 kern_fatal(result
, "task_set_bootstrap_port");
556 else if (pid
== 0) { /* CHILD */
557 exec_server(serverp
);
559 } else { /* PARENT */
560 result
= task_set_bootstrap_port(mach_task_self(),
562 if (result
!= KERN_SUCCESS
)
563 kern_fatal(result
, "task_set_bootstrap_port");
565 result
= task_for_pid(mach_task_self(),
567 &serverp
->task_port
);
568 if (result
!= KERN_SUCCESS
)
569 kern_fatal(result
, "getting server task port");
570 running_servers
+= 1;
577 unblock_init(task_port_t task
, mach_port_t newBootstrap
)
579 mach_msg_header_t init_go_msg
;
580 kern_return_t result
;
583 * Proc 1 is blocked in a msg_receive on its notify port, this lets
584 * it continue, and we hand off its new bootstrap port
586 init_go_msg
.msgh_remote_port
= inherited_bootstrap_port
;
587 init_go_msg
.msgh_local_port
= newBootstrap
;
588 init_go_msg
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, MACH_MSG_TYPE_MAKE_SEND
);
589 result
= mach_msg(&init_go_msg
, MACH_SEND_MSG
, sizeof(init_go_msg
), 0, MACH_PORT_NULL
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
590 if (result
!= KERN_SUCCESS
)
591 kern_fatal(result
, "unblock_init mach_msg(send) failed");
592 debug("sent go message");
596 exec_server(server_t
*serverp
)
602 * Setup environment for server, someday this should be Mach stuff
603 * rather than Unix crud
605 log("Initiating server %s [pid %d]", serverp
->cmd
, getpid());
606 argv
= argvize(serverp
->cmd
);
607 nfds
= getdtablesize();
611 * If our priority's to be changed, set it up here.
613 if (serverp
->priority
>= 0) {
614 kern_return_t result
;
615 result
= task_priority(mach_task_self(), serverp
->priority
,
617 if (result
!= KERN_SUCCESS
)
618 kern_error(result
, "task_priority %d",
625 * Mark this process as an "init process" so that it won't be
626 * blown away by init when it starts up (or changes states).
629 debug("marking process %s as init_process\n", argv
[0]);
633 for (fd
= debugging
? 3 : 0; fd
< nfds
; fd
++)
635 fd
= open("/dev/tty", O_RDONLY
);
637 ioctl(fd
, TIOCNOTTY
, 0);
641 execv(argv
[0], argv
);
642 unix_error("Can't exec %s", argv
[0]);
646 argvize(const char *string
)
648 static char *argv
[100], args
[1000];
654 * Convert a command line into an argv for execv
659 for (cp
= string
; *cp
;) {
662 term
= (*cp
== '"') ? *cp
++ : '\0';
663 if (nargs
< NELEM(argv
))
664 argv
[nargs
++] = argp
;
665 while (*cp
&& (term
? *cp
!= term
: !isspace(*cp
))
666 && argp
< END_OF(args
)) {
680 * server_loop -- pick requests off our service port and process them
681 * Also handles notifications
683 #define bootstrapMaxRequestSize 1024
684 #define bootstrapMaxReplySize 1024
689 bootstrap_info_t
*bootstrap
;
692 kern_return_t result
;
693 mach_port_name_t previous
;
694 mach_port_array_t array
;
695 mach_msg_type_number_t count
;
699 mach_msg_header_t hdr
;
700 char body
[bootstrapMaxRequestSize
];
703 mach_msg_header_t hdr
;
707 char body
[bootstrapMaxReplySize
];
711 memset(&msg
, 0, sizeof(msg
));
712 result
= mach_msg_overwrite_trap(&msg
.hdr
, MACH_RCV_MSG
|MACH_RCV_INTERRUPT
|MACH_RCV_TIMEOUT
, 0, sizeof(msg
), bootstrap_port_set
, 500, MACH_PORT_NULL
, MACH_MSG_NULL
, 0);
713 if (result
!= KERN_SUCCESS
) {
714 if (result
!= MACH_RCV_TIMED_OUT
) {
715 kern_error(result
, "server_loop: msg_receive()");
721 debug("received message on port %d\n", msg
.hdr
.msgh_local_port
);
725 * Pick off notification messages
727 if (msg
.hdr
.msgh_local_port
== notify_port
) {
730 switch (msg
.hdr
.msgh_id
) {
731 case MACH_NOTIFY_DEAD_NAME
:
732 np
= ((mach_dead_name_notification_t
*)&msg
)->not_port
;
734 info("Notified dead name %d", np
);
736 if (np
== inherited_bootstrap_port
)
738 inherited_bootstrap_port
= MACH_PORT_NULL
;
744 * This may be notification that the task_port associated
745 * with a task we've launched has been deleted. This
746 * happens only when the server dies.
748 serverp
= lookup_server_by_task_port(np
);
749 if (serverp
!= NULL
) {
750 info("Notified that server %s died\n", serverp
->cmd
);
751 if (running_servers
<= 0) {
752 /* This "can't" happen */
754 error("task count error");
756 running_servers
-= 1;
757 log("server %s died",
758 serverp
!= NULL
? serverp
->cmd
: "Unknown");
759 if (serverp
!= NULL
) {
761 * FIXME: need to control execs
762 * when server fails immediately
764 if ( serverp
->servertype
== RESTARTABLE
766 && haven't started this recently */)
767 start_server(serverp
);
774 * Check to see if a subset requestor port was deleted.
776 while (bootstrap
= lookup_bootstrap_req_by_port(np
)) {
777 info("notified that requestor of subset %d died",
778 bootstrap
->bootstrap_port
);
779 delete_bootstrap(bootstrap
);
783 * Check to see if a defined service has gone
786 while (servicep
= lookup_service_by_port(np
)) {
788 * Port gone, server died.
790 debug("Received destroyed notification for service %s "
791 "on bootstrap port %d\n",
792 servicep
->name
, servicep
->bootstrap
);
793 if (servicep
->servicetype
== REGISTERED
) {
794 debug("Service %s failed - deallocate", servicep
->name
);
795 mach_port_deallocate(mach_task_self(),np
);
796 mach_port_deallocate(mach_task_self(),servicep
->port
);
797 delete_service(servicep
);
800 * Allocate a new, backed-up port for this service.
802 log("Service %s failed - re-initialize",
804 msg_destroy_port(servicep
->port
);
805 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, &servicep
->port
);
806 if (result
!= KERN_SUCCESS
)
807 kern_fatal(result
, "port_allocate");
808 result
= mach_port_insert_right(bootstrap_self
, servicep
->port
, servicep
->port
, MACH_MSG_TYPE_MAKE_SEND
);
809 if (result
!= KERN_SUCCESS
)
810 kern_fatal(result
, "mach_port_insert_right");
812 result
= port_set_backup(mach_task_self(),
816 if (result
!= KERN_SUCCESS
)
817 kern_fatal(result
, "port_set_backup");
819 servicep
->isActive
= FALSE
;
824 error("Unexpected notification: %d", msg
.hdr
.msgh_id
);
829 else if (msg
.hdr
.msg_local_port
== backup_port
) {
830 notification_t
*not = (notification_t
*) &msg
.hdr
;
831 mach_port_name_t np
= not->notify_port
;
834 * Port sent back to us, server died.
836 info("port %d returned via backup", np
);
837 servicep
= lookup_service_by_port(np
);
838 if (servicep
!= NULL
) {
839 debug("Received %s notification for service %s",
840 not->notify_header
.msg_id
841 == NOTIFY_PORT_DESTROYED
842 ? "destroyed" : "receive rights",
844 log("Service %s failed - port backed-up", servicep
->name
);
845 ASSERT(canReceive(servicep
->port
));
846 servicep
->isActive
= FALSE
;
847 result
= port_set_backup(mach_task_self(),
851 if (result
!= KERN_SUCCESS
)
852 kern_fatal(result
, "port_set_backup");
854 msg_destroy_port(np
);
858 { /* must be a service request */
859 bootstrap_server(&msg
.hdr
, &reply
.hdr
);
861 debug("Handled request.");
863 reply
.hdr
.msgh_local_port
= MACH_PORT_NULL
;
864 result
= mach_msg(&reply
.hdr
, MACH_SEND_MSG
|MACH_SEND_TIMEOUT
, reply
.hdr
.msgh_size
, 0, MACH_PORT_NULL
,
865 BOOTSTRAP_REPLY_TIMEOUT
, MACH_PORT_NULL
);
867 debug("Reply sent.");
869 if (result
!= MACH_MSG_SUCCESS
) {
870 kern_error(result
, "msg_send");
873 /* deallocate uninteresting ports received in message */
874 msg_destroy(&msg
.hdr
);
879 * msg_destroy -- walk through a received message and deallocate any
880 * useless ports or out-of-line memory
883 msg_destroy(mach_msg_header_t
*m
)
885 #ifdef notyet /* [ */
887 msg_type_long_t
*mtlp
;
889 unsigned type
, size
, num
;
892 kern_return_t result
;
894 msg_destroy_port(m
->msg_remote_port
);
895 for ( mtp
= (msg_type_t
*)(m
+ 1)
896 ; (unsigned)mtp
- (unsigned)m
< m
->msg_size
899 inlne
= mtp
->msg_type_inline
;
900 if (mtp
->msg_type_longform
) {
901 mtlp
= (msg_type_long_t
*)mtp
;
902 type
= mtlp
->msg_type_long_name
;
903 size
= mtlp
->msg_type_long_size
;
904 num
= mtlp
->msg_type_long_number
;
905 dp
= (void *)(mtlp
+ 1);
907 type
= mtp
->msg_type_name
;
908 size
= mtp
->msg_type_size
;
909 num
= mtp
->msg_type_number
;
910 dp
= (void *)(mtp
+ 1);
913 mtp
= (msg_type_t
*)(dp
+ num
* (size
/BITS_PER_BYTE
));
915 mtp
= (msg_type_t
*)(dp
+ sizeof(void *));
918 if (MSG_TYPE_PORT_ANY(type
)) {
919 for (pp
= (mach_port_t
*)dp
; num
-- > 0; pp
++)
920 msg_destroy_port(*pp
);
923 result
= vm_deallocate(mach_task_self(), (vm_address_t
)dp
,
924 num
* (size
/BITS_PER_BYTE
));
925 if (result
!= KERN_SUCCESS
)
927 "vm_deallocate: msg_destroy");
930 #endif /* notyet ] */
934 * msg_destroy_port -- deallocate port if it's not important to bootstrap
935 * Bad name, this is used for things other than msg_destroy.
938 msg_destroy_port(mach_port_t p
)
940 if ( p
== MACH_PORT_NULL
941 || p
== mach_task_self()
942 || p
== mig_get_reply_port()
943 || p
== bootstrap_port_set
944 || p
== inherited_bootstrap_port
945 || lookup_service_by_port(p
)
946 || lookup_server_by_port(p
)
947 || lookup_bootstrap_by_port(p
) != &bootstraps
948 || lookup_bootstrap_req_by_port(p
) != &bootstraps
949 || p
== bootstraps
.bootstrap_port
950 || p
== bootstraps
.requestor_port
)
954 debug("Deallocating port %d", p
);
956 (void) mach_port_deallocate(mach_task_self(), p
);
960 canReceive(mach_port_t port
)
962 mach_port_type_t p_type
;
963 kern_return_t result
;
965 result
= mach_port_type(mach_task_self(), port
, &p_type
);
966 if (result
!= KERN_SUCCESS
) {
967 kern_error(result
, "port_type");
970 return ((p_type
& MACH_PORT_TYPE_RECEIVE
) != 0);
975 canSend(mach_port_t port
)
977 mach_port_type_t p_type
;
978 kern_return_t result
;
980 result
= mach_port_type(mach_task_self(), port
, &p_type
);
981 if (result
!= KERN_SUCCESS
) {
982 kern_error(result
, "port_type");
985 return ((p_type
& MACH_PORT_TYPE_PORT_RIGHTS
) != 0);
989 mach_port_t master_host_port
)
992 host_priority_info_data_t host_pri_info
;
993 mach_port_t default_processor_set_name
;
994 mach_port_t default_processor_set
;
995 policy_rr_base_data_t rr_base
;
996 policy_rr_limit_data_t rr_limit
;
997 kern_return_t result
;
998 mach_msg_type_number_t count
;
999 static char here
[] = "default_pager_set_policy";
1001 count
= HOST_PRIORITY_INFO_COUNT
;
1002 result
= host_info(mach_host_self(),
1004 (host_info_t
) &host_pri_info
,
1006 if (result
!= KERN_SUCCESS
)
1007 kern_fatal(result
, "Could not get host priority info");
1009 rr_base
.quantum
= 0;
1010 rr_base
.base_priority
= host_pri_info
.system_priority
;
1011 rr_limit
.max_priority
= host_pri_info
.system_priority
;
1013 (void)processor_set_default(mach_host_self(),
1014 &default_processor_set_name
);
1015 (void)host_processor_set_priv(master_host_port
,
1016 default_processor_set_name
,
1017 &default_processor_set
);
1019 result
= task_set_policy(mach_host_self(), default_processor_set
,
1021 (policy_base_t
) & rr_base
, POLICY_RR_BASE_COUNT
,
1022 (policy_limit_t
) & rr_limit
, POLICY_RR_LIMIT_COUNT
,
1024 if (result
!= KERN_SUCCESS
)
1025 kern_fatal(result
, "Could not set task policy ");