For 64-bit division, what is the difference between using / and do_div?
only to improve performance? and is it architecture dependent?
The source code is here.
The purpose of this macro and functions in this module is optimization. The comment in the kernel code is pretty clear:
/*
* do_div() is NOT a C function. It wants to return
* two values (the quotient and the remainder), but
* since that doesn't work very well in C, what it
* does is:
*
* - modifies the 64-bit dividend _in_place_
* - returns the 32-bit remainder
*
* This ends up being the most efficient "calling
* convention" on x86.
*/
The macro is used in the kernel to compute both the quotient and the remainder in a single step with a single division instead of 2 operations in standard C potentially producing 2 division opcodes.
Indeed Intel x86 CPUs compute both the quotient and the remainder of an integer division with a single instruction. The macro uses inline assembly to take advantage of this, while the C compiler might not optimize 2 separate computations with / and % into a single opcode.
At the time this code was written, most compilers did not and the division opcode was very costly, so Linus decided to use a special function to optimize this computation.
Note that the C Standard provides a set of functions for this purpose (declared in <stdlib.h>):
div_t div(int numer, int denom);
ldiv_t ldiv(long int numer, long int denom);
lldiv_t lldiv(long long int numer, long long int denom);
The linux kernel targets systems that may not have a standard compliant compiler and definitely predates some of these standard additions, so it has its own versions of these functions as a macro, and some others in the same module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With