[libdispatch-changes] [187] trunk/src
source_changes at macosforge.org
source_changes at macosforge.org
Thu Feb 18 00:10:00 PST 2010
Revision: 187
http://trac.macosforge.org/projects/libdispatch/changeset/187
Author: kvv at apple.com
Date: 2010-02-18 00:09:57 -0800 (Thu, 18 Feb 2010)
Log Message:
-----------
protect transparent union use with __GNUC__
Modified Paths:
--------------
trunk/src/internal.h
trunk/src/object.c
trunk/src/object_internal.h
Modified: trunk/src/internal.h
===================================================================
--- trunk/src/internal.h 2010-02-18 05:49:14 UTC (rev 186)
+++ trunk/src/internal.h 2010-02-18 08:09:57 UTC (rev 187)
@@ -137,8 +137,13 @@
#define NSEC_PER_USEC 1000ull
/* I wish we had __builtin_expect_range() */
+#if __GNUC__
#define fastpath(x) ((typeof(x))__builtin_expect((long)(x), ~0l))
#define slowpath(x) ((typeof(x))__builtin_expect((long)(x), 0l))
+#else
+#define fastpath(x) (x)
+#define slowpath(x) (x)
+#endif
void _dispatch_bug(size_t line, long val) __attribute__((__noinline__));
void _dispatch_abort(size_t line, long val) __attribute__((__noinline__,__noreturn__));
@@ -215,8 +220,12 @@
} \
} while (0)
+#if __GNUC__
+#define DO_CAST(x) ((struct dispatch_object_s *)(x)._do)
+#else
+#define DO_CAST(x) ((struct dispatch_object_s *)(x))
+#endif
-
#ifdef __BLOCKS__
dispatch_block_t _dispatch_Block_copy(dispatch_block_t block);
void _dispatch_call_block_and_release(void *block);
Modified: trunk/src/object.c
===================================================================
--- trunk/src/object.c 2010-02-18 05:49:14 UTC (rev 186)
+++ trunk/src/object.c 2010-02-18 08:09:57 UTC (rev 187)
@@ -20,15 +20,14 @@
#include "internal.h"
-
void
-dispatch_debug(dispatch_object_t dou, const char *msg, ...)
+dispatch_debug(dispatch_object_t obj, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
- dispatch_debugv(dou._do, msg, ap);
+ dispatch_debugv(obj, msg, ap);
va_end(ap);
}
@@ -39,8 +38,10 @@
char buf[4096];
size_t offs;
- if (dou._do && dou._do->do_vtable->do_debug) {
- offs = dx_debug(dou._do, buf, sizeof(buf));
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
+ if (obj && obj->do_vtable->do_debug) {
+ offs = dx_debug(obj, buf, sizeof(buf));
} else {
offs = snprintf(buf, sizeof(buf), "NULL vtable slot");
}
@@ -53,10 +54,12 @@
void
dispatch_retain(dispatch_object_t dou)
{
- if (dou._do->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
+ if (obj->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
return; // global object
}
- if ((dispatch_atomic_inc(&dou._do->do_xref_cnt) - 1) == 0) {
+ if ((dispatch_atomic_inc(&obj->do_xref_cnt) - 1) == 0) {
DISPATCH_CLIENT_CRASH("Resurrection of an object");
}
}
@@ -64,10 +67,12 @@
void
_dispatch_retain(dispatch_object_t dou)
{
- if (dou._do->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
+ if (obj->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
return; // global object
}
- if ((dispatch_atomic_inc(&dou._do->do_ref_cnt) - 1) == 0) {
+ if ((dispatch_atomic_inc(&obj->do_ref_cnt) - 1) == 0) {
DISPATCH_CLIENT_CRASH("Resurrection of an object");
}
}
@@ -75,26 +80,28 @@
void
dispatch_release(dispatch_object_t dou)
{
- typeof(dou._do->do_xref_cnt) oldval;
+ struct dispatch_object_s *obj = DO_CAST(dou);
- if (dou._do->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
+ unsigned int oldval;
+
+ if (obj->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
return;
}
- oldval = dispatch_atomic_dec(&dou._do->do_xref_cnt) + 1;
+ oldval = dispatch_atomic_dec(&obj->do_xref_cnt) + 1;
if (fastpath(oldval > 1)) {
return;
}
if (oldval == 1) {
- if (dou._do->do_vtable == (void*)&_dispatch_source_kevent_vtable) {
- return _dispatch_source_xref_release(dou._ds);
+ if ((uintptr_t)obj->do_vtable == (uintptr_t)&_dispatch_source_kevent_vtable) {
+ return _dispatch_source_xref_release((dispatch_source_t)obj);
}
- if (slowpath(DISPATCH_OBJECT_SUSPENDED(dou._do))) {
+ if (slowpath(DISPATCH_OBJECT_SUSPENDED(obj))) {
// Arguments for and against this assert are within 6705399
DISPATCH_CLIENT_CRASH("Release of a suspended object");
}
- return _dispatch_release(dou._do);
+ return _dispatch_release(obj);
}
DISPATCH_CLIENT_CRASH("Over-release of an object");
}
@@ -102,14 +109,16 @@
void
_dispatch_dispose(dispatch_object_t dou)
{
- dispatch_queue_t tq = dou._do->do_targetq;
- dispatch_function_t func = dou._do->do_finalizer;
- void *ctxt = dou._do->do_ctxt;
+ struct dispatch_object_s *obj = DO_CAST(dou);
- dou._do->do_vtable = (void *)0x200;
+ dispatch_queue_t tq = obj->do_targetq;
+ dispatch_function_t func = obj->do_finalizer;
+ void *ctxt = obj->do_ctxt;
- free(dou._do);
+ obj->do_vtable = (struct dispatch_object_vtable_s *)0x200;
+ free(obj);
+
if (func && ctxt) {
dispatch_async_f(tq, ctxt, func);
}
@@ -119,26 +128,28 @@
void
_dispatch_release(dispatch_object_t dou)
{
- typeof(dou._do->do_ref_cnt) oldval;
+ struct dispatch_object_s *obj = DO_CAST(dou);
- if (dou._do->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
+ unsigned int oldval;
+
+ if (obj->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
return; // global object
}
- oldval = dispatch_atomic_dec(&dou._do->do_ref_cnt) + 1;
+ oldval = dispatch_atomic_dec(&obj->do_ref_cnt) + 1;
if (fastpath(oldval > 1)) {
return;
}
if (oldval == 1) {
- if (dou._do->do_next != DISPATCH_OBJECT_LISTLESS) {
+ if (obj->do_next != DISPATCH_OBJECT_LISTLESS) {
DISPATCH_CRASH("release while enqueued");
}
- if (dou._do->do_xref_cnt) {
+ if (obj->do_xref_cnt) {
DISPATCH_CRASH("release while external references exist");
}
- return dx_dispose(dou._do);
+ return dx_dispose(obj);
}
DISPATCH_CRASH("over-release");
}
@@ -146,42 +157,61 @@
void *
dispatch_get_context(dispatch_object_t dou)
{
- return dou._do->do_ctxt;
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
+ return obj->do_ctxt;
}
void
dispatch_set_context(dispatch_object_t dou, void *context)
{
- if (dou._do->do_ref_cnt != DISPATCH_OBJECT_GLOBAL_REFCNT) {
- dou._do->do_ctxt = context;
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
+ if (obj->do_ref_cnt != DISPATCH_OBJECT_GLOBAL_REFCNT) {
+ obj->do_ctxt = context;
}
}
void
dispatch_set_finalizer_f(dispatch_object_t dou, dispatch_function_t finalizer)
{
- dou._do->do_finalizer = finalizer;
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
+ obj->do_finalizer = finalizer;
}
void
dispatch_suspend(dispatch_object_t dou)
{
- if (slowpath(dou._do->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
+ if (slowpath(obj->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
return;
}
- dispatch_atomic_add(&dou._do->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_INTERVAL);
+ (void)dispatch_atomic_add(&obj->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_INTERVAL);
}
void
dispatch_resume(dispatch_object_t dou)
{
- if (slowpath(dou._do->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
+ // Global objects cannot be suspended or resumed. This also has the
+ // side effect of saturating the suspend count of an object and
+ // guarding against resuming due to overflow.
+ if (slowpath(obj->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
return;
}
- switch (dispatch_atomic_sub(&dou._do->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_INTERVAL) + DISPATCH_OBJECT_SUSPEND_INTERVAL) {
+
+ // Switch on the previous value of the suspend count. If the previous
+ // value was a single suspend interval, the object should be resumed.
+ // If the previous value was less than the suspend interval, the object
+ // has been over-resumed.
+ switch (dispatch_atomic_sub(&obj->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_INTERVAL) + DISPATCH_OBJECT_SUSPEND_INTERVAL) {
case DISPATCH_OBJECT_SUSPEND_INTERVAL:
- _dispatch_wakeup(dou._do);
+ _dispatch_wakeup(obj);
break;
+ case DISPATCH_OBJECT_SUSPEND_LOCK:
case 0:
DISPATCH_CLIENT_CRASH("Over-resume of an object");
break;
@@ -193,6 +223,8 @@
size_t
dispatch_object_debug_attr(dispatch_object_t dou, char* buf, size_t bufsiz)
{
+ struct dispatch_object_s *obj = DO_CAST(dou);
+
return snprintf(buf, bufsiz, "refcnt = 0x%x, suspend_cnt = 0x%x, ",
- dou._do->do_ref_cnt, dou._do->do_suspend_cnt);
+ obj->do_ref_cnt, obj->do_suspend_cnt);
}
Modified: trunk/src/object_internal.h
===================================================================
--- trunk/src/object_internal.h 2010-02-18 05:49:14 UTC (rev 186)
+++ trunk/src/object_internal.h 2010-02-18 08:09:57 UTC (rev 187)
@@ -72,7 +72,7 @@
unsigned int do_suspend_cnt; \
struct dispatch_queue_s *do_targetq; \
void *do_ctxt; \
- void *do_finalizer
+ dispatch_function_t do_finalizer
#define DISPATCH_OBJECT_GLOBAL_REFCNT (~0u)
#define DISPATCH_OBJECT_SUSPEND_LOCK 1u // "word and bit" must be a power of two to be safely subtracted
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/libdispatch-changes/attachments/20100218/eb514c63/attachment.html>
More information about the libdispatch-changes
mailing list