[libdispatch-dev] libdispatch on VS 2008 and VS 2010 64bit

DrPizza DrPizza at quiscalusmexicanus.org
Sun Jun 12 19:28:11 PDT 2011

I may be wrong, but I believe libxdispatch needs further modifications 
before it'll build reasonable 64-bit binaries, at least in VC++. There are 
some bugs that definitely need fixing, and some warts that would be nice to 

Mac OS X and Linux are both, I believe, LP64 platforms. Win32 (er... Win64?) 
isn't; if you want a 64-bit integer, you'll have to use the hideous "long 
long" (though I would have to double check that even works; I know it works 
for compiling C++, but VC++ has no C99 support, so I'm not sure what C mode 
does) or __int64.

To attain reasonable compatibility between the platforms, I believe we 
should therefore change any location that currently uses long to use intptr_t, 
and any location using unsigned long to use uintptr_t. There are possibly a 
few exceptions; we can probably get away with using longs for semaphore counts, 
because four billion is a lot, and long is still fine for queue priorities, as 
there are only three/six.

IMHO we should change anything that might reasonably be used for pointer-size 
values. This has some API-level consequences; I think it would be good if we 
unsigned long dispatch_source_get_data(dispatch_source_t source);
void dispatch_source_merge_data(dispatch_source_t source, unsigned long value);

This change in turn has consequences in a few places within the codebase, 
where longs and related types need to be changed to intptr_ts.

It would be desirable in many regards to change the mask similarly, in:
unsigned long dispatch_source_get_mask(dispatch_source_t source);
dispatch_source_t dispatch_source_create(dispatch_source_type_t type,
                                         uintptr_t handle,
                                         unsigned long mask,
                                         dispatch_queue_t queue);

However, this is a problem, because struct kevent uses an int32 for the mask 
(libdispatch stores the mask in the fflags member, which has type u_int). So, 
for that matter, does kevent64_s. Two thoughts occur. One, switch to 
kevent64_s and store the mask in ext[0]. Two, stop using long for the mask 
value, so that the interface becomes honest. We can't use it as a long, so 
stop pretending that we can.

There are also repercussions for atomic operations. VC++'s atomic operations 
are sadly not as convenient as gcc's overloaded ones. If this were a C++ 
project then that would of course not be a problem, but it isn't, so it is. 
Generally speaking, VC++ has two sets of atomic operations; 32-bit ones, that 
are defined in terms of LONG, and 64-bit ones, that use LONGLONG or similar. 
These are plain old C functions--no overloads--so have different names.

The functions (well, macros) for which this is most relevant are:
dispatch_atomic_add(p, v)
dispatch_atomic_sub(p, v)

In 32-bit builds, they use InterlockedExchangeAdd--which works on longs--in 
64-bit builds, InterlockedExchangeAdd--which works on __int64s. To be safe, 
64-bit builds must, therefore, use __int64 operands. Otherwise, 32-bit overflow 
will cause the subsequent 32-bit words to be corrupted. There may also be 
alignment issues.

The operands are, however, uint32_ts (dispatch_queue_s::dq_running), unsigned 
longs (dispatch_source_s::ds_pending_data), or unsigned ints (

dispatch_source_s::ds_pending_data is also used with a dispatch_atomic_xchg 
call, so if it is changed to 64-bit (to make the dispatch_atomic_add safe) then 
dispatch_atomic_xchg would likewise have to be altered to use 64-bit integers.

dispatch_source_s::ds_pending_data is the only one likely to ever cause a 
problem, of course, as it's the only one that might reasonable wrap around 
with 32-bit values.

There are also a few pointer trunctions (probably harmless, e.g. the casts to 
long in _dispatch_continuation_pop).

Ultimately I think there are two options. The slightly easier one is to ensure 
that VC++ builds only use 32-bit atomic operations and include a note somewhere 
that while 64-bit Linux or Mac OS X builds can use 64-bit values in some 
places, this won't be possible in Windows.

My preference would be to go an alternative route: replace longs with intptr_ts 
and ensure that atomic operations are working on the right data types. If it's 
desirable to keep suspend/reference counts as 32-bit integers, then there'll 
need to be both 64- and 32-bit atomic arithmetic; I think it's easier to just 
make them use pointer-sized integers too. That's what my fork does.

> -----Original Message-----
> From: libdispatch-dev-bounces at lists.macosforge.org [mailto:libdispatch-dev-
> bounces at lists.macosforge.org] On Behalf Of Marius Zwicker
> Sent: 26 May 2011 21:02
> To: libdispatch-dev at lists.macosforge.org
> Subject: [libdispatch-dev] libdispatch on VS 2008 and VS 2010 64bit
> Hi everyone,
> Just wanted to inform you that as of today the trunk of the xdispatch project
> is supporting building with Visual Studio 2008 and Visual Studio
> 2010 64bit as well. Although VS 2008 is of limited use as we cannot provide
> blocks/closures/lambdas on this platform.
> With this milestone I consider libdispatch (and xdispatch/QtDispatch of
> course) production ready on Linux 32bit/64bit, Windows 32bit/64bit (using
> VS2008 or VS2010) and on Mac OS 64bit.
> As always I welcome any comments.
> Regards,
> Marius
> _______________________________________________
> libdispatch-dev mailing list
> libdispatch-dev at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo.cgi/libdispatch-dev

More information about the libdispatch-dev mailing list