[libdispatch-dev] libdispatch on VS 2008 and VS 2010 64bit
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 . 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,
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  and this truncated value then
gets stored in dispatch_source_s::ds_pending_data_mask . If the original
value were used instead, a 64-bit mask would be usable. So change  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  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  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!
More information about the libdispatch-dev