2009-06-02

C code for determining the operating system

In the last days I have been busy trying to making our analysis program (written in a strange mixture of C, C++ and ITT IDL) work under Windows, Linux, Mac OS X and FreeBSD. I have discovered that a severe bottleneck was represented by the data transmission through a local socket. Under Linux and FreeBSD, sending ~500 packets of a few bytes each was taking ages to complete, while under Mac OS X the same task completed in a fraction of second. This is really strange, considering that we were using local sockets, i.e. communications between two tasks on the same machine.
After a little digging with Google, I discovered that the standard algorithm used by Linux and FreeBSD to send data through a socket can sometimes induce severe slowdowns. Luckly, there is a simple solution: call setsockopt and set TCP_NODELAY to 1. Doing this on our code made a performance boost of several orders of magnitude.
Since I wanted not to change things on those operating system that have never raised troubles (Mac OS X), I decided to put the call to setsockopt within an #ifdef#endif block. But what macros must be checked to determine if we are compiling under Windows, Linux, FreeBSD or Mac OS X? It turned out that this information is not easy to find on the internet.
By Googling and using the clever trick suggested in this Wikipedia page (i.e. call gcc -dM -E - < /dev/null to discover which macros are automatically defined by the preprocessor), I have been able to find the following macros:
  • FreeBSD defines __FreeBSD__ (at least FreeBSD 7.x);
  • Under Linux you must check either __linux or __linux__;
  • Windows defines _WIN32. (this was easy, as it is clearly specified in MSDN).
I have had no need so far to find this information for Mac OS X. I suppose that the macro to use is something like __darwin,__Darwin__ or whatever.

Update: (2011/05/17) Predef has nice tables containing the preprocessor macros defined by many compilers and operating systems. Very useful!