Power Vote 投票仲裁机制
1. 模块定位与核心价值
1.1 问题域
在华为 MATE X5 电源管理系统中,同一个参数可能被多个模块同时控制,这会导致冲突和混乱:
典型冲突场景:
充电电流限制问题:
├─ 温度管理模块:温度 > 45°C,限制充电电流 ≤ 2000mA
├─ 电池健康模块:循环次数 > 500,限制充电电流 ≤ 1500mA
├─ 用户设置模块:用户设置省电模式,限制充电电流 ≤ 1000mA
├─ USB 识别模块:识别为 SDP,限制充电电流 ≤ 500mA
└─ 直充模块: 检测到快充适配器,需要充电电流 = 5000mA
❌ 问题:哪个模块的设置应该生效?如何协调?传统解决方案的缺陷:
- 硬编码优先级:修改逻辑需要改代码
- 全局变量竞争:多线程访问不安全
- 难以调试:无法追溯最终值由谁决定
1.2 Power Vote 解决方案
核心思想: 将参数控制权转化为"投票机制"
投票箱(Vote Object): "charging_current"
类型:取最小值(SET_MIN)
投票过程:
┌──────────────────────────────────────────────┐
│ 客户端投票 │
├──────────────────────────────────────────────┤
│ "temp_mgr" enabled=true value=2000 │
│ "bat_health" enabled=true value=1500 │
│ "user_settings" enabled=true value=1000 │
│ "usb_detect" enabled=true value=500 │ ← 最小值
│ "direct_charge" enabled=false value=5000 │ (未使能)
└──────────────────────────────────────────────┘
↓
仲裁结果:500mA
(由 "usb_detect" 决定)
↓
回调函数:set_charging_current(500)1.3 架构设计
┌─────────────────────────────────────────────────────┐
│ Power Vote 模块 (cc_common_module/power_vote) │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ 全局投票对象链表 (g_power_vote_list) │ │
│ │ ├─ Vote Object 1: "charging_current" │ │
│ │ ├─ Vote Object 2: "charging_voltage" │ │
│ │ ├─ Vote Object 3: "input_suspend" │ │
│ │ └─ Vote Object N: ... │ │
│ └────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ 投票类型(仲裁策略) │ │
│ │ ├─ POWER_VOTE_SET_MIN (取最小值) │ │
│ │ ├─ POWER_VOTE_SET_MAX (取最大值) │ │
│ │ └─ POWER_VOTE_SET_ANY (任意使能即true) │ │
│ └────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────────┐ │
│ │ 调试接口 │ │
│ │ /sys/kernel/debug/hw_power/power_vote/ │ │
│ │ └─ object (查看所有投票状态) │ │
│ └────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘2. 核心数据结构
2.1 投票对象(Vote Object)
c
struct power_vote_object {
const char *name; // 投票对象名称(如 "charging_current")
struct list_head list; // 链表节点(挂载到全局链表)
struct mutex lock; // 互斥锁(保护并发访问)
int type; // 投票类型(SET_MIN/SET_MAX/SET_ANY)
bool voted_on; // 是否已执行过投票
int eff_client_id; // 当前生效的客户端 ID
int eff_result; // 当前生效的投票结果
int override_result; // 覆盖结果(-1 表示无覆盖)
struct power_vote_client_data clients[POWER_VOTE_MAX_CLIENTS]; // 客户端数组(最多32个)
void *data; // 回调函数私有数据
int (*cb)(struct power_vote_object *obj, void *data,
int result, const char *client_str); // 结果变化时的回调函数
};字段说明:
name:投票对象的唯一标识符type:仲裁策略(决定如何从多个投票中选出最终结果)eff_result:当前生效的值(仲裁后的最终结果)override_result:强制覆盖值(用于调试或特殊场景,-1表示不覆盖)cb:当仲裁结果变化时调用的回调函数
2.2 客户端数据(Client Data)
c
struct power_vote_client_data {
char *name; // 客户端名称(如 "temp_mgr", "usb_detect")
bool enabled; // 是否使能(只有使能的投票才参与仲裁)
int value; // 投票值
};客户端管理:
- 每个投票对象最多支持 32 个客户端(
POWER_VOTE_MAX_CLIENTS) - 客户端动态注册(首次投票时自动创建)
- 客户端名称不可重复
2.3 投票类型枚举
c
enum power_vote_type {
POWER_VOTE_SET_MIN, // 取所有使能投票中的最小值
POWER_VOTE_SET_MAX, // 取所有使能投票中的最大值
POWER_VOTE_SET_ANY, // 任意一个使能即为 true(用于开关控制)
};3. 三种仲裁策略详解
3.1 SET_MIN - 取最小值
使用场景: 限制类参数(充电电流、输入电压等)
仲裁逻辑:
c
static void power_vote_set_min(struct power_vote_object *obj,
int client_id, int *eff_result, int *eff_id)
{
int i;
*eff_result = INT_MAX; // 初始化为最大整数
*eff_id = -1;
// 遍历所有客户端
for (i = 0; i < POWER_VOTE_MAX_CLIENTS; i++) {
if (!obj->clients[i].name)
break;
// 只考虑使能的投票
if (!obj->clients[i].enabled)
continue;
// 更新最小值
if (*eff_result > obj->clients[i].value) {
*eff_result = obj->clients[i].value;
*eff_id = i;
}
}
// 如果没有使能的投票,返回 -1
if (*eff_id == -1)
*eff_result = -1;
}应用示例:充电电流限制
c
// 创建投票对象
power_vote_create_object("fcc_votable",
POWER_VOTE_SET_MIN,
fcc_callback,
NULL);
// 各模块投票
power_vote_set("fcc_votable", "THERMAL", true, 2000); // 温度限制2A
power_vote_set("fcc_votable", "USER_LIMIT", true, 1500); // 用户限制1.5A
power_vote_set("fcc_votable", "USB_ICL", true, 500); // USB限制500mA ← 最小
power_vote_set("fcc_votable", "BATTERY_FULL", false, 0); // 未使能,忽略
// 仲裁结果:500mA(由 USB_ICL 决定)3.2 SET_MAX - 取最大值
使用场景: 优先级选择(充电优先级、功率等级等)
仲裁逻辑:
c
static void power_vote_set_max(struct power_vote_object *obj,
int client_id, int *eff_result, int *eff_id)
{
int i;
*eff_result = INT_MIN; // 初始化为最小整数
*eff_id = -1;
for (i = 0; i < POWER_VOTE_MAX_CLIENTS; i++) {
if (!obj->clients[i].name)
break;
if (!obj->clients[i].enabled)
continue;
// 更新最大值
if (*eff_result < obj->clients[i].value) {
*eff_result = obj->clients[i].value;
*eff_id = i;
}
}
if (*eff_id == -1)
*eff_result = -1;
}应用示例:电源模式选择
c
// 创建投票对象
power_vote_create_object("power_mode",
POWER_VOTE_SET_MAX,
mode_callback,
NULL);
// 各模块投票(值越大优先级越高)
power_vote_set("power_mode", "LOW_POWER", true, 1); // 省电模式
power_vote_set("power_mode", "BALANCED", true, 2); // 均衡模式
power_vote_set("power_mode", "PERFORMANCE", true, 3); // 性能模式 ← 最大
power_vote_set("power_mode", "ULTRA_SAVE", false, 0); // 未使能
// 仲裁结果:3(性能模式生效)3.3 SET_ANY - 任意使能即为真
使用场景: 开关控制(充电使能、输入暂停等)
仲裁逻辑:
c
static void power_vote_set_any(struct power_vote_object *obj,
int client_id, int *eff_result, int *eff_id)
{
int i;
*eff_result = 0; // 初始化为 false
*eff_id = client_id;
// 统计使能的客户端数量
for (i = 0; i < POWER_VOTE_MAX_CLIENTS; i++) {
if (!obj->clients[i].name)
break;
if (obj->clients[i].enabled)
*eff_result += 1;
}
// 只要有任意客户端使能,结果就为 true
if (*eff_result)
*eff_result = 1; // true
}应用示例:输入暂停控制
c
// 创建投票对象
power_vote_create_object("usb_suspend",
POWER_VOTE_SET_ANY,
suspend_callback,
NULL);
// 各模块投票(value值被忽略,仅看enabled)
power_vote_set("usb_suspend", "OTG_MODE", true, 0); // OTG模式暂停充电
power_vote_set("usb_suspend", "OVER_TEMP", false, 0); // 温度正常,不暂停
power_vote_set("usb_suspend", "USER_DISABLE", false, 0); // 用户未禁用
// 仲裁结果:true(因为 OTG_MODE enabled=true)
// 只要有一个客户端 enabled=true,结果就是 true4. 核心 API 详解
4.1 创建投票对象
c
int power_vote_create_object(const char *name,
int vote_type, power_vote_cb cb, void *data)参数说明:
name:投票对象名称(唯一标识符)vote_type:仲裁类型(SET_MIN/SET_MAX/SET_ANY)cb:结果变化时的回调函数data:回调函数的私有数据指针
回调函数原型:
c
int callback(struct power_vote_object *obj,
void *data,
int result,
const char *client_str)
{
// obj: 投票对象指针
// data: 创建时传入的私有数据
// result: 仲裁后的结果值
// client_str: 决定结果的客户端名称
hwlog_info("New result: %d from %s\n", result, client_str);
// 实际执行参数设置
set_hardware_register(result);
return 0; // 成功返回0,失败返回负值
}使用示例:
c
static int fcc_callback(struct power_vote_object *obj,
void *data,
int result,
const char *client_str)
{
struct charger_dev *chg_dev = (struct charger_dev *)data;
hwlog_info("Set FCC to %d mA by %s\n", result, client_str);
return charger_set_current(chg_dev, result);
}
static int __init charger_init(void)
{
struct charger_dev *chg_dev = get_charger_device();
// 创建充电电流投票对象
power_vote_create_object("FCC",
POWER_VOTE_SET_MIN,
fcc_callback,
chg_dev);
return 0;
}4.2 投票(设置值)
c
int power_vote_set(const char *name,
const char *client_name, bool enabled, int value)参数说明:
name:投票对象名称client_name:客户端名称(自动注册,无需预先创建)enabled:是否使能(false时不参与仲裁)value:投票值
工作流程:
1. 查找投票对象
↓
2. 获取/创建客户端 ID
↓
3. 检查投票是否相同(去重优化)
↓
4. 执行仲裁(根据type选择策略)
↓
5. 如果结果变化,调用回调函数
↓
6. 返回结果使用示例:
c
// 温度管理模块
void thermal_monitor_work(void)
{
int temp = get_battery_temp();
if (temp > 45) {
// 温度过高,限制电流为 1500mA
power_vote_set("FCC", "THERMAL", true, 1500);
} else {
// 温度正常,取消限制
power_vote_set("FCC", "THERMAL", false, 0);
}
}
// USB 识别模块
void usb_type_changed(int type)
{
switch (type) {
case USB_SDP: // 标准下游端口
power_vote_set("FCC", "USB_ICL", true, 500);
break;
case USB_DCP: // 专用充电端口
power_vote_set("FCC", "USB_ICL", true, 2000);
break;
case USB_CDP: // 充电下游端口
power_vote_set("FCC", "USB_ICL", true, 1500);
break;
}
}4.3 强制覆盖
c
int power_vote_set_override(const char *name,
const char *client_name, bool enabled, int value)功能: 忽略所有其他投票,强制使用指定值(用于调试或紧急场景)
使用示例:
c
// 调试场景:强制设置充电电流为 3000mA
power_vote_set_override("FCC", "DEBUG", true, 3000);
// 恢复正常投票机制
power_vote_set_override("FCC", "DEBUG", false, 0);4.4 查询接口
c
// 查询客户端是否使能
bool power_vote_is_client_enabled_locked(const char *name,
const char *client_name, bool lock_flag);
// 查询客户端投票值
int power_vote_get_client_value_locked(const char *name,
const char *client_name, bool lock_flag);
// 查询当前生效结果
int power_vote_get_effective_result_locked(const char *name,
bool lock_flag);lock_flag 参数说明:
true:内部会加锁(线程安全)false:调用者已持有锁(避免死锁)
5. 典型应用场景
5.1 充电电流动态调整
场景: 多个因素同时影响充电电流
c
// 初始化
static int charger_fcc_callback(struct power_vote_object *obj,
void *data, int result, const char *client)
{
hwlog_info("Set charging current to %d mA (by %s)\n", result, client);
return charger_ic_set_current(result);
}
static void charger_init(void)
{
power_vote_create_object("FCC_VOTABLE",
POWER_VOTE_SET_MIN,
charger_fcc_callback,
NULL);
}
// 温度管理投票
void thermal_work(void)
{
int temp = get_battery_temp();
if (temp < 10) {
// 低温限制 500mA
power_vote_set("FCC_VOTABLE", "THERMAL", true, 500);
} else if (temp > 45) {
// 高温限制 1000mA
power_vote_set("FCC_VOTABLE", "THERMAL", true, 1000);
} else {
// 正常温度不限制
power_vote_set("FCC_VOTABLE", "THERMAL", false, 0);
}
}
// 电池健康投票
void battery_health_check(void)
{
int cycle_count = get_battery_cycle();
if (cycle_count > 500) {
// 老化电池限制 1500mA
power_vote_set("FCC_VOTABLE", "BATTERY_AGE", true, 1500);
} else {
power_vote_set("FCC_VOTABLE", "BATTERY_AGE", false, 0);
}
}
// USB 识别投票
void usb_type_detect(int type)
{
if (type == USB_SDP) {
power_vote_set("FCC_VOTABLE", "USB_TYPE", true, 500);
} else if (type == USB_DCP) {
power_vote_set("FCC_VOTABLE", "USB_TYPE", true, 2000);
}
}
// 用户设置投票
void user_limit_setting(bool enabled, int limit)
{
power_vote_set("FCC_VOTABLE", "USER", enabled, limit);
}仲裁过程:
时刻 T1:
USB_TYPE: enabled=true, value=2000 (USB DCP)
THERMAL: enabled=false, value=0 (温度正常)
BATTERY_AGE: enabled=false, value=0 (新电池)
USER: enabled=false, value=0 (用户未限制)
→ 仲裁结果: 2000mA (由 USB_TYPE 决定)
时刻 T2:(温度升高到 46°C)
USB_TYPE: enabled=true, value=2000
THERMAL: enabled=true, value=1000 ← 新增限制
BATTERY_AGE: enabled=false, value=0
USER: enabled=false, value=0
→ 仲裁结果: 1000mA (由 THERMAL 决定,最小值)
时刻 T3:(用户开启省电模式)
USB_TYPE: enabled=true, value=2000
THERMAL: enabled=true, value=1000
BATTERY_AGE: enabled=false, value=0
USER: enabled=true, value=500 ← 新增限制
→ 仲裁结果: 500mA (由 USER 决定,最小值)5.2 输入暂停控制
场景: 多个条件触发输入暂停
c
// 初始化
static int suspend_callback(struct power_vote_object *obj,
void *data, int result, const char *client)
{
hwlog_info("USB suspend: %s (by %s)\n",
result ? "SUSPEND" : "RESUME", client);
return usb_set_suspend(result);
}
static void suspend_init(void)
{
power_vote_create_object("USB_SUSPEND",
POWER_VOTE_SET_ANY, // 任意一个使能即暂停
suspend_callback,
NULL);
}
// OTG 模式
void otg_mode_changed(bool otg_enabled)
{
// OTG 模式下必须暂停输入
power_vote_set("USB_SUSPEND", "OTG", otg_enabled, 0);
}
// 温度保护
void temp_protect_check(void)
{
int temp = get_battery_temp();
// 温度过高暂停充电
power_vote_set("USB_SUSPEND", "TEMP_PROTECT", temp > 60, 0);
}
// 工厂模式
void factory_mode_check(void)
{
bool factory = is_factory_mode();
// 工厂模式暂停充电
power_vote_set("USB_SUSPEND", "FACTORY", factory, 0);
}仲裁逻辑(SET_ANY):
只要有任意一个客户端 enabled=true,结果就是 true(暂停)
场景1:正常充电
OTG: enabled=false
TEMP_PROTECT: enabled=false
FACTORY: enabled=false
→ 结果: false (不暂停,正常充电)
场景2:进入 OTG 模式
OTG: enabled=true ← 触发暂停
TEMP_PROTECT: enabled=false
FACTORY: enabled=false
→ 结果: true (暂停输入)
场景3:温度过高 + OTG
OTG: enabled=true
TEMP_PROTECT: enabled=true ← 两个都触发
FACTORY: enabled=false
→ 结果: true (仍然是暂停)5.3 直充模式选择
场景: 根据多种条件选择最优充电模式
c
// 充电模式优先级(值越大优先级越高)
#define MODE_BUCK 0 // Buck 充电(5V)
#define MODE_FCP 1 // FCP 快充(9V)
#define MODE_LVC 2 // LVC 直充(1:1)
#define MODE_SC 3 // SC 直充(2:1)
#define MODE_SC4 4 // SC4 直充(4:1)
static int mode_callback(struct power_vote_object *obj,
void *data, int result, const char *client)
{
const char *mode_names[] = {"BUCK", "FCP", "LVC", "SC", "SC4"};
hwlog_info("Switch to %s mode (by %s)\n",
mode_names[result], client);
return switch_charging_mode(result);
}
static void mode_init(void)
{
power_vote_create_object("CHARGE_MODE",
POWER_VOTE_SET_MAX, // 取最大值(最优模式)
mode_callback,
NULL);
}
// 适配器检测
void adapter_detect_result(int adapter_cap)
{
if (adapter_cap & ADAPTER_SC4_SUPPORT)
power_vote_set("CHARGE_MODE", "ADAPTER", true, MODE_SC4);
else if (adapter_cap & ADAPTER_SC_SUPPORT)
power_vote_set("CHARGE_MODE", "ADAPTER", true, MODE_SC);
else if (adapter_cap & ADAPTER_FCP_SUPPORT)
power_vote_set("CHARGE_MODE", "ADAPTER", true, MODE_FCP);
else
power_vote_set("CHARGE_MODE", "ADAPTER", true, MODE_BUCK);
}
// 电池状态检查
void battery_status_check(void)
{
int soc = get_battery_soc();
int temp = get_battery_temp();
// SOC > 90% 降级到 Buck
if (soc > 90) {
power_vote_set("CHARGE_MODE", "BATTERY_SOC", true, MODE_BUCK);
return;
}
// 温度异常降级到 FCP
if (temp < 10 || temp > 45) {
power_vote_set("CHARGE_MODE", "BATTERY_TEMP", true, MODE_FCP);
return;
}
// 正常状态不限制
power_vote_set("CHARGE_MODE", "BATTERY_SOC", false, 0);
power_vote_set("CHARGE_MODE", "BATTERY_TEMP", false, 0);
}6. 调试与监控
6.1 Debugfs 接口
路径: /sys/kernel/debug/hw_power/power_vote/object
功能: 显示所有投票对象的状态
输出格式:
bash
$ cat /sys/kernel/debug/hw_power/power_vote/object
FCC_VOTABLE: type=Set_Min eff_result=500 eff_client_name=USB_TYPE eff_id=2
THERMAL: enabled=0 value=0
BATTERY_AGE: enabled=0 value=0
USB_TYPE: enabled=1 value=500
USER: enabled=0 value=0
USB_SUSPEND: type=Set_Any eff_result=1 eff_client_name=OTG eff_id=0
OTG: enabled=1 value=0
TEMP_PROTECT: enabled=0 value=0
FACTORY: enabled=0 value=0
CHARGE_MODE: type=Set_Max eff_result=3 eff_client_name=ADAPTER eff_id=0
ADAPTER: enabled=1 value=3
BATTERY_SOC: enabled=0 value=0
BATTERY_TEMP: enabled=0 value=06.2 日志分析
关键日志标签: power_vote
典型日志输出:
bash
# 创建投票对象
[power_vote] vote object FCC_VOTABLE create ok
# 投票操作
[power_vote] FCC_VOTABLE: USB_TYPE,2 vote on of value=500 eff_result=500,500 eff_id=2
# 结果变化
[power_vote] FCC_VOTABLE: effective vote is now 500 voted by USB_TYPE,2
# 相同投票去重
[power_vote] FCC_VOTABLE: USB_TYPE,2 same vote on of value=500
[power_vote] FCC_VOTABLE: USB_TYPE,2 ignore same vote on of value=5006.3 实时监控脚本
bash
#!/bin/bash
# 监控投票变化
echo "=== Power Vote Monitor ==="
dmesg -w | grep "power_vote" | grep "effective vote" | while read line; do
timestamp=$(date '+%H:%M:%S')
echo "[$timestamp] $line"
done7. 设计模式与最佳实践
7.1 策略模式应用
Power Vote 是策略模式的典型应用:
角色映射:
- Context(上下文):
power_vote_object - Strategy(策略接口):
power_vote_set_min/max/any - ConcreteStrategy(具体策略):三种仲裁算法
优势:
- 仲裁算法可灵活切换(创建时指定type)
- 新增策略无需修改现有代码
- 策略独立封装便于测试
7.2 使用建议
1. 选择合适的仲裁类型
c
// 限制类参数 → SET_MIN
power_vote_create_object("max_current", POWER_VOTE_SET_MIN, ...);
power_vote_create_object("max_voltage", POWER_VOTE_SET_MIN, ...);
// 优先级类参数 → SET_MAX
power_vote_create_object("charge_priority", POWER_VOTE_SET_MAX, ...);
power_vote_create_object("power_mode", POWER_VOTE_SET_MAX, ...);
// 开关类参数 → SET_ANY
power_vote_create_object("input_suspend", POWER_VOTE_SET_ANY, ...);
power_vote_create_object("otg_enable", POWER_VOTE_SET_ANY, ...);2. 客户端命名规范
c
// 好的命名(清晰表达投票来源)
power_vote_set("FCC", "THERMAL_HIGH_TEMP", true, 1000);
power_vote_set("FCC", "USB_SDP_LIMIT", true, 500);
power_vote_set("FCC", "BATTERY_AGED", true, 1500);
// 不好的命名(难以理解)
power_vote_set("FCC", "client1", true, 1000);
power_vote_set("FCC", "mgr", true, 500);3. 回调函数设计
c
// 好的设计:简洁清晰
static int fcc_callback(struct power_vote_object *obj,
void *data, int result, const char *client)
{
hwlog_info("Set FCC: %d mA (by %s)\n", result, client);
return charger_set_fcc(result);
}
// 不好的设计:逻辑过于复杂
static int bad_callback(struct power_vote_object *obj,
void *data, int result, const char *client)
{
// 回调函数内不应包含复杂业务逻辑
if (result > 2000) {
check_battery_health();
update_ui_status();
notify_thermal_manager();
}
...
}4. 线程安全
c
// 模块内部已加锁(外部无需额外加锁)
power_vote_set("FCC", "THERMAL", true, 1000); // 线程安全
// 查询时可选择是否加锁
value = power_vote_get_effective_result_locked("FCC", true); // 加锁查询7.3 常见陷阱
陷阱1:忘记禁用投票
c
// 错误:条件不满足时未禁用
if (temp > 45) {
power_vote_set("FCC", "THERMAL", true, 1000);
}
// 温度降低后,投票仍然生效!
// 正确:显式禁用
if (temp > 45) {
power_vote_set("FCC", "THERMAL", true, 1000);
} else {
power_vote_set("FCC", "THERMAL", false, 0);
}陷阱2:SET_ANY 误用 value
c
// 错误:SET_ANY 类型忽略 value 值
power_vote_set("USB_SUSPEND", "OTG", true, 1); // value=1 无意义
power_vote_set("USB_SUSPEND", "TEMP", true, 0); // value=0 无意义
// 正确:value 统一设置为 0
power_vote_set("USB_SUSPEND", "OTG", true, 0);
power_vote_set("USB_SUSPEND", "TEMP", false, 0);陷阱3:回调函数阻塞
c
// 错误:回调函数内长时间阻塞
static int bad_callback(struct power_vote_object *obj,
void *data, int result, const char *client)
{
msleep(1000); // ❌ 阻塞 1 秒,影响其他投票
return 0;
}
// 正确:异步处理
static int good_callback(struct power_vote_object *obj,
void *data, int result, const char *client)
{
schedule_work(&update_work); // ✓ 异步执行
return 0;
}8. 技术要点总结
8.1 核心优势
| 优势 | 说明 | 对比传统方案 |
|---|---|---|
| 解耦合 | 各模块独立投票,互不影响 | 传统方案需硬编码优先级 |
| 可追溯 | 清晰记录最终结果由谁决定 | 难以调试多模块冲突 |
| 灵活性 | 运行时动态调整投票 | 修改逻辑需重新编译 |
| 线程安全 | 内置互斥锁保护 | 全局变量易竞争 |
| 可调试 | debugfs 实时查看所有投票 | 传统方案无可视化 |
这个Vote机制的核心思想是分布式决策、集中仲裁:
- 各个子系统根据自己的需求独立投票
- Vote机制自动根据规则(MIN/MAX/ANY)计算最终结果
- 只有当结果改变时才触发回调,避免重复操作
- 通过取最小值(MIN)确保最严格的限制总是生效,保证安全性
这种设计在复杂的充电管理系统中非常实用,能够优雅地处理多个因素(温度、用户设置、硬件能力、协议限制等)对充电参数的影响。
8.2 性能特性
- 时间复杂度:O(N),N 为客户端数量(最大32)
- 空间复杂度:每个投票对象约 2KB
- 锁粒度:对象级别(不同对象可并发操作)
- 优化:相同投票去重,避免无效回调
8.3 应用统计
在 MATE X5 电源系统中的典型应用:
投票对象类型分布:
├─ SET_MIN(60%):充电电流、输入电压、温度限制等
├─ SET_MAX(25%):充电模式、功率等级、优先级等
└─ SET_ANY(15%):输入暂停、OTG 使能、充电使能等
客户端数量分布:
├─ 1-5 个客户端(70%):简单场景
├─ 6-10 个客户端(20%):复杂场景
└─ 10+ 个客户端(10%):极端场景