Files
The Arithmetic Module

The arithmetic module provides safe arithmetics for C types. Overflows or underflows in the type's range are reported as errors to the transaction. More...

Files

file  picotm-arithmetic-ctypes.h
 Transactional, safe arithmetics for native C types.
 
file  picotm-arithmetic.h
 Public interfaces of picotm's arithmetic module.
 

Detailed Description

The arithmetic module provides safe arithmetic operations for C types. Overflows, underflows and undefined operations are detected and reported to the transaction's recovery code. Supported operations are additions, subtractions, multiplications and divisions.

Additions are in the form add_<type>_tx() where <type> is the name of the C type. For example, overflow-safe addition of two long integer values is performed by the following transaction.

long res = add_long_tx(INT_MAX, INT_MAX);
(picotm_error_as_errno() == ERANGE)) {
// An error happened during an arithmetic operation.
}

The success of this operations depends on the size of type long. If long is 64 bit in size, the addition will return the sum of both operands. If long is only 32 bit in size, which is the same of int on most platforms, the addition will overflow and the function will roll the transaction back to the previous consistent state and report ERANGE to the recovery code.

The arithmetic module comes with support for all native C types. We can define safe addition for application-specific types with the C preprocessor macros PICOTM_ARITHMETIC_ADD_S_TX(), PICOTM_ARITHMETIC_ADD_U_TX() and PICOTM_ARITHMETIC_ADD_F_TX(). The first macro, PICOTM_ARITHMETIC_ADD_S_TX() supports signed integer types; the second macro, PICOTM_ARITHMETIC_ADD_U_TX(), supports unsigned integer types. Finally, the third macro, PICOTM_ARITHMETIC_ADD_F_TX(), supports floating-point types.

For example, an application might use the specialized floating-point type float100, which only contains values from minus 100 to plus 100.

typedef float float100;
#define FLT100_MAX 100 // similar to FLT_MAX from <float.h>

We can use the macro PICOTM_ARITHMETIC_ADD_F_TX() to create an add function that overflows at plus 100 and underflows at minus 100.

float100
float100_add(float100 lhs, float100 rhs)
{
return lhs + rhs;
}
float100
float100_sub(float100 lhs, float100 rhs)
{
return lhs - rhs;
}
PICOTM_ARITHMETIC_ADD_F_TX(float100, float100, FLT100_MAX, 0.f,
float100_add, float_100_sub)

The first two parameters are name and C type of the function. The third parameter is the type's range or extension. For float100 it ranges from -FLT100_MAX to FLT100_MAX. The forth paramater is the value of the type's operation's identity element (i.e., the value that does nothing for the operation). For additions, the identity element is 0. The two final macro parameters are the type's primitive addition and subtraction functions. These functions perform the plain operations without safety checks.

The example macro invocation expands to the following function.

static inline
float100
add_float100_tx(float100 lhs, float100 rhs)
{
... // safe addition
}

A transaction can use it like add_long_tx() in the previous example.

float100 res = add_float100_tx(75.f, 25.f);
(picotm_error_as_errno() == ERANGE)) {
// An error happened during an arithmetic operation.
}

Picotm provides equivalent generator macros for subtraction, multiplication and division of signed integer types, unsigned integer types and floating-point types. Defining subtraction, multiplication and division completes elementary arithmetics for float100. The full example code is shown below.

float100
float100_add(float100 lhs, float100 rhs)
{
return lhs + rhs;
}
float100
float100_sub(float100 lhs, float100 rhs)
{
return lhs - rhs;
}
float100
float100_mul(float100 lhs, float100 rhs)
{
return lhs * rhs;
}
float100
float100_div(float100 lhs, float100 rhs)
{
return lhs / rhs;
}
PICOTM_ARITHMETIC_ADD_F_TX(float100, float100, FLT100_MAX, 0.f,
float100_add, float_100_sub)
PICOTM_ARITHMETIC_SUB_F_TX(float100, float100, FLT100_MAX, 0.f,
float100_add, float_100_sub)
PICOTM_ARITHMETIC_MUL_F_TX(float100, float100, FLT100_MAX, 1.f, 0.f,
float100_mul, float_100_div)
PICOTM_ARITHMETIC_DIV_F_TX(float100, float100, FLT100_MAX, 1.f, 0.f,
float100_div, float_100_div)

The identity element for multiplication and division is 1. In addition to the identity element, the generator macros for multiplication and division take an additional absorbing element. This is the value the maps each factor to the absorbing element itself. For multiplication this value is 0. For divisions by the absorbing element, the generated division function rolls the transaction back and returns the errno code EDOM to the recovery mode.

Results or parameters of arithmetics operations should be loaded into the transaction or stored from the transaction using the Transactional Memory module.