VMware 12.1.1 and 4.7.0-1

VMware 12.1.1 and 4.7.0-1 [openSUSE Tumbleweed (20160730) (x86_64)]:

1. VMware Virtual ethernet module:

/usr/lib/vmware/modules/source/vmnet-only/netif.c: In function ‘VNetNetifStartXmit’:
/usr/lib/vmware/modules/source/vmnet-only/netif.c:468:7: error: ‘struct net_device’ has no member named ‘trans_start’; did you mean ‘mem_start’?
    dev->trans_start = jiffies;
       ^~

Robert Gadsdon’s solution was to remove that line entirely:
http://rglinuxtech.com/?p=1746

Also virtualbox developers did basically the same:
https://www.virtualbox.org/ticket/15444
https://www.virtualbox.org/changeset/61429/vbox

VMware and 4.6.1-1

Today while trying to compile kernel modules for VMware Workstation 12.1.1 + 4.6.1-1-default [openSUSE Tumbleweed (20160422) (x86_64)] I got two compilation errors:

1. VMware Virtual ethernet module:

/usr/lib/vmware/modules/source/vmnet-only/userif.c:116:13: error: too many arguments to function ‘get_user_pages’
    retval = get_user_pages(current, current->mm, addr,
             ^

2. VMware Virtual machine monitor:

/usr/lib/vmware/modules/source/vmmon-only/linux/hostif.c:1165:13: error: too many arguments to function ‘get_user_pages’
    retval = get_user_pages(current, current->mm, (unsigned long)uvAddr,
             ^

VMware Community member alexsandr1981 has the correct answer in the discussion, which is to replace every get_user_pages call with get_user_pages_remote calls.
After replacing the original tar, the compilation succeeded for me.

The dangers and sideffects of MACROS

This article is a collection of practical examples of unexpected behavior while using MACROS. I also collected a few general opinions on the usage of macros.

Dangerous situations:

// A macro that returns the absolute value of i
#define unsafe(i)  \
        ( (i) >= 0 ? (i) : -(i) )

// An inline function that returns the absolute value of i
inline
int safe(int i)
{
  return i >= 0 ? i : -i;
}

int f();

void userCode(int x)
{
  int ans;

  ans = unsafe(x++);   // Error! x is incremented twice
  ans = unsafe(f());   // Danger! f() is called twice

  ans = safe(x++);     // Correct! x is incremented once
  ans = safe(f());     // Correct! f() is called once
}

“Also unlike macros, argument types are checked, and necessary conversions are performed correctly.”
Source: C++FAQ

#include
#include
#define double(x) ((x)+(x))

int main()
{
    int x = 3;
    int y = double (++x);

    printf("y is %d\n",y);

    return 0;
}

Instead of the expected 8 this will yield 10!

y = (++x) + (++x);
/*
the stack is :
+
++x
++x

- the first '+' is unstacked
- the first '++x' is evaluated and unstacked => x = 4
- the second '++x'is evaluated and unstacked => x = 5
- then the '+' give x+x = 5+5 = 10*/

Source: Wikipedia

Using a macro instead of writing a function for max causes calling getValue() twice instead of just once, which may have negative sideffects.

#include

inline int max(const int a, const int b){ return (a>b)?a:b; }

#ifndef MAX
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

int getValue()
{
    printf("getValue has been called!\n");
    return 42;
}

int main(int argc, char** argv)
{
    int x=0;
    x=max(2,getValue());
    printf("X: %i\n",x);
    return 0;
}

 

ferenc@fileserver:~> gcc -Wall -o makrotest.o makrotest.c && ./makrotest.o
getValue has been called!
getValue has been called!
X: 42
ferenc@fileserver:~> gcc -Wall -DMAX -o makrotest.o makrotest.c && ./makrotest.o
getValue has been called!
X: 42
ferenc@fileserver:~>

Original Source: Robert Prouse

#define ASPECT_RATIO 1.653

vs

const double AspectRatio = 1.653;

What are legitimate uses of macros?

In C++ (Google Style Guide) for example to explicitly disallow copying and copy assignment.

DISALLOW_COPY_AND_ASSIGN(ClassName);

which would cause this:

private:
        ClassName(const ClassName&);
        void operator=(const ClassName&);

Google Style C++ Guide

In C, and in the Linux kernel it’s often used to fake iterators:

#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
     pos = n, n = pos->next)

In both languages, when you really need the preprocessor symbols like __LINE__, __FILE__, __func__, it is usually acceptable.

Macro rules

“Macros with multiple statements should be enclosed in a do – while block” Linux Kernel CodingStyle

Why? Consider this

if( something ) function1(); else function2();

If function1() is actually a macro, just using { } requires you to omit the semicolon at the point of use, but do { } while(0) lets you use exactly the same syntax as for a real function. Plus using return in a simple { } block would cause the calling function to return, but in a do { } while(0) you can use break to end the execution of your code in the macro.

Some general opinions:

“In addition, in the case of a floating point constant (such as in this example), use of the constant may yield smaller code than
using a #define. That’s because the preprocessor’s blind substitution of the macro name ASPECT_RATIO with 1.653 could
result in multiple copies of 1.653 in your object code, while the use of the constant AspectRatio should never result in more
than one copy.”

Source: Scott Meyers Effective C++ 3rd edition

“Rationale: The C preprocessor is a powerful obfuscation tool that can destroy code
clarity and befuddle many text based checkers. The effect of constructs in unrestricted
preprocessor code can be extremely hard to decipher, even with a formal language
definition in hand. In a new implementation of the C preprocessor, developers often
have to resort to using earlier implementations as the referee for interpreting complex
defining language in the C standard. The rationale for the caution against conditional
compilation is equally important. Note that with just ten conditional compilation
directives, there could be up to 210 possible versions of the code, each of which would
have to be tested– causing a huge increase in the required test effort.”

Gerard J.Holzmann NASA Jet Propulsion Laboratory

“Generally, inline functions are preferable to macros resembling functions.”
Linux Kernel CodingStyle