Xv6 cpu and process information storage skills, xv6 cpu storage skills

Source: Internet
Author: User
Tags field table

Xv6 cpu and process information storage skills, xv6 cpu storage skills

Xv6 is a multi-processor Unix-like operating system,

I recently read the source code and found that xv6 is very tricky when recording the current CPU and Process status.

 

First, go to the Code:

 1 extern struct cpu cpus[NCPU]; 2 extern int ncpu; 3  4 // Per-CPU variables, holding pointers to the 5 // current cpu and to the current process. 6 // The asm suffix tells gcc to use "%gs:0" to refer to cpu 7 // and "%gs:4" to refer to proc.  seginit sets up the 8 // %gs segment register so that %gs refers to the memory 9 // holding those two variables in the local cpu's struct cpu.10 // This is similar to how thread-local variables are implemented11 // in thread libraries such as Linux pthreads.12 extern struct cpu *cpu asm("%gs:0");       // &cpus[cpunum()]13 extern struct proc *proc asm("%gs:4");     // cpus[cpunum()].proc

 

Struct cpu is a struct used to save the running status of each cpu,

The first line of the Code defines the structure array cpus [NCPU]. The total number of NCPU resources (up to 8) corresponds to the total number of NCPU resources ),That is to say, cpus is used to store the running status of all cpus..

 

The problem arises: the kernel code above runs on each cpu. How can each cpu know its current running status?

For this problem, we can obtain the cpu ID through lapic, and then use the number to address cpus,

That is to say, for any cpu, the storage location of its own status can be obtained as follows: struct cpu * c = & cpus [cpunum ()];

 

However, the second question comes: It is impossible for us to get the ID through lapic every time we reference the cpu status. Can we get a global variable to store the Status Location at one time?

For example, struct cpu * cpu; // global variable, stores the cpu status, and then cpu = c in the initialization code;

For the problem of recording the running processes of each cpu, can it be written as: struct proc * proc; // global variable to store the status of the processes currently running by the cpu?

 

So the third problem comes: Each cpu is independent and parallel. The kernel code running on each cpu is the same, and the page table is the same,

This means that the addresses of the global variables cpu and proc are the same, so that they cannot be used to differentiate the status of different CPUs.

Therefore, we need a way to record the status with the same symbol in each cpu, but these symbols are mapped to different addresses.

Since the page table is the same, we naturally cannot use an absolute number to address it. Think carefully, what is on the page table? There is also a field table above the page table.

Therefore, we need to use segment register for addressing. As long as we map all the segments to different memory regions when creating a field table, we have the following statement:

1 extern struct cpu *cpu asm("%gs:0");       // &cpus[cpunum()]2 extern struct proc *proc asm("%gs:4");     // cpus[cpunum()].proc

We use gs as the segment register, cpu points to [% gs], proc points to [% gs + 4],

Which of the following statements must start with extern? I asked a great god, he said that the gs segment was created externally, which is equivalent to an external definition...

 

OK. The last question is, where should the gs segment point to ensure that the gs segment of each cpu is located in different regions?

The most intuitive idea is to point to the corresponding cpus [num], so add two domains at the end of the struct cpu:

1 struct cpu {2 ........ // cpu status 3 4 // Cpu-local storage variables; see below5 struct cpu * cpu; 6 struct proc * proc; // The currently-running process.7}

Then, when creating a field table, add the gs segment and map it to the two fields at the end:

1 c = & cpus [cpunum ()]; 2 3 ......... // create another segment 4 5 // create a gs segment, two domains in total (storage cpu and proc address ), start address: & c-> cpu 6 c-> gdt [SEG_KCPU] = SEG (STA_W, & c-> cpu, 8, 0 ); 7 8 // load gdt 9 lgdt (c-> gdt, sizeof (c-> gdt); 10 // load gs11 loadgs (SEG_KCPU <3 ); 12 13 // assign the current cpu and proc status address to the cpu and proc global variables 14 // The cpu variable essence is % gs: 0, and the proc variable essence is % gs: 415 cpu = c; 16 proc = 0;

 

In fact, the cpu and proc variables are similar to the local storage of threads. Each processor can reference the same variable, but these variables correspond to different storage regions.

It is possible that this implementation technique is similar to TLS (local thread storage). If you have time to study the implementation of TLS, check whether it is.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.