Article Title: Linux clock processing mechanism (2 ). Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
3.3 add or delete a Software Clock
After learning about the data organization of the Software Clock, let's take a look at how to add and delete a Software Clock.
3.3.1 add Software Clock
To add a software clock in the Linux kernel, you must first allocate a variable of the struct timer_list type and then call the add_timer () function () add the software clock to the base of the CPU that calls the add_timer function. Add_timer is a layer package for function _ mod_timer. The Code of function _ mod_timer () is shown in listing 3-2:
Listing 3-2 _ mod_timer Function
Int _ mod_timer (struct timer_list * timer, unsigned long expires) {struct tvec_base * base, * new_base; unsigned long flags; int ret = 0 ;...... Base = lock_timer_base (timer, & flags); if (timer_pending (timer) {detach_timer (timer, 0); ret = 1;} new_base = _ get_cpu_var (tvec_bases ); if (base! = New_base) {if (likely (base-> running_timer! = Timer) {/* See the comment in lock_timer_base () */timer_set_base (timer, NULL); spin_unlock (& base-> lock); base = new_base; spin_lock (& base-> lock); timer_set_base (timer, base) ;}} timer-> expires = expires; internal_add_timer (base, timer); spin_unlock_irqrestore (& base-> lock, flags); return ret ;}
Code explanation:
Note: detaching a Software Clock means removing the software clock from the base where the Software Clock is located. This is also the meaning of detaching a Software Clock later.
Obtain the synchronization lock on the base where the Software Clock is located (the spin lock in the struct tvec_base variable), return the base of the Software Clock, and save it in the base variable.
If the Software Clock is in pending state (in base, ready for execution), uninstall the Software Clock
Obtain the base pointer on the CPU (type: struct tvec_base *) and save it in new_base.
If the base and new_base are different, that is, the Software Clock is migrated (from one CPU to another ), if the processing function of the software clock is not running on the CPU before the migration, set the base of the Software Clock to NULL first, then, set the base of the Software Clock to new_base. Otherwise, go to Step 5.
Set the Software Clock expiration time
Call the internal_add_timer function to add the software clock to the base of the Software Clock (the base of the current CPU)
Release lock
It is necessary to explain in detail how the software clock is added to the base of the Software Clock (the tv1 ~ Tv5), because this is the basis of Software Clock processing. Let's look at the implementation of the internal_add_timer function, as shown in Figure 3-3.
Listing 3-3 internal_add_timer Functions
Static void Merge (struct tvec_base * base, struct timer_list * timer) {unsigned long expires = timer-> expires; unsigned long idx = expires-base-> struct; struct list_head * vec; if (idx <TVR_SIZE) {int I = expires & TVR_MASK; vec = base-> tv1.vec + I;} else if (idx <1 <(TVR_BITS + TVN_BITS )) {int I = (expires> TVR_BITS) & TVN_MASK; vec = base-> tv2.vec + I;} else if (idx <1 <(TVR_BITS + 2 * TVN_BITS )) {int I = (expires >>( TVR_BITS + TVN_BITS) & TVN_MASK; vec = base-> tv3.vec + I ;} else if (idx <1 <(TVR_BITS + 3 * TVN_BITS) {int I = (expires> (TVR_BITS + 2 * TVN_BITS) & TVN_MASK; vec = base-> tv4.vec + I;} else if (signed long) idx <0) {vec = base-> tv1.vec + (base-> timer_jiffies & TVR_MASK );} else {int I; if (idx> 0 xfffffful) {idx = 0 xfffffful; expires = idx + base-> timer_jiffies ;} I = (expires> (TVR_BITS + 3 * TVN_BITS) & TVN_MASK; vec = base-> tv5.vec + I;} list_add_tail (& timer-> entry, vec );}
Code explanation:
Calculate the difference between the expiration time of the Software Clock and the timer_jiffies (the expiration time of the Software Clock currently being processed), and store it as an index in the idx variable.
Determine the interval of idx, in
[0,] or (, 0) (the Software Clock has expired), it will be added to tv1
[,], To be added to tv2
[,], To be added to tv3
[,], To be added to tv4
[,), It will be added to tv5, but the actual maximum value is 0 xffffffffUL
Calculate the specific position to be added (in which linked list, that is, tv1 ~ Which sub-linked list of tv5, refer to-1)
Finally, add it to the corresponding linked list.
From this function, we can know that the kernel adds the software clock to the base where the Software Clock is located according to the relative value of the Software Clock expiration time (relative to the value of timer_jiffies.
3.3.2 delete a Software Clock
The kernel can call the del_timer function to delete the Software Clock. The del_timer code is shown in listing 3-4.
Listing 3-4 del_timer Functions
Int del_timer (struct timer_list * timer) {struct tvec_base * base; unsigned long flags; int ret = 0 ;...... If (timer_pending (timer) {base = lock_timer_base (timer, & flags); if (timer_pending (timer) {detach_timer (timer, 1); ret = 1 ;} spin_unlock_irqrestore (& base-> lock, flags);} return ret ;}
Code explanation:
Checks whether the software clock is in pending state (in base, ready to run). If not, the function returns
If it is in pending status, the lock is obtained.
Check again whether the software clock is in pending status (the Software Clock may be uninstalled). If not, release the lock and then the function returns
If it is still pending, it will be detached, and then the lock will be released. The function returns
In the SMP system, you need to use the del_timer_sync function to delete the Software Clock. Before explaining the del_timer_sync function, let's take a look at the implementation of the try_to_del_timer_sync function (this function is used by the del_timer_sync function). The Code is shown in listing 3-5.
Listing 3-5 try_to_del_timer_sync Functions
Int try_to_del_timer_sync (struct timer_list * timer) {struct tvec_base * base; unsigned long flags; int ret =-1; base = lock_timer_base (timer, & flags ); if (base-> running_timer = timer) goto out; ret = 0; if (timer_pending (timer) {detach_timer (timer, 1); ret = 1;} out: spin_unlock_irqrestore (& base-> lock, flags); return ret ;}
This function checks whether the currently running software clock is the Software Clock. If yes, the function returns-1, indicating that the software clock cannot be deleted currently; if the software clock is not in pending status, if not, the function returns 0, indicating that the software clock has been uninstalled. If the software clock is in pending status, the function returns 1, indicates that the software clock is successfully uninstalled.
[1] [2] [3] Next page