- if (mappings != NULL &&
- mappings != &stack_mappings[0]) {
- kmem_free(kernel_map,
- (vm_offset_t) mappings,
- mappings_size);
- }
- mappings = NULL;
-
- return error;
-}
-
-int
-load_shared_file(
- __unused struct proc *p,
- __unused struct load_shared_file_args *uap,
- __unused int *retval)
-{
- return ENOSYS;
-}
-
-int
-reset_shared_file(
- __unused struct proc *p,
- __unused struct reset_shared_file_args *uap,
- __unused int *retval)
-{
- return ENOSYS;
-}
-
-int
-new_system_shared_regions(
- __unused struct proc *p,
- __unused struct new_system_shared_regions_args *uap,
- __unused int *retval)
-{
- return ENOSYS;
-}
-
-
-
-int
-clone_system_shared_regions(
- int shared_regions_active,
- int chain_regions,
- int base_vnode)
-{
- shared_region_mapping_t new_shared_region;
- shared_region_mapping_t next;
- shared_region_mapping_t old_shared_region;
- struct shared_region_task_mappings old_info;
- struct shared_region_task_mappings new_info;
-
- vm_get_shared_region(current_task(), &old_shared_region);
- old_info.self = (vm_offset_t)old_shared_region;
- shared_region_mapping_info(old_shared_region,
- &(old_info.text_region),
- &(old_info.text_size),
- &(old_info.data_region),
- &(old_info.data_size),
- &(old_info.region_mappings),
- &(old_info.client_base),
- &(old_info.alternate_base),
- &(old_info.alternate_next),
- &(old_info.fs_base),
- &(old_info.system),
- &(old_info.flags), &next);
-
- if (shared_regions_active ||
- base_vnode == ENV_DEFAULT_ROOT) {
- if (shared_file_create_system_region(&new_shared_region,
- old_info.fs_base,
- old_info.system))
- return ENOMEM;
- } else {
- if (old_shared_region &&
- base_vnode == ENV_DEFAULT_ROOT) {
- base_vnode = old_info.fs_base;
- }
- new_shared_region =
- lookup_default_shared_region(base_vnode,
- old_info.system);
- if (new_shared_region == NULL) {
- shared_file_boot_time_init(base_vnode,
- old_info.system);
- vm_get_shared_region(current_task(),
- &new_shared_region);
- } else {
- vm_set_shared_region(current_task(), new_shared_region);
- }
- if (old_shared_region)
- shared_region_mapping_dealloc(old_shared_region);
- }
- new_info.self = (vm_offset_t)new_shared_region;
- shared_region_mapping_info(new_shared_region,
- &(new_info.text_region),
- &(new_info.text_size),
- &(new_info.data_region),
- &(new_info.data_size),
- &(new_info.region_mappings),
- &(new_info.client_base),
- &(new_info.alternate_base),
- &(new_info.alternate_next),
- &(new_info.fs_base),
- &(new_info.system),
- &(new_info.flags), &next);
- if(shared_regions_active) {
- if(vm_region_clone(old_info.text_region, new_info.text_region)) {
- panic("clone_system_shared_regions: shared region mis-alignment 1");
- shared_region_mapping_dealloc(new_shared_region);
- return(EINVAL);
- }
- if (vm_region_clone(old_info.data_region, new_info.data_region)) {
- panic("clone_system_shared_regions: shared region mis-alignment 2");
- shared_region_mapping_dealloc(new_shared_region);
- return(EINVAL);
- }
- if (chain_regions) {
- /*
- * We want a "shadowed" clone, a private superset of the old
- * shared region. The info about the old mappings is still
- * valid for us.
- */
- shared_region_object_chain_attach(
- new_shared_region, old_shared_region);
- } else {
- /*
- * We want a completely detached clone with no link to
- * the old shared region. We'll be removing some mappings
- * in our private, cloned, shared region, so the old mappings
- * will become irrelevant to us. Since we have a private
- * "shared region" now, it isn't going to be shared with
- * anyone else and we won't need to maintain mappings info.
- */
- shared_region_object_chain_detached(new_shared_region);
- }
- }
- if (vm_map_region_replace(current_map(), old_info.text_region,
- new_info.text_region, old_info.client_base,
- old_info.client_base+old_info.text_size)) {
- panic("clone_system_shared_regions: shared region mis-alignment 3");
- shared_region_mapping_dealloc(new_shared_region);
- return(EINVAL);
- }
- if(vm_map_region_replace(current_map(), old_info.data_region,
- new_info.data_region,
- old_info.client_base + old_info.text_size,
- old_info.client_base
- + old_info.text_size + old_info.data_size)) {
- panic("clone_system_shared_regions: shared region mis-alignment 4");
- shared_region_mapping_dealloc(new_shared_region);
- return(EINVAL);
- }
- vm_set_shared_region(current_task(), new_shared_region);
-
- /* consume the reference which wasn't accounted for in object */
- /* chain attach */
- if (!shared_regions_active || !chain_regions)
- shared_region_mapping_dealloc(old_shared_region);
-
- SHARED_REGION_TRACE(
- SHARED_REGION_TRACE_INFO,
- ("shared_region: %p task=%p "
- "clone(active=%d, base=0x%x,chain=%d) "
- "old=%p[%x,%x,%x] new=%p[%x,%x,%x]\n",
- current_thread(), current_task(),
- shared_regions_active, base_vnode, chain_regions,
- old_shared_region,
- old_info.fs_base,
- old_info.system,
- old_info.flags,
- new_shared_region,
- new_info.fs_base,
- new_info.system,
- new_info.flags));
-
- return(0);
-
-}
-
-/* header for the profile name file. The profiled app info is held */
-/* in the data file and pointed to by elements in the name file */
-
-struct profile_names_header {
- unsigned int number_of_profiles;
- unsigned int user_id;
- unsigned int version;
- off_t element_array;
- unsigned int spare1;
- unsigned int spare2;
- unsigned int spare3;
-};
-
-struct profile_element {
- off_t addr;
- vm_size_t size;
- unsigned int mod_date;
- unsigned int inode;
- char name[12];
-};
-
-struct global_profile {
- struct vnode *names_vp;
- struct vnode *data_vp;
- vm_offset_t buf_ptr;
- unsigned int user;
- unsigned int age;
- unsigned int busy;
-};
-
-struct global_profile_cache {
- int max_ele;
- unsigned int age;
- struct global_profile profiles[3];
-};
-
-/* forward declarations */
-int bsd_open_page_cache_files(unsigned int user,
- struct global_profile **profile);
-void bsd_close_page_cache_files(struct global_profile *profile);
-int bsd_search_page_cache_data_base(
- struct vnode *vp,
- struct profile_names_header *database,
- char *app_name,
- unsigned int mod_date,
- unsigned int inode,
- off_t *profile,
- unsigned int *profile_size);
-
-struct global_profile_cache global_user_profile_cache =
- {3, 0, {{NULL, NULL, 0, 0, 0, 0},
- {NULL, NULL, 0, 0, 0, 0},
- {NULL, NULL, 0, 0, 0, 0}} };
-
-/* BSD_OPEN_PAGE_CACHE_FILES: */
-/* Caller provides a user id. This id was used in */
-/* prepare_profile_database to create two unique absolute */
-/* file paths to the associated profile files. These files */
-/* are either opened or bsd_open_page_cache_files returns an */
-/* error. The header of the names file is then consulted. */
-/* The header and the vnodes for the names and data files are */
-/* returned. */
-
-int
-bsd_open_page_cache_files(
- unsigned int user,
- struct global_profile **profile)
-{
- const char *cache_path = "/var/vm/app_profile/";
- struct proc *p;
- int error;
- vm_size_t resid;
- off_t resid_off;
- unsigned int lru;
- vm_size_t size;
-
- struct vnode *names_vp;
- struct vnode *data_vp;
- vm_offset_t names_buf;
- vm_offset_t buf_ptr;
-
- int profile_names_length;
- int profile_data_length;
- char *profile_data_string;
- char *profile_names_string;
- char *substring;
-
- off_t file_size;
- struct vfs_context context;
-
- kern_return_t ret;
-
- struct nameidata nd_names;
- struct nameidata nd_data;
- int i;
-
-
- p = current_proc();
-
- context.vc_proc = p;
- context.vc_ucred = kauth_cred_get();
-
-restart:
- for(i = 0; i<global_user_profile_cache.max_ele; i++) {
- if((global_user_profile_cache.profiles[i].user == user)
- && (global_user_profile_cache.profiles[i].data_vp
- != NULL)) {
- *profile = &global_user_profile_cache.profiles[i];
- /* already in cache, we're done */
- if ((*profile)->busy) {
- /*
- * drop funnel and wait
- */
- (void)tsleep((void *)
- *profile,
- PRIBIO, "app_profile", 0);
- goto restart;
- }
- (*profile)->busy = 1;
- (*profile)->age = global_user_profile_cache.age;
-
- /*
- * entries in cache are held with a valid
- * usecount... take an iocount which will
- * be dropped in "bsd_close_page_cache_files"
- * which is called after the read or writes to
- * these files are done
- */
- if ( (vnode_getwithref((*profile)->data_vp)) ) {
-
- vnode_rele((*profile)->data_vp);
- vnode_rele((*profile)->names_vp);
-
- (*profile)->data_vp = NULL;
- (*profile)->busy = 0;
- wakeup(*profile);
-
- goto restart;
- }
- if ( (vnode_getwithref((*profile)->names_vp)) ) {