国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

echo 0 > /sys/devices/system/cpu/cpuX/online

2019-11-09 14:50:46
字體:
供稿:網(wǎng)友
當通過下面的code是cpu offline的話。echo 0 > /sys/devices/system/cpu/cpuX/online具體的code flow如下:int device_add(struct device *dev)->device_create_file而dev_attr_onlline 就是按照下面的方式定義的static ssize_t online_store(struct device *dev, struct device_attribute *attr,                const char *buf, size_t count){    bool val;    int ret;    ret = strtobool(buf, &val);    if (ret < 0)        return ret;    ret = lock_device_hotplug_sysfs();    if (ret)        return ret;    ret = val ? device_online(dev) : device_offline(dev);    unlock_device_hotplug();    return ret < 0 ? ret : count;}static DEVICE_ATTR_RW(online);當echo 0的時候選擇device_online,否則device_offlineint device_offline(struct device *dev){    int ret;    if (dev->offline_disabled)        return -EPERM;    ret = device_for_each_child(dev, NULL, device_check_offline);    if (ret)        return ret;    device_lock(dev);    if (device_supports_offline(dev)) {        if (dev->offline) {            ret = 1;        } else {            ret = dev->bus->offline(dev);            if (!ret) {                kobject_uevent(&dev->kobj, KOBJ_OFFLINE);                dev->offline = true;            }        }    }    device_unlock(dev);    return ret;}可見是調(diào)用的bus->offline而cpu的bus定義如下:struct bus_type cpu_subsys = {    .name = "cpu",    .dev_name = "cpu",    .match = cpu_subsys_match,#ifdef CONFIG_HOTPLUG_CPU    .online = cpu_subsys_online,    .offline = cpu_subsys_offline,#endif};最終會調(diào)用cpu_subsys_offline->cpu_down->do_cpu_down->_cpu_down->cpuhp_down_callbacksstatic int cpuhp_invoke_callback(unsigned int cpu, enum cpuhp_state state,                 bool bringup, struct hlist_node *node){    struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);    struct cpuhp_step *step = cpuhp_get_step(state);    int (*cbm)(unsigned int cpu, struct hlist_node *node);    int (*cb)(unsigned int cpu);    int ret, cnt;    if (!step->multi_instance) {        cb = bringup ? step->startup.single : step->teardown.single;        if (!cb)            return 0;        trace_cpuhp_enter(cpu, st->target, state, cb);        ret = cb(cpu);        trace_cpuhp_exit(cpu, st->state, state, ret);        return ret;    }    cbm = bringup ? step->startup.multi : step->teardown.multi;    if (!cbm)        return 0;    }在cpuhp_invoke_callback 中我們假定step->multi_instance == 0,因此cb= step->teardown.single其是在cpuhp_bp_states 數(shù)組中定義的    [CPUHP_TEARDOWN_CPU] = {        .name            = "cpu:teardown",        .startup.single        = NULL,        .teardown.single    = takedown_cpu,        .cant_stop        = true,    },takedown_cpu->__cpu_die->op_cpu_kill其中op_cpu_kill 在arm64下定義如下:static int op_cpu_kill(unsigned int cpu){    /*     * If we have no means of synchronising with the dying CPU, then assume     * that it is really dead. We can only wait for an arbitrary length of     * time and hope that it's dead, so let's skip the wait and just hope.     */    if (!cpu_ops[cpu]->cpu_kill)        return 0;    return cpu_ops[cpu]->cpu_kill(cpu);}而在smp_cpu_setup->cpu_read_ops來決定cpu_ops的值int __init cpu_read_ops(int cpu){    const char *enable_method = cpu_read_enable_method(cpu);    if (!enable_method)        return -ENODEV;    cpu_ops[cpu] = cpu_get_ops(enable_method);    if (!cpu_ops[cpu]) {        PR_warn("Unsupported enable-method: %s/n", enable_method);        return -EOPNOTSUPP;    }    return 0;}enable_method 是會從deviceTree或者acpi表中parse 當前的enable_methodstatic const char *__init cpu_read_enable_method(int cpu){    const char *enable_method;    if (acpi_disabled) {        struct device_node *dn = of_get_cpu_node(cpu, NULL);        if (!dn) {            if (!cpu)                pr_err("Failed to find device node for boot cpu/n");            return NULL;        }        enable_method = of_get_property(dn, "enable-method", NULL);        if (!enable_method) {            /*             * The boot CPU may not have an enable method (e.g.             * when spin-table is used for secondaries).             * Don't warn spuriously.             */            if (cpu != 0)                pr_err("%s: missing enable-method property/n",                    dn->full_name);        }    } else {        enable_method = acpi_get_enable_method(cpu);        if (!enable_method) {            /*             * In ACPI systems the boot CPU does not require             * checking the enable method since for some             * boot protocol (ie parking protocol) it need not             * be initialized. Don't warn spuriously.             */            if (cpu != 0)                pr_err("Unsupported ACPI enable-method/n");        }    }    return enable_method;}我們以acpi為例static inline const char *acpi_get_enable_method(int cpu){    if (acpi_psci_present())        return "psci";    if (acpi_parking_protocol_valid(cpu))        return "parking-protocol";    return NULL;}可見cpu_ops分為兩類,psci和parking-protocol,目前主流是psci,具體是在acpi的FADT表中判斷當前是否支持psci的bool __init acpi_psci_present(void){    return acpi_gbl_FADT.arm_boot_flags & ACPI_FADT_PSCI_COMPLIANT;}決定是psci后,因此cpu_ops就是cpu_psci_opsstatic const struct cpu_Operations *acpi_supported_cpu_ops[] __initconst = {#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL    &acpi_parking_protocol_ops,#endif    &cpu_psci_ops,    NULL,};const struct cpu_operations cpu_psci_ops = {    .name        = "psci",#ifdef CONFIG_CPU_IDLE    .cpu_init_idle    = psci_cpu_init_idle,    .cpu_suspend    = psci_cpu_suspend_enter,#endif    .cpu_init    = cpu_psci_cpu_init,    .cpu_prepare    = cpu_psci_cpu_prepare,    .cpu_boot    = cpu_psci_cpu_boot,#ifdef CONFIG_HOTPLUG_CPU    .cpu_disable    = cpu_psci_cpu_disable,    .cpu_die    = cpu_psci_cpu_die,    .cpu_kill    = cpu_psci_cpu_kill,#endif};psci的cpu_kill是cpu_psci_cpu_killstatic int cpu_psci_cpu_kill(unsigned int cpu){    int err, i;    if (!psci_ops.affinity_info)        return 0;    /*     * cpu_kill could race with cpu_die and we can     * potentially end up declaring this cpu undead     * while it is dying. So, try again a few times.     */    for (i = 0; i < 10; i++) {        err = psci_ops.affinity_info(cpu_logical_map(cpu), 0);        if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) {            pr_info("CPU%d killed./n", cpu);            return 0;        }        msleep(10);        pr_info("Retrying again to check for CPU kill/n");    }    pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)/n",            cpu, err);    return -ETIMEDOUT;}有調(diào)用psci_ops.affinity_info    psci_ops.affinity_info = psci_affinity_info;可見最后是給ATF發(fā)信號讓ATF來關(guān)掉cpu的。static int psci_affinity_info(unsigned long target_affinity,        unsigned long lowest_affinity_level){    return invoke_psci_fn(PSCI_FN_NATIVE(0_2, AFFINITY_INFO),                  target_affinity, lowest_affinity_level, 0);}
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 临猗县| 汤原县| 大洼县| 安岳县| 沂水县| 荣成市| 金堂县| 花莲县| 衡山县| 双柏县| 香港| 改则县| 泰顺县| 樟树市| 沛县| 大港区| 阳谷县| 富锦市| 利川市| 历史| 浮山县| 高青县| 林周县| 惠水县| 汤原县| 崇礼县| 安乡县| 安西县| 台江县| 同仁县| 大厂| 开封县| 平阳县| 东方市| 肥城市| 綦江县| 桃园县| 杭锦后旗| 库尔勒市| 新巴尔虎右旗| 姚安县|