+
+#ifdef __APPLE__
+// XX another copy of this routine is in shutdown.c; it would be nice to share
+
+#define LCK_MAXTRIES 10
+#define LCK_DELAY 30
+/*
+ * contact kextd to lock for reboot
+ */
+int
+reserve_reboot()
+{
+ int rval = ELAST+1;
+ kern_return_t macherr = KERN_FAILURE;
+ mach_port_t tport, bsport, kxport, myport = MACH_PORT_NULL;
+ int busyStatus, nretries = LCK_MAXTRIES;
+ dev_path_t busyDev = "<unknown>";
+
+ // find kextd
+ tport = mach_task_self();
+ if (tport == MACH_PORT_NULL) goto finish;
+ macherr = task_get_bootstrap_port(tport, &bsport);
+ if (macherr) goto finish;
+ macherr = bootstrap_look_up(bsport, KEXTD_SERVER_NAME, &kxport);
+ if (macherr) goto finish;
+
+ // allocate a port to pass to kextd (in case we die)
+ macherr = mach_port_allocate(tport, MACH_PORT_RIGHT_RECEIVE, &myport);
+ if (macherr) goto finish;
+
+ // loop trying to lock for reboot (i.e. no volumes are busy)
+ do {
+ nretries--;
+ macherr = kextmanager_lock_reboot(kxport, myport, busyDev, &busyStatus);
+ if (macherr) goto finish;
+
+ if (busyStatus == EBUSY) {
+ if (*busyDev) {
+ warnx("%s is busy updating; delaying reboot (%d retries left)",
+ busyDev, nretries);
+ } else
+ warnx("kextd still starting up");
+ if (nretries) sleep(LCK_DELAY); // don't sleep the last time
+ }
+ } while (busyStatus == EBUSY && nretries > 0);
+
+ rval = busyStatus;
+
+finish:
+ if (macherr == BOOTSTRAP_UNKNOWN_SERVICE) {
+ mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
+ rval = 0;
+ } else if (macherr) {
+ warnx("couldn't lock kext manager for reboot: %s",
+ mach_error_string(macherr));
+ rval = ELAST + 1;
+ }
+ if (rval && myport != MACH_PORT_NULL) {
+ mach_port_mod_refs(tport, myport, MACH_PORT_RIGHT_RECEIVE, -1);
+ }
+
+ return rval;
+}
+#endif