免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2104 | 回复: 5
打印 上一主题 下一主题

__exit_mm 为何增加 mm_count 引用 [复制链接]

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-18 11:13 |只看该作者 |倒序浏览
static inline void __exit_mm(struct task_struct * tsk)
{
        struct mm_struct * mm = tsk->mm;

        mm_release();
        if (mm) {
                atomic_inc(&mm->mm_count);
                if (mm != tsk->active_mm) BUG();
                /* more a memory barrier than a real lock */
                task_lock(tsk);
                tsk->mm = NULL;
                task_unlock(tsk);
                enter_lazy_tlb(mm, current, smp_processor_id());
                mmput(mm);
        }
}

谁还要防止 mm struct 被释放????

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
2 [报告]
发表于 2011-11-18 12:35 |只看该作者
感觉这个问题转化成了 lazy tlb 机制实现原理。。。。。。继续跟踪。

论坛徽章:
0
3 [报告]
发表于 2011-11-18 15:36 |只看该作者
因为下面要对该结构体操作,防止操作的过程中其他内核路径将该结构体释放了。mmput又会对mm_count减1

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
4 [报告]
发表于 2011-11-18 16:14 |只看该作者
因为下面要对该结构体操作,防止操作的过程中其他内核路径将该结构体释放了。mmput又会对mm_count减1
flikelinux 发表于 2011-11-18 15:36


单说一个普通情况, mm->count 和 mm->user_count 都是1, 这个是 allocate_mm 中设置的。
mm->count 和 mm->user_count 区别在于无论 mm->user_count 是多大, 都只是对应一个 mm->count.
因此, fork 的时候, 增加了 mm->user_count 却仍然保持 mm->count 为原值。
换句话说, mm->user_count记录的是有几个 task->mm 引用了这个  mm, 只要被任意一个引用, 则 mm->count 值至少为1

mm->count 变化发生与除此之外的其他引用中, 比如 switch 中被暂借到 active_mm 时;
因此,

230static int exec_mmap(void)
231{
232        struct mm_struct * mm, * old_mm;
233
234        old_mm = current->mm;
235        if (old_mm && atomic_read(&old_mm->mm_users) == 1) {
236                flush_cache_mm(old_mm);
237                mm_release();
238                exit_mmap(old_mm);
239                flush_tlb_mm(old_mm);
240                return 0;
241        }
242
243        mm = mm_alloc();
244        if (mm) {
245                struct mm_struct *active_mm = current->active_mm;
246
247                current->mm = mm;
248                current->active_mm = mm;
249                activate_mm(active_mm, mm);
250                mm_release();
251                if (old_mm) {
252                        if (active_mm != old_mm) BUG();
253                        mmput(old_mm);   // 这里只需要 mmput 即可, 因为 active_mm 是本身, 在 switch 时直接赋值而没有增加 mm->count, mm->count, mm->user_count 都是1
254                        return 0;
255                }
256                mmdrop(active_mm);  // 而这里, 确实暂借的, mm_count 被增加了; 需要额外释放
257                return 0;
258        }
259        return -ENOMEM;
260}
261

因此, 你那种解释是肤浅的

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
5 [报告]
发表于 2011-11-18 16:26 |只看该作者
本帖最后由 zylthinking 于 2011-11-18 16:29 编辑

找到点证据, 但还是没明白这个 lazy tlb 的全貌, 但已经明白这个 atomic_inc(&mm->mm_count);  是因为 task->mm = NULL 了, 然而还存在着 task->active_mm != NULL, 原来两个一致, active_mm 躲在 mm 之后过日子, 没什么自己出头露面的必要, 但这次没有挡风墙了, 只好增加 mm_count

271/*
272 * We can use these to temporarily drop into
273 * "lazy TLB" mode and back.
274 */
275struct mm_struct * start_lazy_tlb(void)
276{
277        struct mm_struct *mm = current->mm;
278        current->mm = NULL;
279        /* active_mm is still 'mm' */
280        atomic_inc(&mm->mm_count);    // 如出一辄
281        enter_lazy_tlb(mm, current, smp_processor_id());

282        return mm;
283}
284
285void end_lazy_tlb(struct mm_struct *mm)
286{
287        struct mm_struct *active_mm = current->active_mm;
288
289        current->mm = mm;
290        if (mm != active_mm) {
291                current->active_mm = mm;
292                activate_mm(active_mm, mm);
293        }
294        mmdrop(active_mm);  //对应的释放
295}
296

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
6 [报告]
发表于 2011-11-18 16:53 |只看该作者
明白了, 和 lazy tlb 没太大关系, 我还不明白这玩艺呢
保留active_mm 的原因在于调度时需要, 因此这玩艺至少要保留到调度后。

615        /*
616         * there are 3 processes which are affected by a context switch:
617         *
618         * prev == .... ==> (last => next)
619         *
620         * It's the 'much more previous' 'prev' that is on next's stack,
621         * but prev is set to (the just run) 'last' process by switch_to().
622         * This might sound slightly confusing but makes tons of sense.
623         */
624        prepare_to_switch();
625        {
626                struct mm_struct *mm = next->mm;
627                struct mm_struct *oldmm = prev->active_mm;
628                if (!mm) {
629                        if (next->active_mm) BUG();
630                        next->active_mm = oldmm;
631                        atomic_inc(&oldmm->mm_count);
632                        enter_lazy_tlb(oldmm, next, this_cpu);
633                } else {
634                        if (next->active_mm != mm) BUG();
635                        switch_mm(oldmm, mm, next, this_cpu);
636                }
637
638                if (!prev->mm) {    // 释放地
639                        prev->active_mm = NULL;
640                        mmdrop(oldmm);
641                }

642        }
643
644        /*
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP