Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c16fd00f authored by Takaya Saeki's avatar Takaya Saeki
Browse files

libmodprobe: add thread safety annotations

Add thread safety annotations to let compilers check the thread safety
of `ModProbe` class. We used to have a data race issue in `ModProbe`
class. Utilizing thread safety annotation would mitigate future same
issues.

Bug: 400592897
Test: cuttlefish boots
Change-Id: I8c15394de5994b9f40ae8e2c53c6c8f8d7d36b31
parent ba17833f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ cc_library_static {
    name: "libmodprobe",
    cflags: [
        "-Werror",
        "-Wthread-safety",
    ],
    vendor_available: true,
    ramdisk_available: true,
+12 −8
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <atomic>
#include <functional>
#include <mutex>
#include <set>
@@ -31,10 +32,10 @@ class Modprobe {
    Modprobe(const std::vector<std::string>&, const std::string load_file = "modules.load",
             bool use_blocklist = true);

    bool LoadModulesParallel(int num_threads);
    bool LoadModulesParallel(int num_threads) EXCLUDES(module_loaded_lock_);
    bool LoadListedModules(bool strict = true);
    bool LoadWithAliases(const std::string& module_name, bool strict,
                         const std::string& parameters = "");
                         const std::string& parameters = "") EXCLUDES(module_loaded_lock_);
    bool Remove(const std::string& module_name);
    std::vector<std::string> ListModules(const std::string& pattern);
    bool GetAllDependencies(const std::string& module, std::vector<std::string>* pre_dependencies,
@@ -47,8 +48,9 @@ class Modprobe {
  private:
    std::string MakeCanonical(const std::string& module_path);
    bool InsmodWithDeps(const std::string& module_name, const std::string& parameters);
    bool Insmod(const std::string& path_name, const std::string& parameters);
    bool Rmmod(const std::string& module_name);
    bool Insmod(const std::string& path_name, const std::string& parameters)
            EXCLUDES(module_loaded_lock_);
    bool Rmmod(const std::string& module_name) EXCLUDES(module_loaded_lock_);
    std::vector<std::string> GetDependencies(const std::string& module);
    bool ModuleExists(const std::string& module_name);
    void AddOption(const std::string& module_name, const std::string& option_name,
@@ -65,6 +67,7 @@ class Modprobe {
    void ParseKernelCmdlineOptions();
    void ParseCfg(const std::string& cfg, std::function<bool(const std::vector<std::string>&)> f);

    // These non const fields are initialized by the constructor and never be modified.
    std::vector<std::pair<std::string, std::string>> module_aliases_;
    std::unordered_map<std::string, std::vector<std::string>> module_deps_;
    std::vector<std::pair<std::string, std::string>> module_pre_softdep_;
@@ -72,9 +75,10 @@ class Modprobe {
    std::vector<std::string> module_load_;
    std::unordered_map<std::string, std::string> module_options_;
    std::set<std::string> module_blocklist_;

    std::mutex module_loaded_lock_;
    std::unordered_set<std::string> module_loaded_;
    std::unordered_set<std::string> module_loaded_paths_;
    int module_count_ = 0;
    bool blocklist_enabled = false;
    std::unordered_set<std::string> module_loaded_ GUARDED_BY(module_loaded_lock_);
    std::unordered_set<std::string> module_loaded_paths_ GUARDED_BY(module_loaded_lock_);
    std::atomic_int module_count_ = 0;
    const bool blocklist_enabled = false;
};