+void
+dispatch_group_leave(dispatch_group_t dg)
+{
+ long value = os_atomic_dec2o(dg, dg_value, release);
+ if (slowpath(value == 0)) {
+ return (void)_dispatch_group_wake(dg, true);
+ }
+ if (slowpath(value < 0)) {
+ DISPATCH_CLIENT_CRASH(value,
+ "Unbalanced call to dispatch_group_leave()");
+ }
+}
+
+void
+_dispatch_group_dispose(dispatch_object_t dou, DISPATCH_UNUSED bool *allow_free)
+{
+ dispatch_group_t dg = dou._dg;
+
+ if (dg->dg_value) {
+ DISPATCH_CLIENT_CRASH(dg->dg_value,
+ "Group object deallocated while in use");
+ }
+
+ _dispatch_sema4_dispose(&dg->dg_sema, _DSEMA4_POLICY_FIFO);
+}
+
+size_t
+_dispatch_group_debug(dispatch_object_t dou, char *buf, size_t bufsiz)
+{
+ dispatch_group_t dg = dou._dg;
+
+ size_t offset = 0;
+ offset += dsnprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ",
+ dx_kind(dg), dg);
+ offset += _dispatch_object_debug_attr(dg, &buf[offset], bufsiz - offset);
+#if USE_MACH_SEM
+ offset += dsnprintf(&buf[offset], bufsiz - offset, "port = 0x%u, ",
+ dg->dg_sema);
+#endif
+ offset += dsnprintf(&buf[offset], bufsiz - offset,
+ "count = %ld, waiters = %d }", dg->dg_value, dg->dg_waiters);
+ return offset;
+}
+