)]}'
{
  "commit": "3439dd86e34580384d3b58cf8d54a9283cd7a342",
  "tree": "b421244c25d96e83a744576ad543587339e581fb",
  "parents": [
    "626ab0e69d376fa07599af669af8ba92d58e87c1"
  ],
  "author": {
    "name": "Porpoise",
    "email": "porpoise.chiang@gmail.com",
    "time": "Fri Jun 23 02:05:56 2006 -0700"
  },
  "committer": {
    "name": "Linus Torvalds",
    "email": "torvalds@g5.osdl.org",
    "time": "Fri Jun 23 07:43:08 2006 -0700"
  },
  "message": "[PATCH] When CONFIG_BASE_SMALL\u003d1, cascade() may enter an infinite loop\n\nWhen CONFIG_BASE_SAMLL\u003d1, cascade() in may enter the infinite loop.\nBecause of CONFIG_BASE_SMALL\u003d1(TVR_BITS\u003d6 and TVN_BITS\u003d4), the list\nbase-\u003etv5 may cascade into base-\u003etv5.  So, the kernel enters the infinite\nloop in the function cascade().\n\nI created a test module to verify this bug, and a patch to fix it.\n\n#include \u003clinux/kernel.h\u003e\n#include \u003clinux/module.h\u003e\n#include \u003clinux/init.h\u003e\n#include \u003clinux/timer.h\u003e\n#if 0\n#include \u003clinux/kdb.h\u003e\n#else\n#define kdb_printf printk\n#endif\n\n#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)\n#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)\n#define TVN_SIZE (1 \u003c\u003c TVN_BITS)\n#define TVR_SIZE (1 \u003c\u003c TVR_BITS)\n#define TVN_MASK (TVN_SIZE - 1)\n#define TVR_MASK (TVR_SIZE - 1)\n\n#define TV_SIZE(N)  (N*TVN_BITS  + TVR_BITS)\n\nstruct timer_list timer0;\nstruct timer_list dummy_timer1;\nstruct timer_list dummy_timer2;\n\nvoid dummy_timer_fun(unsigned long data) {\n}\nunsigned long j\u003d0;\nvoid check_timer_base(unsigned long data)\n{\n        kdb_printf(\"check_timer_base %08x\\n\",jiffies);\n        mod_timer(\u0026timer0,(jiffies \u0026 (~0xFFF)) + 0x1FFF);\n}\n\nint init_module(void)\n{\n        init_timer(\u0026timer0);\n        timer0.data \u003d (unsigned long)0;\n        timer0.function \u003d check_timer_base;\n        mod_timer(\u0026timer0,jiffies+1);\n\n        init_timer(\u0026dummy_timer1);\n        dummy_timer1.data \u003d (unsigned long)0;\n        dummy_timer1.function \u003d dummy_timer_fun;\n\n        init_timer(\u0026dummy_timer2);\n        dummy_timer2.data \u003d (unsigned long)0;\n        dummy_timer2.function \u003d dummy_timer_fun;\n\n        j\u003djiffies;\n        j\u0026\u003d(~((1\u003c\u003cTV_SIZE(3))-1));\n        j+\u003d(1\u003c\u003cTV_SIZE(3));\n        j+\u003d(1\u003c\u003cTV_SIZE(4));\n\n        kdb_printf(\"mod_timer %08x\\n\",j);\n\n        mod_timer(\u0026dummy_timer1, j );\n        mod_timer(\u0026dummy_timer2, j );\n\n        return 0;\n}\n\nvoid cleanup_module()\n{\n        del_timer_sync(\u0026timer0);\n        del_timer_sync(\u0026dummy_timer1);\n        del_timer_sync(\u0026dummy_timer2);\n}\n\n(Cleanups from Oleg)\n\n[oleg@tv-sign.ru: use list_replace_init()]\nCc: Oleg Nesterov \u003coleg@tv-sign.ru\u003e\nCc: Matt Mackall \u003cmpm@selenic.com\u003e\nSigned-off-by: Oleg Nesterov \u003coleg@tv-sign.ru\u003e\nSigned-off-by: Andrew Morton \u003cakpm@osdl.org\u003e\nSigned-off-by: Linus Torvalds \u003ctorvalds@osdl.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "3bf0e9ed2dbe622cc205b47a41b5151babe4695f",
      "old_mode": 33188,
      "old_path": "kernel/timer.c",
      "new_id": "f35b3939e9372c5139f0588a9f728b681d225d17",
      "new_mode": 33188,
      "new_path": "kernel/timer.c"
    }
  ]
}
