The Big Kernel Lock

本文深入分析了BKL(Binary Kernel Lock)与Semaphore的使用场景,阐述了它们在并发控制中的性能表现及潜在问题,如系统空闲时间增加和线程间竞争引发的bug,并提出了一种更优的解决方案——Spinlock,以提高系统效率并减少资源冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://lwn.net/Articles/281437/

BLK    

    ==> semaphore

            ==> The semaphore is handled over to the new thread waiting for it. This introduces performance penalty --- the system's running idle almost 50% of the time.

            ==> lock stealing: A thread acquiring the semaphore could get it once the semaphore becomes available, regardless of whether or not the thread's at the head of the queue. However, this introduces bugs in some situation.

 

    ==> spin lock

               ==> makes the BKL non-preemptible. However, this sub-optimal BKL is currently the best solution for this trade-off problem.

转载于:https://my.oschina.net/u/158589/blog/48707

Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) { auto lock = LockExclusive(); if (!lock) return Return::Error(); auto update_state = ReadUpdateState(lock.get()); if (update_state != UpdateState::Initiated) { LOG(ERROR) << "Cannot create update snapshots in state " << update_state; return Return::Error(); } // TODO(b/134949511): remove this check. Right now, with overlayfs mounted, the scratch // partition takes up a big chunk of space in super, causing COW images to be created on // retrofit Virtual A/B devices. if (device_->IsOverlayfsSetup()) { LOG(ERROR) << "Cannot create update snapshots with overlayfs setup. Run `adb enable-verity`" << ", reboot, then try again."; return Return::Error(); } const auto& opener = device_->GetPartitionOpener(); auto current_suffix = device_->GetSlotSuffix(); uint32_t current_slot = SlotNumberForSlotSuffix(current_suffix); auto target_suffix = device_->GetOtherSlotSuffix(); uint32_t target_slot = SlotNumberForSlotSuffix(target_suffix); auto current_super = device_->GetSuperDevice(current_slot); auto current_metadata = MetadataBuilder::New(opener, current_super, current_slot); if (current_metadata == nullptr) { LOG(ERROR) << "Cannot create metadata builder."; return Return::Error(); } auto target_metadata = MetadataBuilder::NewForUpdate(opener, current_super, current_slot, target_slot); if (target_metadata == nullptr) { LOG(ERROR) << "Cannot create target metadata builder."; return Return::Error(); } // Delete partitions with target suffix in |current_metadata|. Otherwise, // partition_cow_creator recognizes these left-over partitions as used space. for (const auto& group_name : current_metadata->ListGroups()) { if (android::base::EndsWith(group_name, target_suffix)) { current_metadata->RemoveGroupAndPartitions(group_name); } } SnapshotMetadataUpdater metadata_updater(target_metadata.get(), target_slot, manifest); if (!metadata_updater.Update()) { LOG(ERROR) << "Cannot calculate new metadata."; return Return::Error(); } // Delete previous COW partitions in current_metadata so that PartitionCowCreator marks those as // free regions. UnmapAndDeleteCowPartition(current_metadata.get()); // Check that all these metadata is not retrofit dynamic partitions. Snapshots on // devices with retrofit dynamic partitions does not make sense. // This ensures that current_metadata->GetFreeRegions() uses the same device // indices as target_metadata (i.e. 0 -> "super"). // This is also assumed in MapCowDevices() call below. CHECK(current_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME && target_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME); std::map<std::string, SnapshotStatus> all_snapshot_status; // In case of error, automatically delete devices that are created along the way. // Note that "lock" is destroyed after "created_devices", so it is safe to use |lock| for // these devices. AutoDeviceList created_devices; const auto& dap_metadata = manifest.dynamic_partition_metadata(); CowOptions options; CowWriter writer(options); bool cow_format_support = true; if (dap_metadata.cow_version() < writer.GetCowVersion()) { cow_format_support = false; } LOG(INFO) << " dap_metadata.cow_version(): " << dap_metadata.cow_version() << " writer.GetCowVersion(): " << writer.GetCowVersion(); bool use_compression = IsCompressionEnabled() && dap_metadata.vabc_enabled() && !device_->IsRecovery() && cow_format_support; std::string compression_algorithm; if (use_compression) { compression_algorithm = dap_metadata.vabc_compression_param(); if (compression_algorithm.empty()) { // Older OTAs don't set an explicit compression type, so default to gz. compression_algorithm = "gz"; } } else { compression_algorithm = "none"; } PartitionCowCreator cow_creator{ .target_metadata = target_metadata.get(), .target_suffix = target_suffix, .target_partition = nullptr, .current_metadata = current_metadata.get(), .current_suffix = current_suffix, .update = nullptr, .extra_extents = {}, .compression_enabled = use_compression, .compression_algorithm = compression_algorithm, }; auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices, &all_snapshot_status); if (!ret.is_ok()) return ret; auto exported_target_metadata = target_metadata->Export(); if (exported_target_metadata == nullptr) { LOG(ERROR) << "Cannot export target metadata"; return Return::Error(); } ret = InitializeUpdateSnapshots(lock.get(), target_metadata.get(), exported_target_metadata.get(), target_suffix, all_snapshot_status); if (!ret.is_ok()) return ret; if (!UpdatePartitionTable(opener, device_->GetSuperDevice(target_slot), *exported_target_metadata, target_slot)) { LOG(ERROR) << "Cannot write target metadata"; return Return::Error(); } // If compression is enabled, we need to retain a copy of the old metadata // so we can access original blocks in case they are moved around. We do // not want to rely on the old super metadata slot because we don't // guarantee its validity after the slot switch is successful. if (cow_creator.compression_enabled) { auto metadata = current_metadata->Export(); if (!metadata) { LOG(ERROR) << "Could not export current metadata"; return Return::Error(); } auto path = GetOldPartitionMetadataPath(); if (!android::fs_mgr::WriteToImageFile(path, *metadata.get())) { LOG(ERROR) << "Cannot write old metadata to " << path; return Return::Error(); } } SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get()); status.set_state(update_state); status.set_compression_enabled(cow_creator.compression_enabled); if (cow_creator.compression_enabled) { if (!device()->IsTestDevice()) { bool userSnapshotsEnabled = IsUserspaceSnapshotsEnabled(); const std::string UNKNOWN = "unknown"; const std::string vendor_release = android::base::GetProperty( "ro.vendor.build.version.release_or_codename", UNKNOWN); // No user-space snapshots if vendor partition is on Android 12 if (vendor_release.find("12") != std::string::npos) { LOG(INFO) << "Userspace snapshots disabled as vendor partition is on Android: " << vendor_release; userSnapshotsEnabled = false; } // Userspace snapshots is enabled only if compression is enabled status.set_userspace_snapshots(userSnapshotsEnabled); if (userSnapshotsEnabled) { is_snapshot_userspace_ = true; status.set_io_uring_enabled(IsIouringEnabled()); LOG(INFO) << "Userspace snapshots enabled"; } else { is_snapshot_userspace_ = false; LOG(INFO) << "Userspace snapshots disabled"; } // Terminate stale daemon if any std::unique_ptr<SnapuserdClient> snapuserd_client = SnapuserdClient::Connect(kSnapuserdSocket, 5s); if (snapuserd_client) { snapuserd_client->DetachSnapuserd(); snapuserd_client->CloseConnection(); snapuserd_client = nullptr; } // Clear the cached client if any if (snapuserd_client_) { snapuserd_client_->CloseConnection(); snapuserd_client_ = nullptr; } } else { bool userSnapshotsEnabled = true; const std::string UNKNOWN = "unknown"; const std::string vendor_release = android::base::GetProperty( "ro.vendor.build.version.release_or_codename", UNKNOWN); // No user-space snapshots if vendor partition is on Android 12 if (vendor_release.find("12") != std::string::npos) { LOG(INFO) << "Userspace snapshots disabled as vendor partition is on Android: " << vendor_release; userSnapshotsEnabled = false; } userSnapshotsEnabled = (userSnapshotsEnabled && !IsDmSnapshotTestingEnabled()); status.set_userspace_snapshots(userSnapshotsEnabled); if (!userSnapshotsEnabled) { is_snapshot_userspace_ = false; LOG(INFO) << "User-space snapshots disabled for testing"; } else { is_snapshot_userspace_ = true; LOG(INFO) << "User-space snapshots enabled for testing"; } } } if (!WriteSnapshotUpdateStatus(lock.get(), status)) { LOG(ERROR) << "Unable to write new update state"; return Return::Error(); } created_devices.Release(); LOG(INFO) << "Successfully created all snapshots for target slot " << target_suffix; return Return::Ok(); }解析王法
07-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值