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

DrPizza DrPizza at quiscalusmexicanus.org
Tue Jun 14 23:02:26 PDT 2011

> I don't think that the 'mask' parameter can reasonably be used for pointer-
> size values. According to the documentation, the possible values of 'mask'
> are well-defined and fit within a 32-bit integer type [1]. There is one
> exception: DISPATCH_SOURCE_TYPE_DATA_OR supports arbitrary values for the
> 'mask' parameter.
Yes, it is this one that I have in mind.

> It should be sufficient to document in the manpage that the 'mask'
> parameter is limited to the lower 32 bits for the
> DISPATCH_SOURCE_TYPE_DATA_OR source type. If anyone wants to use more than
> 32 bitflags in a single bitmask, then they are probably doing something wrong
> :)
Well, documenting it would certainly be better than the current situation, 
silent truncation.

Nonetheless, it does feel a bit peculiar to the user; the data itself is a 
64-bit long (in 64-bit builds) so it's strange that only the bottom 32 bits 
should be usable. And in retrospect, I don't think such a restriction is 
necessary after all.

Looking through the source again, I suspect it might actually be simpler than 
I previously thought. The reason the mask gets truncated is that the (unsigned 
long) mask gets first truncated to uint32_t [1] and this truncated value then 
gets stored in dispatch_source_s::ds_pending_data_mask [2]. If the original 
value were used instead, a 64-bit mask would be usable. So change [2] to:

ds->ds_pending_data_mask = mask;

The next part of the problem is ensuring that dispatch_source_merge_data 
allows use of the full 64-bit value. We see at [3] that the unsigned long val 
parameter is stored both verbatim, in the kevent::data field, and truncated, 
in the kevent::fflags field. So that is fine; the full 64-bit value is stored 
safely and is accessible.

Finally, there's actually merging the supplied value into 
dispatch_source_s::pending_data. This is done in _dispatch_source_merge_kevent. 
Here we see that although the full kevent::data field is used for 
DISPATCH_SOURCE_TYPE_DATA_ADD, the truncated kevent::fflags is used for 
DISPATCH_SOURCE_TYPE_DATA_OR. I believe that if [4] were changed to read:

dispatch_atomic_or(&ds->ds_pending_data, ke->data & ds->ds_pending_data_mask);

then support for 64-bit masks would be complete.

This would bring the code in-line with the current documentation; it would also 
create parity between 32- and 64-bit versions: both would support full-size 
masks. I think that is a much better solution than changing the documentation!

[1]: http://libdispatch.macosforge.org/trac/browser/trunk/src/source_kevent.c#L602
[2]: http://libdispatch.macosforge.org/trac/browser/trunk/src/source_kevent.c#L609
[3]: http://libdispatch.macosforge.org/trac/browser/trunk/src/source_kevent.c#L560
[4]: http://libdispatch.macosforge.org/trac/browser/trunk/src/source_kevent.c#L536

More information about the libdispatch-dev mailing list