免费注册 查看新帖 |

Chinaunix

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

swapout protection token(swap token)防止页面“抖动”处理 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-05-02 20:28 |只看该作者 |倒序浏览
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
  hhj.cublog.cn
为了解决可能出现的页面换入换出时的“抖动”,内核采用swap token技术。swap token通过
一个mm_struct指针swap_token_mm实现。swap_token_mm指向拥有swap token的进程的mm_struct
结构。拥有swap token的进程的内存active队列中的页面,不会转移到inactive队列中,从而避免
换入到磁盘上。函数grab_swap_token决定当前进程是否能获得swap token。
/*
* Try to grab the swapout protection token.  We only try to
* grab it once every TOKEN_CHECK_INTERVAL, both to prevent
* SMP lock contention and to check that the process that held
* the token before is no longer thrashing.
*/
void grab_swap_token(void)
{
struct mm_struct *mm;
int reason;
/* We have the token. Let others know we still need it. */
if (has_swap_token(current->mm)) {
//若当前进程已经占有swap token,则记录下最近换入标志,然后返回。
  current->mm->recent_pagein = 1;
  if (unlikely(!swap_token_default_timeout))
   disable_swap_token();
  return;
}
//执行到这里,当前进程没有占有swap token
if (time_after(jiffies, swap_token_check)) {
//每隔swap_token_check时间,检测是否要将swap token 重新分配
  if (!swap_token_default_timeout) {
   swap_token_check = jiffies + SWAP_TOKEN_CHECK_INTERVAL;
   return;
  }
  /* ... or if we recently held the token. */
//若当前进程最近占有过swap token,则返回
  if (time_before(jiffies, current->mm->swap_token_time))
   return;
  if (!spin_trylock(&swap_token_lock))
   return;
  swap_token_check = jiffies + SWAP_TOKEN_CHECK_INTERVAL;
  mm = swap_token_mm;
  if ((reason = should_release_swap_token(mm))) {
   unsigned long eligible = jiffies;
   if (reason == SWAP_TOKEN_TIMED_OUT) {
    eligible += swap_token_default_timeout;
   }
   mm->swap_token_time = eligible;
//在swap_token_time时间之前,之前占有swap token的进程不会重新获得swap token
   swap_token_timeout = jiffies + swap_token_default_timeout;
   swap_token_mm = current->mm;//将swap token赋给当前进程
  }
  spin_unlock(&swap_token_lock);
}
return;
}
   这里用到了函数should_release_swap_token,判断当前占有swap token的进程是否
应该释放swap token.
static int should_release_swap_token(struct mm_struct *mm)
{
int ret = 0;
if (!mm->recent_pagein)//当前进程没有过换入操作
  ret = SWAP_TOKEN_ENOUGH_RSS;
else if (time_after(jiffies, swap_token_timeout))
//当前进程有换入操作,但占有swap token时间超时
  ret = SWAP_TOKEN_TIMED_OUT;
mm->recent_pagein = 0;
return ret;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/36646/showart_290713.html

论坛徽章:
1
摩羯座
日期:2013-10-23 12:41:02
2 [报告]
发表于 2015-04-09 08:29 |只看该作者
今天也看到这个地方,按照2.6.24跟新
参考 mm_struct
……
        /* Swap token stuff */
        /*
         * Last value of global fault stamp as seen by this process.
         * In other words, this value gives an indication of how long
         * it has been since this task got the token.
         * Look at mm/thrash.c
         */
        unsigned int faultstamp;
        unsigned int token_priority;
        unsigned int last_interval;
……

static DEFINE_SPINLOCK(swap_token_lock);
struct mm_struct *swap_token_mm; // 指向持有token的进程的mm_struct
static unsigned int global_faults; // 这个文件里的全局变量,用于表示时间的记数,但又不是时间

void grab_swap_token(void) // <-- do_swap_page <-- handle_pte_fault <-- handle_mm_fault
{
        int current_interval;

        global_faults++; // 唯一的赋值操作,每次尝试获得token都会对该计数器简单递增

        current_interval = global_faults - current->mm->faultstamp; // 当前记数-我上一次得到token的记数=我有多久没占有token的记数

        if (!spin_trylock(&swap_token_lock))
                return;

        /* First come first served */
        if (swap_token_mm == NULL) { // token空闲,一切很简单
                current->mm->token_priority = current->mm->token_priority + 2;
                swap_token_mm = current->mm;
                goto out;
        }

        if (current->mm != swap_token_mm) { // 我不持有token吗?
                if (current_interval < current->mm->last_interval) // 当前等待的记数<自己上一次的等待记数
                        current->mm->token_priority++;
                else {
                        if (likely(current->mm->token_priority > 0))
                                current->mm->token_priority--;
                }
                /* Check if we deserve the token */
                if (current->mm->token_priority >
                                swap_token_mm->token_priority) { // 我的优先级>持有令牌进程的优先级
                        current->mm->token_priority += 2;
                        swap_token_mm = current->mm; // 核心:交换
                }
        } else { // 继续持有,而且提高优先级奖励
                /* Token holder came in again! */
                current->mm->token_priority += 2;
        }

out: // 获得token后的操作
        current->mm->faultstamp = global_faults; // 得到token时刻计数器的值,用于标记持有token记数长度
        current->mm->last_interval = current_interval;
        spin_unlock(&swap_token_lock);
return;
}

/* Called on process exit. */
void __put_swap_token(struct mm_struct *mm) // <-- put_swap_token <-- mmput
{
        spin_lock(&swap_token_lock);
        if (likely(mm == swap_token_mm))
                swap_token_mm = NULL; // 释放token
        spin_unlock(&swap_token_lock);
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP