Create per-CPU tick counter #417
                
     Open
            
            
          
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
It is intuitive to allow each CPU have its own tick counter.
This commit provides the key concepts of per-CPU variable and serves as a warm-up for the Lock Lab: memory allocator.
(*) Preemption
Accessing per-CPU variable must disable preemption to avoid data races.
For example, a process tries to update the tick counter of CPU0, but is switched to another CPU before store instruction, and the subsequent process running on CPU0 also wants to update the tick counter of CPU0.
In xv6, disabling and enabling preemption can be controlled by push_off() and pop_off().
(*) Remove lock contention and deadlock
Previously, interrupts had to be disabled before holding the tickslock in sys_uptime() to avoid deadlock, as this lock was also used in the interrupt context, i.e., clockintr().
Note: however, in xv6, invoking sleep() requires holding a lock, and we need to adjust this restriction.
(*) False sharing
Per-CPU variables should be placed in different cache lines to avoid false sharing, that is,
In addition, per-CPU tick counter also improves fairness. Previously, wakeup() was handled only by CPU0 in clockintr(). Ideally, each CPU should have its own sleep queue.
https://github.com/segfauIt/xv6-riscv/blob/e60f18e/kernel/proc.c#L555-L626