/* * Routine: macx_triggers * Function: * Syscall interface to set the call backs for low and * high water marks. */ int macx_triggers( struct macx_triggers_args *args) { int hi_water = args->hi_water; int low_water = args->low_water; int flags = args->flags; mach_port_t trigger_name = args->alert_port; kern_return_t kr; memory_object_default_t default_pager; ipc_port_t trigger_port; default_pager = MEMORY_OBJECT_DEFAULT_NULL; kr = host_default_memory_manager(host_priv_self(), &default_pager, 0); if(kr != KERN_SUCCESS) { return EINVAL; } if ((flags & SWAP_ENCRYPT_ON) && (flags & SWAP_ENCRYPT_OFF)) { /* can't have it both ways */ return EINVAL; } if (default_pager_init_flag == 0) { start_def_pager(NULL); default_pager_init_flag = 1; } if (flags & SWAP_ENCRYPT_ON) { /* ENCRYPTED SWAP: tell default_pager to encrypt */ default_pager_triggers(default_pager, 0, 0, SWAP_ENCRYPT_ON, IP_NULL); } else if (flags & SWAP_ENCRYPT_OFF) { /* ENCRYPTED SWAP: tell default_pager not to encrypt */ default_pager_triggers(default_pager, 0, 0, SWAP_ENCRYPT_OFF, IP_NULL); } if (flags & HI_WAT_ALERT) { trigger_port = trigger_name_to_port(trigger_name); if(trigger_port == NULL) { return EINVAL; } /* trigger_port is locked and active */ ipc_port_make_send_locked(trigger_port); /* now unlocked */ default_pager_triggers(default_pager, hi_water, low_water, HI_WAT_ALERT, trigger_port); } if (flags & LO_WAT_ALERT) { trigger_port = trigger_name_to_port(trigger_name); if(trigger_port == NULL) { return EINVAL; } /* trigger_port is locked and active */ ipc_port_make_send_locked(trigger_port); /* and now its unlocked */ default_pager_triggers(default_pager, hi_water, low_water, LO_WAT_ALERT, trigger_port); } /* * Set thread scheduling priority and policy for the current thread * it is assumed for the time being that the thread setting the alert * is the same one which will be servicing it. * * XXX This does not belong in the kernel XXX */ { thread_precedence_policy_data_t pre; thread_extended_policy_data_t ext; ext.timeshare = FALSE; pre.importance = INT32_MAX; thread_policy_set(current_thread(), THREAD_EXTENDED_POLICY, (thread_policy_t)&ext, THREAD_EXTENDED_POLICY_COUNT); thread_policy_set(current_thread(), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&pre, THREAD_PRECEDENCE_POLICY_COUNT); } current_thread()->options |= TH_OPT_VMPRIV; return 0; }
/* * Routine: mach_macx_triggers * Function: * Syscall interface to set the call backs for low and * high water marks. */ int mach_macx_triggers( struct macx_triggers_args *args) { int hi_water = args->hi_water; int low_water = args->low_water; int flags = args->flags; mach_port_t trigger_name = args->alert_port; kern_return_t kr; memory_object_default_t default_pager; ipc_port_t trigger_port; default_pager = MEMORY_OBJECT_DEFAULT_NULL; kr = host_default_memory_manager(host_priv_self(), &default_pager, 0); if(kr != KERN_SUCCESS) { return EINVAL; } if (((flags & SWAP_ENCRYPT_ON) && (flags & SWAP_ENCRYPT_OFF)) || ((flags & SWAP_COMPACT_ENABLE) && (flags & SWAP_COMPACT_DISABLE))) { /* can't have it both ways */ return EINVAL; } if (default_pager_init_flag == 0) { start_def_pager(NULL); default_pager_init_flag = 1; } if (flags & SWAP_ENCRYPT_ON) { /* ENCRYPTED SWAP: tell default_pager to encrypt */ default_pager_triggers(default_pager, 0, 0, SWAP_ENCRYPT_ON, IP_NULL); } else if (flags & SWAP_ENCRYPT_OFF) { /* ENCRYPTED SWAP: tell default_pager not to encrypt */ default_pager_triggers(default_pager, 0, 0, SWAP_ENCRYPT_OFF, IP_NULL); } if (flags & USE_EMERGENCY_SWAP_FILE_FIRST) { /* * Time to switch to the emergency segment. */ return default_pager_triggers(default_pager, 0, 0, USE_EMERGENCY_SWAP_FILE_FIRST, IP_NULL); } if (flags & SWAP_FILE_CREATION_ERROR) { /* * For some reason, the dynamic pager failed to create a swap file. */ trigger_port = trigger_name_to_port(trigger_name); if(trigger_port == NULL) { return EINVAL; } /* trigger_port is locked and active */ ipc_port_make_send_locked(trigger_port); /* now unlocked */ default_pager_triggers(default_pager, 0, 0, SWAP_FILE_CREATION_ERROR, trigger_port); } if (flags & HI_WAT_ALERT) { trigger_port = trigger_name_to_port(trigger_name); if(trigger_port == NULL) { return EINVAL; } /* trigger_port is locked and active */ ipc_port_make_send_locked(trigger_port); /* now unlocked */ default_pager_triggers(default_pager, hi_water, low_water, HI_WAT_ALERT, trigger_port); } if (flags & LO_WAT_ALERT) { trigger_port = trigger_name_to_port(trigger_name); if(trigger_port == NULL) { return EINVAL; } /* trigger_port is locked and active */ ipc_port_make_send_locked(trigger_port); /* and now its unlocked */ default_pager_triggers(default_pager, hi_water, low_water, LO_WAT_ALERT, trigger_port); } if (flags & PROC_RESUME) { /* * For this call, hi_water is used to pass in the pid of the process we want to resume * or unthrottle. This is of course restricted to the superuser (checked inside of * proc_resetpcontrol). */ return proc_resetpcontrol(hi_water); } /* * Set thread scheduling priority and policy for the current thread * it is assumed for the time being that the thread setting the alert * is the same one which will be servicing it. * * XXX This does not belong in the kernel XXX */ if (flags & HI_WAT_ALERT) { thread_precedence_policy_data_t pre; thread_extended_policy_data_t ext; ext.timeshare = FALSE; pre.importance = INT32_MAX; thread_policy_set(current_thread(), THREAD_EXTENDED_POLICY, (thread_policy_t)&ext, THREAD_EXTENDED_POLICY_COUNT); thread_policy_set(current_thread(), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&pre, THREAD_PRECEDENCE_POLICY_COUNT); current_thread()->options |= TH_OPT_VMPRIV; } if (flags & (SWAP_COMPACT_DISABLE | SWAP_COMPACT_ENABLE)) { return macx_backing_store_compaction(flags & (SWAP_COMPACT_DISABLE | SWAP_COMPACT_ENABLE)); } return 0; }