)]}'
{
  "commit": "d670ec13178d0fd8680e6742a2bc6e04f28f87d8",
  "tree": "81a2ac824dd92a0536e42f9a0ba3d83240856722",
  "parents": [
    "6ebbe7a07b3bc40b168d2afc569a6543c020d2e3"
  ],
  "author": {
    "name": "Peter Zijlstra",
    "email": "a.p.zijlstra@chello.nl",
    "time": "Thu Sep 01 12:42:04 2011 +0200"
  },
  "committer": {
    "name": "Thomas Gleixner",
    "email": "tglx@linutronix.de",
    "time": "Fri Sep 30 14:07:06 2011 +0200"
  },
  "message": "posix-cpu-timers: Cure SMP wobbles\n\nDavid reported:\n\n  Attached below is a watered-down version of rt/tst-cpuclock2.c from\n  GLIBC.  Just build it with \"gcc -o test test.c -lpthread -lrt\" or\n  similar.\n\n  Run it several times, and you will see cases where the main thread\n  will measure a process clock difference before and after the nanosleep\n  which is smaller than the cpu-burner thread\u0027s individual thread clock\n  difference.  This doesn\u0027t make any sense since the cpu-burner thread\n  is part of the top-level process\u0027s thread group.\n\n  I\u0027ve reproduced this on both x86-64 and sparc64 (using both 32-bit and\n  64-bit binaries).\n\n  For example:\n\n  [davem@boricha build-x86_64-linux]$ ./test\n  process: before(0.001221967) after(0.498624371) diff(497402404)\n  thread:  before(0.000081692) after(0.498316431) diff(498234739)\n  self:    before(0.001223521) after(0.001240219) diff(16698)\n  [davem@boricha build-x86_64-linux]$ \n\n  The diff of \u0027process\u0027 should always be \u003e\u003d the diff of \u0027thread\u0027.\n\n  I make sure to wrap the \u0027thread\u0027 clock measurements the most tightly\n  around the nanosleep() call, and that the \u0027process\u0027 clock measurements\n  are the outer-most ones.\n\n  ---\n  #include \u003cunistd.h\u003e\n  #include \u003cstdio.h\u003e\n  #include \u003cstdlib.h\u003e\n  #include \u003ctime.h\u003e\n  #include \u003cfcntl.h\u003e\n  #include \u003cstring.h\u003e\n  #include \u003cerrno.h\u003e\n  #include \u003cpthread.h\u003e\n\n  static pthread_barrier_t barrier;\n\n  static void *chew_cpu(void *arg)\n  {\n\t  pthread_barrier_wait(\u0026barrier);\n\t  while (1)\n\t\t  __asm__ __volatile__(\"\" : : : \"memory\");\n\t  return NULL;\n  }\n\n  int main(void)\n  {\n\t  clockid_t process_clock, my_thread_clock, th_clock;\n\t  struct timespec process_before, process_after;\n\t  struct timespec me_before, me_after;\n\t  struct timespec th_before, th_after;\n\t  struct timespec sleeptime;\n\t  unsigned long diff;\n\t  pthread_t th;\n\t  int err;\n\n\t  err \u003d clock_getcpuclockid(0, \u0026process_clock);\n\t  if (err)\n\t\t  return 1;\n\n\t  err \u003d pthread_getcpuclockid(pthread_self(), \u0026my_thread_clock);\n\t  if (err)\n\t\t  return 1;\n\n\t  pthread_barrier_init(\u0026barrier, NULL, 2);\n\t  err \u003d pthread_create(\u0026th, NULL, chew_cpu, NULL);\n\t  if (err)\n\t\t  return 1;\n\n\t  err \u003d pthread_getcpuclockid(th, \u0026th_clock);\n\t  if (err)\n\t\t  return 1;\n\n\t  pthread_barrier_wait(\u0026barrier);\n\n\t  err \u003d clock_gettime(process_clock, \u0026process_before);\n\t  if (err)\n\t\t  return 1;\n\n\t  err \u003d clock_gettime(my_thread_clock, \u0026me_before);\n\t  if (err)\n\t\t  return 1;\n\n\t  err \u003d clock_gettime(th_clock, \u0026th_before);\n\t  if (err)\n\t\t  return 1;\n\n\t  sleeptime.tv_sec \u003d 0;\n\t  sleeptime.tv_nsec \u003d 500000000;\n\t  nanosleep(\u0026sleeptime, NULL);\n\n\t  err \u003d clock_gettime(th_clock, \u0026th_after);\n\t  if (err)\n\t\t  return 1;\n\n\t  err \u003d clock_gettime(my_thread_clock, \u0026me_after);\n\t  if (err)\n\t\t  return 1;\n\n\t  err \u003d clock_gettime(process_clock, \u0026process_after);\n\t  if (err)\n\t\t  return 1;\n\n\t  diff \u003d process_after.tv_nsec - process_before.tv_nsec;\n\t  printf(\"process: before(%lu.%.9lu) after(%lu.%.9lu) diff(%lu)\\n\",\n\t\t process_before.tv_sec, process_before.tv_nsec,\n\t\t process_after.tv_sec, process_after.tv_nsec, diff);\n\t  diff \u003d th_after.tv_nsec - th_before.tv_nsec;\n\t  printf(\"thread:  before(%lu.%.9lu) after(%lu.%.9lu) diff(%lu)\\n\",\n\t\t th_before.tv_sec, th_before.tv_nsec,\n\t\t th_after.tv_sec, th_after.tv_nsec, diff);\n\t  diff \u003d me_after.tv_nsec - me_before.tv_nsec;\n\t  printf(\"self:    before(%lu.%.9lu) after(%lu.%.9lu) diff(%lu)\\n\",\n\t\t me_before.tv_sec, me_before.tv_nsec,\n\t\t me_after.tv_sec, me_after.tv_nsec, diff);\n\n\t  return 0;\n  }\n\nThis is due to us using p-\u003ese.sum_exec_runtime in\nthread_group_cputime() where we iterate the thread group and sum all\ndata. This does not take time since the last schedule operation (tick\nor otherwise) into account. We can cure this by using\ntask_sched_runtime() at the cost of having to take locks.\n\nThis also means we can (and must) do away with\nthread_group_sched_runtime() since the modified thread_group_cputime()\nis now more accurate and would deadlock when called from\nthread_group_sched_runtime().\n\nAside of that it makes the function safe on 32 bit systems. The old\ncode added t-\u003ese.sum_exec_runtime unprotected. sum_exec_runtime is a\n64bit value and could be changed on another cpu at the same time.\n\nReported-by: David Miller \u003cdavem@davemloft.net\u003e\nSigned-off-by: Peter Zijlstra \u003ca.p.zijlstra@chello.nl\u003e\nCc: stable@kernel.org\nLink: http://lkml.kernel.org/r/1314874459.7945.22.camel@twins\nTested-by: David Miller \u003cdavem@davemloft.net\u003e\nSigned-off-by: Thomas Gleixner \u003ctglx@linutronix.de\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "4ac2c0578e0ff9133c4c761fcf3291879ae646d4",
      "old_mode": 33188,
      "old_path": "include/linux/sched.h",
      "new_id": "41d0237fd449fd842d33cd9d92282c59c99d2daf",
      "new_mode": 33188,
      "new_path": "include/linux/sched.h"
    },
    {
      "type": "modify",
      "old_id": "58f405b581e789b1f282a9682fc6159fc545dda0",
      "old_mode": 33188,
      "old_path": "kernel/posix-cpu-timers.c",
      "new_id": "c8008dd58ef25da2d46c1563035f7a3801cfb187",
      "new_mode": 33188,
      "new_path": "kernel/posix-cpu-timers.c"
    },
    {
      "type": "modify",
      "old_id": "d249ea88428cca61c9ee29d6e5533fdcd1911411",
      "old_mode": 33188,
      "old_path": "kernel/sched.c",
      "new_id": "b50b0f0c9aa90cc6d313ccd95573d39f256f90d1",
      "new_mode": 33188,
      "new_path": "kernel/sched.c"
    }
  ]
}
