+/*
+ * load a new default for a specified environment into the default share
+ * regions list. If a previous default exists for the envrionment specification
+ * it is returned along with its reference. It is expected that the new
+ * sytem region structure passes a reference.
+ */
+
+shared_region_mapping_t
+update_default_shared_region(
+ shared_region_mapping_t new_system_region)
+{
+ shared_region_mapping_t old_system_region;
+ unsigned int fs_base;
+ unsigned int system;
+
+ fs_base = new_system_region->fs_base;
+ system = new_system_region->system;
+ new_system_region->flags |= SHARED_REGION_SYSTEM;
+ default_regions_list_lock();
+ old_system_region = default_environment_shared_regions;
+
+ if((old_system_region != NULL) &&
+ (old_system_region->fs_base == fs_base) &&
+ (old_system_region->system == system)) {
+ new_system_region->default_env_list =
+ old_system_region->default_env_list;
+ default_environment_shared_regions = new_system_region;
+ default_regions_list_unlock();
+ old_system_region->flags |= SHARED_REGION_STALE;
+ return old_system_region;
+ }
+ if (old_system_region) {
+ while(old_system_region->default_env_list != NULL) {
+ if((old_system_region->default_env_list->fs_base == fs_base) &&
+ (old_system_region->default_env_list->system == system)) {
+ new_system_region->default_env_list =
+ old_system_region->default_env_list
+ ->default_env_list;
+ old_system_region->default_env_list =
+ new_system_region;
+ default_regions_list_unlock();
+ old_system_region->flags |= SHARED_REGION_STALE;
+ return old_system_region;
+ }
+ old_system_region = old_system_region->default_env_list;
+ }
+ }
+ /* If we get here, we are at the end of the system list and we */
+ /* did not find a pre-existing entry */
+ if(old_system_region) {
+ old_system_region->default_env_list = new_system_region;
+ } else {
+ default_environment_shared_regions = new_system_region;
+ }
+ default_regions_list_unlock();
+ return NULL;
+}
+
+/*
+ * lookup a system_shared_region for the environment specified. If one is
+ * found, it is returned along with a reference against the structure
+ */
+
+shared_region_mapping_t
+lookup_default_shared_region(
+ unsigned int fs_base,
+ unsigned int system)
+{
+ shared_region_mapping_t system_region;
+ default_regions_list_lock();
+ system_region = default_environment_shared_regions;
+
+ while(system_region != NULL) {
+ if((system_region->fs_base == fs_base) &&
+ (system_region->system == system)) {
+ break;
+ }
+ system_region = system_region->default_env_list;
+ }
+ if(system_region)
+ shared_region_mapping_ref(system_region);
+ default_regions_list_unlock();
+ return system_region;
+}
+
+/*
+ * remove a system_region default if it appears in the default regions list.
+ * Drop a reference on removal.
+ */
+
+__private_extern__ void
+remove_default_shared_region_lock(
+ shared_region_mapping_t system_region,
+ int need_lock)
+{
+ shared_region_mapping_t old_system_region;
+ unsigned int fs_base;
+ unsigned int system;
+
+ default_regions_list_lock();
+ old_system_region = default_environment_shared_regions;
+
+ if(old_system_region == NULL) {
+ default_regions_list_unlock();
+ return;
+ }
+
+ if (old_system_region == system_region) {
+ default_environment_shared_regions
+ = old_system_region->default_env_list;
+ old_system_region->flags |= SHARED_REGION_STALE;
+ shared_region_mapping_dealloc_lock(old_system_region,
+ need_lock);
+ default_regions_list_unlock();
+ return;
+ }
+
+ while(old_system_region->default_env_list != NULL) {
+ if(old_system_region->default_env_list == system_region) {
+ shared_region_mapping_t dead_region;
+ dead_region = old_system_region->default_env_list;
+ old_system_region->default_env_list =
+ old_system_region->default_env_list->default_env_list;
+ dead_region->flags |= SHARED_REGION_STALE;
+ shared_region_mapping_dealloc_lock(dead_region,
+ need_lock);
+ default_regions_list_unlock();
+ return;
+ }
+ old_system_region = old_system_region->default_env_list;
+ }
+ default_regions_list_unlock();
+}
+
+/*
+ * Symbol compatability; we believe shared_region_mapping_dealloc_lock() is
+ * the only caller. Remove this stub function and the corresponding symbol
+ * export for Merlot.
+ */
+void
+remove_default_shared_region(
+ shared_region_mapping_t system_region)
+{
+ remove_default_shared_region_lock(system_region, 1);
+}
+
+void
+remove_all_shared_regions()
+{
+ shared_region_mapping_t system_region;
+ shared_region_mapping_t next_system_region;
+
+ default_regions_list_lock();
+ system_region = default_environment_shared_regions;
+
+ if(system_region == NULL) {
+ default_regions_list_unlock();
+ return;
+ }
+
+ while(system_region != NULL) {
+ next_system_region = system_region->default_env_list;
+ system_region->flags |= SHARED_REGION_STALE;
+ shared_region_mapping_dealloc(system_region);
+ system_region = next_system_region;
+ }
+ default_environment_shared_regions = NULL;
+ default_regions_list_unlock();
+}
+
+/* shared_com_boot_time_init initializes the common page shared data and */
+/* text region. This region is semi independent of the split libs */
+/* and so its policies have to be handled differently by the code that */
+/* manipulates the mapping of shared region environments. However, */
+/* the shared region delivery system supports both */
+shared_com_boot_time_init()
+{
+ kern_return_t kret;
+ vm_named_entry_t named_entry;
+
+ if(com_region_handle) {
+ panic("shared_com_boot_time_init: "
+ "com_region_handle already set\n");
+ }
+
+ /* create com page region */
+ if(kret = vm_region_object_create(kernel_map,
+ com_region_size,
+ &com_region_handle)) {
+ panic("shared_com_boot_time_init: "
+ "unable to create comm page\n");
+ return;
+ }
+ /* now set export the underlying region/map */
+ named_entry = (vm_named_entry_t)com_region_handle->ip_kobject;
+ com_region_map = named_entry->backing.map;
+ /* wrap the com region in its own shared file mapping structure */
+ shared_region_mapping_create(com_region_handle,
+ com_region_size, NULL, 0, 0,
+ GLOBAL_COM_REGION_BASE, &com_mapping_resource,
+ 0, 0);
+
+}
+