#ifdef KERNEL_PRIVATE
#ifndef _KERN_WAIT_QUEUE_H_
#define _KERN_WAIT_QUEUE_H_
#include <mach/mach_types.h>
#include <mach/sync_policy.h>
#include <mach/kern_return.h>
#include <kern/kern_types.h>
#include <sys/cdefs.h>
#ifdef MACH_KERNEL_PRIVATE
#include <kern/lock.h>
#include <kern/queue.h>
#include <machine/cpu_number.h>
typedef struct wait_queue {
unsigned int
wq_type:16,
wq_fifo:1,
wq_prepost:1,
:0;
hw_lock_data_t wq_interlock;
queue_head_t wq_queue;
} WaitQueue;
typedef struct wait_queue_set {
WaitQueue wqs_wait_queue;
queue_head_t wqs_setlinks;
queue_head_t wqs_preposts;
} WaitQueueSet;
#define wqs_type wqs_wait_queue.wq_type
#define wqs_fifo wqs_wait_queue.wq_fifo
#define wqs_prepost wqs_wait_queue.wq_prepost
#define wqs_queue wqs_wait_queue.wq_queue
typedef struct wait_queue_element {
queue_chain_t wqe_links;
void * wqe_type;
wait_queue_t wqe_queue;
} WaitQueueElement;
typedef WaitQueueElement *wait_queue_element_t;
typedef struct _wait_queue_link {
WaitQueueElement wql_element;
queue_chain_t wql_setlinks;
queue_chain_t wql_preposts;
wait_queue_set_t wql_setqueue;
} WaitQueueLink;
#define wql_links wql_element.wqe_links
#define wql_type wql_element.wqe_type
#define wql_queue wql_element.wqe_queue
#define _WAIT_QUEUE_inited 0xf1d0
#define _WAIT_QUEUE_SET_inited 0xf1d1
#define wait_queue_is_queue(wq) \
((wq)->wq_type == _WAIT_QUEUE_inited)
#define wait_queue_is_set(wqs) \
((wqs)->wqs_type == _WAIT_QUEUE_SET_inited)
#define wait_queue_is_valid(wq) \
(((wq)->wq_type & ~1) == _WAIT_QUEUE_inited)
#define wait_queue_empty(wq) (queue_empty(&(wq)->wq_queue))
#define wait_queue_held(wq) (hw_lock_held(&(wq)->wq_interlock))
#define wait_queue_lock_try(wq) (hw_lock_try(&(wq)->wq_interlock))
#if defined(i386)
#define hwLockTimeOut LockTimeOutTSC
#else
#define hwLockTimeOut LockTimeOut
#endif
static inline void wait_queue_lock(wait_queue_t wq) {
if (!hw_lock_to(&(wq)->wq_interlock, hwLockTimeOut * 2))
panic("wait queue deadlock - wq=%p, cpu=%d\n", wq, cpu_number(
));
}
static inline void wait_queue_unlock(wait_queue_t wq) {
assert(wait_queue_held(wq));
hw_lock_unlock(&(wq)->wq_interlock);
}
#define wqs_lock(wqs) wait_queue_lock(&(wqs)->wqs_wait_queue)
#define wqs_unlock(wqs) wait_queue_unlock(&(wqs)->wqs_wait_queue)
#define wqs_lock_try(wqs) wait_queue__try_lock(&(wqs)->wqs_wait_queue)
#define wqs_is_preposted(wqs) ((wqs)->wqs_prepost && !queue_empty(&(wqs)->wqs_preposts))
#define wql_is_preposted(wql) ((wql)->wql_preposts.next != NULL)
#define wql_clear_prepost(wql) ((wql)->wql_preposts.next = (wql)->wql_preposts.prev = NULL)
#define wait_queue_assert_possible(thread) \
((thread)->wait_queue == WAIT_QUEUE_NULL)
__private_extern__ void wait_queue_bootstrap(void);
__private_extern__ wait_result_t wait_queue_assert_wait64_locked(
wait_queue_t wait_queue,
event64_t wait_event,
wait_interrupt_t interruptible,
uint64_t deadline,
thread_t thread);
__private_extern__ void wait_queue_pull_thread_locked(
wait_queue_t wait_queue,
thread_t thread,
boolean_t unlock);
__private_extern__ kern_return_t wait_queue_wakeup64_all_locked(
wait_queue_t wait_queue,
event64_t wake_event,
wait_result_t result,
boolean_t unlock);
__private_extern__ kern_return_t wait_queue_wakeup64_one_locked(
wait_queue_t wait_queue,
event64_t wake_event,
wait_result_t result,
boolean_t unlock);
__private_extern__ thread_t wait_queue_wakeup64_identity_locked(
wait_queue_t wait_queue,
event64_t wake_event,
wait_result_t result,
boolean_t unlock);
__private_extern__ kern_return_t wait_queue_wakeup64_thread_locked(
wait_queue_t wait_queue,
event64_t wake_event,
thread_t thread,
wait_result_t result,
boolean_t unlock);
__private_extern__ uint32_t num_wait_queues;
__private_extern__ struct wait_queue *wait_queues;
static inline uint32_t wq_hash(char *key)
{
uint32_t hash = 0;
size_t i, length = sizeof(char *);
for (i = 0; i < length; i++) {
hash += key[i];
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
#define wait_hash(event) \
(wq_hash((char *)&event) % (num_wait_queues))
#endif
__BEGIN_DECLS
extern unsigned int wait_queue_set_size(void);
extern unsigned int wait_queue_link_size(void);
extern kern_return_t wait_queue_init(
wait_queue_t wait_queue,
int policy);
extern wait_queue_set_t wait_queue_set_alloc(
int policy);
extern kern_return_t wait_queue_set_init(
wait_queue_set_t set_queue,
int policy);
extern kern_return_t wait_queue_set_free(
wait_queue_set_t set_queue);
extern wait_queue_link_t wait_queue_link_alloc(
int policy);
extern kern_return_t wait_queue_link_free(
wait_queue_link_t link_element);
extern kern_return_t wait_queue_link(
wait_queue_t wait_queue,
wait_queue_set_t set_queue);
extern kern_return_t wait_queue_link_noalloc(
wait_queue_t wait_queue,
wait_queue_set_t set_queue,
wait_queue_link_t link);
extern boolean_t wait_queue_member(
wait_queue_t wait_queue,
wait_queue_set_t set_queue);
extern kern_return_t wait_queue_unlink(
wait_queue_t wait_queue,
wait_queue_set_t set_queue);
extern kern_return_t wait_queue_unlink_all(
wait_queue_t wait_queue);
extern kern_return_t wait_queue_set_unlink_all(
wait_queue_set_t set_queue);
kern_return_t wait_queue_sub_init(
wait_queue_set_t set_queue,
int policy);
kern_return_t wait_queue_sub_clearrefs(
wait_queue_set_t wq_set);
extern kern_return_t wait_subqueue_unlink_all(
wait_queue_set_t set_queue);
extern wait_queue_t wait_queue_alloc(
int policy);
extern kern_return_t wait_queue_free(
wait_queue_t wait_queue);
extern wait_result_t wait_queue_assert_wait64(
wait_queue_t wait_queue,
event64_t wait_event,
wait_interrupt_t interruptible,
uint64_t deadline);
extern kern_return_t wait_queue_wakeup64_one(
wait_queue_t wait_queue,
event64_t wake_event,
wait_result_t result);
extern kern_return_t wait_queue_wakeup64_all(
wait_queue_t wait_queue,
event64_t wake_event,
wait_result_t result);
extern kern_return_t wait_queue_wakeup64_thread(
wait_queue_t wait_queue,
event64_t wake_event,
thread_t thread,
wait_result_t result);
extern wait_result_t wait_queue_assert_wait(
wait_queue_t wait_queue,
event_t wait_event,
wait_interrupt_t interruptible,
uint64_t deadline);
extern kern_return_t wait_queue_wakeup_one(
wait_queue_t wait_queue,
event_t wake_event,
wait_result_t result);
extern kern_return_t wait_queue_wakeup_all(
wait_queue_t wait_queue,
event_t wake_event,
wait_result_t result);
extern kern_return_t wait_queue_wakeup_thread(
wait_queue_t wait_queue,
event_t wake_event,
thread_t thread,
wait_result_t result);
__END_DECLS
#endif
#endif