blob: b9b6c7bf2925d75846e1198a32ffaa29a47cd353 [file] [log] [blame]
/*
* Copyright (c) 2008-2013 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
* IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
* which are subject to change in future releases of Mac OS X. Any applications
* relying on these interfaces WILL break.
*/
#ifndef __DISPATCH_SEMAPHORE_INTERNAL__
#define __DISPATCH_SEMAPHORE_INTERNAL__
struct dispatch_queue_s;
DISPATCH_CLASS_DECL(semaphore, OBJECT);
struct dispatch_semaphore_s {
DISPATCH_OBJECT_HEADER(semaphore);
intptr_t volatile dsema_value;
intptr_t dsema_orig;
_dispatch_sema4_t dsema_sema;
};
/*
* Dispatch Group State:
*
* Generation (32 - 63):
* 32 bit counter that is incremented each time the group value reaaches
* 0 after a dispatch_group_leave. This 32bit word is used to block waiters
* (threads in dispatch_group_wait) in _dispatch_wait_on_address() until the
* generation changes.
*
* Value (2 - 31):
* 30 bit value counter of the number of times the group was entered.
* dispatch_group_enter counts downward on 32bits, and dispatch_group_leave
* upward on 64bits, which causes the generation to bump each time the value
* reaches 0 again due to carry propagation.
*
* Has Notifs (1):
* This bit is set when the list of notifications on the group becomes non
* empty. It is also used as a lock as the thread that successfuly clears this
* bit is the thread responsible for firing the notifications.
*
* Has Waiters (0):
* This bit is set when there are waiters (threads in dispatch_group_wait)
* that need to be woken up the next time the value reaches 0. Waiters take
* a snapshot of the generation before waiting and will wait for the
* generation to change before they return.
*/
#define DISPATCH_GROUP_GEN_MASK 0xffffffff00000000ULL
#define DISPATCH_GROUP_VALUE_MASK 0x00000000fffffffcULL
#define DISPATCH_GROUP_VALUE_INTERVAL 0x0000000000000004ULL
#define DISPATCH_GROUP_VALUE_1 DISPATCH_GROUP_VALUE_MASK
#define DISPATCH_GROUP_VALUE_MAX DISPATCH_GROUP_VALUE_INTERVAL
#define DISPATCH_GROUP_HAS_NOTIFS 0x0000000000000002ULL
#define DISPATCH_GROUP_HAS_WAITERS 0x0000000000000001ULL
DISPATCH_CLASS_DECL(group, OBJECT);
struct dispatch_group_s {
DISPATCH_OBJECT_HEADER(group);
DISPATCH_UNION_LE(uint64_t volatile dg_state,
uint32_t dg_bits,
uint32_t dg_gen
) DISPATCH_ATOMIC64_ALIGN;
struct dispatch_continuation_s *volatile dg_notify_head;
struct dispatch_continuation_s *volatile dg_notify_tail;
};
DISPATCH_ALWAYS_INLINE
static inline uint32_t
_dg_state_value(uint64_t dg_state)
{
return (uint32_t)(-((uint32_t)dg_state & DISPATCH_GROUP_VALUE_MASK)) >> 2;
}
DISPATCH_ALWAYS_INLINE
static inline uint32_t
_dg_state_gen(uint64_t dg_state)
{
return (uint32_t)(dg_state >> 32);
}
dispatch_group_t _dispatch_group_create_and_enter(void);
void _dispatch_group_dispose(dispatch_object_t dou, bool *allow_free);
DISPATCH_COLD
size_t _dispatch_group_debug(dispatch_object_t dou, char *buf,
size_t bufsiz);
void _dispatch_semaphore_dispose(dispatch_object_t dou, bool *allow_free);
DISPATCH_COLD
size_t _dispatch_semaphore_debug(dispatch_object_t dou, char *buf,
size_t bufsiz);
#endif