mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
staging: vchiq: use completions instead of semaphores
It is preferred in the kernel to avoid using semaphores to wait for events, as they are optimised for the opposite situation; where the common case is that they are available and may block only occasionally. FYI see this thread: https://lkml.org/lkml/2008/4/11/323. Also completions are semantically more explicit in this case. Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> Acked-by: Stefan Wahren <stefan.wahren@i2se.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
51c0712650
commit
f27e47bc6b
5 changed files with 106 additions and 102 deletions
|
@ -44,7 +44,7 @@
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
#include <linux/semaphore.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
@ -121,9 +121,9 @@ typedef struct user_service_struct {
|
||||||
int message_available_pos;
|
int message_available_pos;
|
||||||
int msg_insert;
|
int msg_insert;
|
||||||
int msg_remove;
|
int msg_remove;
|
||||||
struct semaphore insert_event;
|
struct completion insert_event;
|
||||||
struct semaphore remove_event;
|
struct completion remove_event;
|
||||||
struct semaphore close_event;
|
struct completion close_event;
|
||||||
VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE];
|
VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE];
|
||||||
} USER_SERVICE_T;
|
} USER_SERVICE_T;
|
||||||
|
|
||||||
|
@ -138,8 +138,8 @@ struct vchiq_instance_struct {
|
||||||
VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS];
|
VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS];
|
||||||
int completion_insert;
|
int completion_insert;
|
||||||
int completion_remove;
|
int completion_remove;
|
||||||
struct semaphore insert_event;
|
struct completion insert_event;
|
||||||
struct semaphore remove_event;
|
struct completion remove_event;
|
||||||
struct mutex completion_mutex;
|
struct mutex completion_mutex;
|
||||||
|
|
||||||
int connected;
|
int connected;
|
||||||
|
@ -562,7 +562,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
|
||||||
vchiq_log_trace(vchiq_arm_log_level,
|
vchiq_log_trace(vchiq_arm_log_level,
|
||||||
"%s - completion queue full", __func__);
|
"%s - completion queue full", __func__);
|
||||||
DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
|
DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT);
|
||||||
if (down_interruptible(&instance->remove_event) != 0) {
|
if (wait_for_completion_interruptible(
|
||||||
|
&instance->remove_event)) {
|
||||||
vchiq_log_info(vchiq_arm_log_level,
|
vchiq_log_info(vchiq_arm_log_level,
|
||||||
"service_callback interrupted");
|
"service_callback interrupted");
|
||||||
return VCHIQ_RETRY;
|
return VCHIQ_RETRY;
|
||||||
|
@ -600,7 +601,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
|
||||||
insert++;
|
insert++;
|
||||||
instance->completion_insert = insert;
|
instance->completion_insert = insert;
|
||||||
|
|
||||||
up(&instance->insert_event);
|
complete(&instance->insert_event);
|
||||||
|
|
||||||
return VCHIQ_SUCCESS;
|
return VCHIQ_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -673,7 +674,8 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
|
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
|
||||||
if (down_interruptible(&user_service->remove_event)
|
if (wait_for_completion_interruptible(
|
||||||
|
&user_service->remove_event)
|
||||||
!= 0) {
|
!= 0) {
|
||||||
vchiq_log_info(vchiq_arm_log_level,
|
vchiq_log_info(vchiq_arm_log_level,
|
||||||
"%s interrupted", __func__);
|
"%s interrupted", __func__);
|
||||||
|
@ -705,7 +707,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&msg_queue_spinlock);
|
spin_unlock(&msg_queue_spinlock);
|
||||||
up(&user_service->insert_event);
|
complete(&user_service->insert_event);
|
||||||
|
|
||||||
header = NULL;
|
header = NULL;
|
||||||
}
|
}
|
||||||
|
@ -745,7 +747,7 @@ static void close_delivered(USER_SERVICE_T *user_service)
|
||||||
unlock_service(user_service->service);
|
unlock_service(user_service->service);
|
||||||
|
|
||||||
/* Wake the user-thread blocked in close_ or remove_service */
|
/* Wake the user-thread blocked in close_ or remove_service */
|
||||||
up(&user_service->close_event);
|
complete(&user_service->close_event);
|
||||||
|
|
||||||
user_service->close_pending = 0;
|
user_service->close_pending = 0;
|
||||||
}
|
}
|
||||||
|
@ -867,7 +869,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
if (status == VCHIQ_SUCCESS) {
|
if (status == VCHIQ_SUCCESS) {
|
||||||
/* Wake the completion thread and ask it to exit */
|
/* Wake the completion thread and ask it to exit */
|
||||||
instance->closing = 1;
|
instance->closing = 1;
|
||||||
up(&instance->insert_event);
|
complete(&instance->insert_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -948,9 +950,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
instance->completion_remove - 1;
|
instance->completion_remove - 1;
|
||||||
user_service->msg_insert = 0;
|
user_service->msg_insert = 0;
|
||||||
user_service->msg_remove = 0;
|
user_service->msg_remove = 0;
|
||||||
sema_init(&user_service->insert_event, 0);
|
init_completion(&user_service->insert_event);
|
||||||
sema_init(&user_service->remove_event, 0);
|
init_completion(&user_service->remove_event);
|
||||||
sema_init(&user_service->close_event, 0);
|
init_completion(&user_service->close_event);
|
||||||
|
|
||||||
if (args.is_open) {
|
if (args.is_open) {
|
||||||
status = vchiq_open_service_internal
|
status = vchiq_open_service_internal
|
||||||
|
@ -1007,7 +1009,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
has been closed until the client library calls the
|
has been closed until the client library calls the
|
||||||
CLOSE_DELIVERED ioctl, signalling close_event. */
|
CLOSE_DELIVERED ioctl, signalling close_event. */
|
||||||
if (user_service->close_pending &&
|
if (user_service->close_pending &&
|
||||||
down_interruptible(&user_service->close_event))
|
wait_for_completion_interruptible(
|
||||||
|
&user_service->close_event))
|
||||||
status = VCHIQ_RETRY;
|
status = VCHIQ_RETRY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1182,7 +1185,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
|
||||||
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
|
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
|
||||||
mutex_unlock(&instance->completion_mutex);
|
mutex_unlock(&instance->completion_mutex);
|
||||||
rc = down_interruptible(&instance->insert_event);
|
rc = wait_for_completion_interruptible(
|
||||||
|
&instance->insert_event);
|
||||||
mutex_lock(&instance->completion_mutex);
|
mutex_lock(&instance->completion_mutex);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
|
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
|
||||||
|
@ -1310,7 +1314,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
up(&instance->remove_event);
|
complete(&instance->remove_event);
|
||||||
mutex_unlock(&instance->completion_mutex);
|
mutex_unlock(&instance->completion_mutex);
|
||||||
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
|
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
|
||||||
} break;
|
} break;
|
||||||
|
@ -1350,8 +1354,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
do {
|
do {
|
||||||
spin_unlock(&msg_queue_spinlock);
|
spin_unlock(&msg_queue_spinlock);
|
||||||
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
|
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
|
||||||
if (down_interruptible(
|
if (wait_for_completion_interruptible(
|
||||||
&user_service->insert_event) != 0) {
|
&user_service->insert_event)) {
|
||||||
vchiq_log_info(vchiq_arm_log_level,
|
vchiq_log_info(vchiq_arm_log_level,
|
||||||
"DEQUEUE_MESSAGE interrupted");
|
"DEQUEUE_MESSAGE interrupted");
|
||||||
ret = -EINTR;
|
ret = -EINTR;
|
||||||
|
@ -1373,7 +1377,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
user_service->msg_remove++;
|
user_service->msg_remove++;
|
||||||
spin_unlock(&msg_queue_spinlock);
|
spin_unlock(&msg_queue_spinlock);
|
||||||
|
|
||||||
up(&user_service->remove_event);
|
complete(&user_service->remove_event);
|
||||||
if (header == NULL)
|
if (header == NULL)
|
||||||
ret = -ENOTCONN;
|
ret = -ENOTCONN;
|
||||||
else if (header->size <= args.bufsize) {
|
else if (header->size <= args.bufsize) {
|
||||||
|
@ -1979,8 +1983,8 @@ vchiq_open(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
vchiq_debugfs_add_instance(instance);
|
vchiq_debugfs_add_instance(instance);
|
||||||
|
|
||||||
sema_init(&instance->insert_event, 0);
|
init_completion(&instance->insert_event);
|
||||||
sema_init(&instance->remove_event, 0);
|
init_completion(&instance->remove_event);
|
||||||
mutex_init(&instance->completion_mutex);
|
mutex_init(&instance->completion_mutex);
|
||||||
mutex_init(&instance->bulk_waiter_list_mutex);
|
mutex_init(&instance->bulk_waiter_list_mutex);
|
||||||
INIT_LIST_HEAD(&instance->bulk_waiter_list);
|
INIT_LIST_HEAD(&instance->bulk_waiter_list);
|
||||||
|
@ -2033,12 +2037,12 @@ vchiq_release(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
/* Wake the completion thread and ask it to exit */
|
/* Wake the completion thread and ask it to exit */
|
||||||
instance->closing = 1;
|
instance->closing = 1;
|
||||||
up(&instance->insert_event);
|
complete(&instance->insert_event);
|
||||||
|
|
||||||
mutex_unlock(&instance->completion_mutex);
|
mutex_unlock(&instance->completion_mutex);
|
||||||
|
|
||||||
/* Wake the slot handler if the completion queue is full. */
|
/* Wake the slot handler if the completion queue is full. */
|
||||||
up(&instance->remove_event);
|
complete(&instance->remove_event);
|
||||||
|
|
||||||
/* Mark all services for termination... */
|
/* Mark all services for termination... */
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -2047,7 +2051,7 @@ vchiq_release(struct inode *inode, struct file *file)
|
||||||
USER_SERVICE_T *user_service = service->base.userdata;
|
USER_SERVICE_T *user_service = service->base.userdata;
|
||||||
|
|
||||||
/* Wake the slot handler if the msg queue is full. */
|
/* Wake the slot handler if the msg queue is full. */
|
||||||
up(&user_service->remove_event);
|
complete(&user_service->remove_event);
|
||||||
|
|
||||||
vchiq_terminate_service_internal(service);
|
vchiq_terminate_service_internal(service);
|
||||||
unlock_service(service);
|
unlock_service(service);
|
||||||
|
@ -2059,7 +2063,7 @@ vchiq_release(struct inode *inode, struct file *file)
|
||||||
!= NULL) {
|
!= NULL) {
|
||||||
USER_SERVICE_T *user_service = service->base.userdata;
|
USER_SERVICE_T *user_service = service->base.userdata;
|
||||||
|
|
||||||
down(&service->remove_event);
|
wait_for_completion(&service->remove_event);
|
||||||
|
|
||||||
BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);
|
BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE);
|
||||||
|
|
||||||
|
@ -2103,7 +2107,7 @@ vchiq_release(struct inode *inode, struct file *file)
|
||||||
|
|
||||||
/* Wake any blocked user-thread */
|
/* Wake any blocked user-thread */
|
||||||
if (instance->use_close_delivered)
|
if (instance->use_close_delivered)
|
||||||
up(&user_service->close_event);
|
complete(&user_service->close_event);
|
||||||
unlock_service(service);
|
unlock_service(service);
|
||||||
}
|
}
|
||||||
instance->completion_remove++;
|
instance->completion_remove++;
|
||||||
|
|
|
@ -376,7 +376,7 @@ mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread)
|
||||||
|
|
||||||
/* Unblock any sending thread. */
|
/* Unblock any sending thread. */
|
||||||
service_quota = &state->service_quotas[service->localport];
|
service_quota = &state->service_quotas[service->localport];
|
||||||
up(&service_quota->quota_event);
|
complete(&service_quota->quota_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -432,9 +432,9 @@ remote_event_wait(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event)
|
||||||
event->armed = 1;
|
event->armed = 1;
|
||||||
dsb(sy);
|
dsb(sy);
|
||||||
if (!event->fired) {
|
if (!event->fired) {
|
||||||
if (down_interruptible(
|
if (wait_for_completion_interruptible(
|
||||||
(struct semaphore *)
|
(struct completion *)
|
||||||
((char *)state + event->event)) != 0) {
|
((char *)state + event->event))) {
|
||||||
event->armed = 0;
|
event->armed = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -451,7 +451,7 @@ static inline void
|
||||||
remote_event_signal_local(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event)
|
remote_event_signal_local(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event)
|
||||||
{
|
{
|
||||||
event->armed = 0;
|
event->armed = 0;
|
||||||
up((struct semaphore *)((char *)state + event->event));
|
complete((struct completion *)((char *)state + event->event));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -581,7 +581,7 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking)
|
||||||
|
|
||||||
/* If there is no free slot... */
|
/* If there is no free slot... */
|
||||||
|
|
||||||
if (down_trylock(&state->slot_available_event) != 0) {
|
if (!try_wait_for_completion(&state->slot_available_event)) {
|
||||||
/* ...wait for one. */
|
/* ...wait for one. */
|
||||||
|
|
||||||
VCHIQ_STATS_INC(state, slot_stalls);
|
VCHIQ_STATS_INC(state, slot_stalls);
|
||||||
|
@ -592,13 +592,13 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking)
|
||||||
remote_event_signal(&state->remote->trigger);
|
remote_event_signal(&state->remote->trigger);
|
||||||
|
|
||||||
if (!is_blocking ||
|
if (!is_blocking ||
|
||||||
(down_interruptible(
|
(wait_for_completion_interruptible(
|
||||||
&state->slot_available_event) != 0))
|
&state->slot_available_event)))
|
||||||
return NULL; /* No space available */
|
return NULL; /* No space available */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE)) {
|
if (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE)) {
|
||||||
up(&state->slot_available_event);
|
complete(&state->slot_available_event);
|
||||||
pr_warn("%s: invalid tx_pos: %d\n", __func__, tx_pos);
|
pr_warn("%s: invalid tx_pos: %d\n", __func__, tx_pos);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -678,7 +678,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length)
|
||||||
/* Signal the service that it
|
/* Signal the service that it
|
||||||
** has dropped below its quota
|
** has dropped below its quota
|
||||||
*/
|
*/
|
||||||
up(&service_quota->quota_event);
|
complete(&service_quota->quota_event);
|
||||||
else if (count == 0) {
|
else if (count == 0) {
|
||||||
vchiq_log_error(vchiq_core_log_level,
|
vchiq_log_error(vchiq_core_log_level,
|
||||||
"service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)",
|
"service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)",
|
||||||
|
@ -703,7 +703,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length)
|
||||||
/* Signal the service in case
|
/* Signal the service in case
|
||||||
** it has dropped below its
|
** it has dropped below its
|
||||||
** quota */
|
** quota */
|
||||||
up(&service_quota->quota_event);
|
complete(&service_quota->quota_event);
|
||||||
vchiq_log_trace(
|
vchiq_log_trace(
|
||||||
vchiq_core_log_level,
|
vchiq_core_log_level,
|
||||||
"%d: pfq:%d %x@%pK - slot_use->%d",
|
"%d: pfq:%d %x@%pK - slot_use->%d",
|
||||||
|
@ -744,7 +744,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length)
|
||||||
count - 1;
|
count - 1;
|
||||||
spin_unlock("a_spinlock);
|
spin_unlock("a_spinlock);
|
||||||
if (count == state->data_quota)
|
if (count == state->data_quota)
|
||||||
up(&state->data_quota_event);
|
complete(&state->data_quota_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -754,7 +754,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length)
|
||||||
mb();
|
mb();
|
||||||
|
|
||||||
state->slot_queue_available = slot_queue_available;
|
state->slot_queue_available = slot_queue_available;
|
||||||
up(&state->slot_available_event);
|
complete(&state->slot_available_event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,8 +862,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
|
||||||
spin_unlock("a_spinlock);
|
spin_unlock("a_spinlock);
|
||||||
mutex_unlock(&state->slot_mutex);
|
mutex_unlock(&state->slot_mutex);
|
||||||
|
|
||||||
if (down_interruptible(&state->data_quota_event)
|
if (wait_for_completion_interruptible(
|
||||||
!= 0)
|
&state->data_quota_event))
|
||||||
return VCHIQ_RETRY;
|
return VCHIQ_RETRY;
|
||||||
|
|
||||||
mutex_lock(&state->slot_mutex);
|
mutex_lock(&state->slot_mutex);
|
||||||
|
@ -873,7 +873,7 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
|
||||||
if ((tx_end_index == state->previous_data_index) ||
|
if ((tx_end_index == state->previous_data_index) ||
|
||||||
(state->data_use_count < state->data_quota)) {
|
(state->data_use_count < state->data_quota)) {
|
||||||
/* Pass the signal on to other waiters */
|
/* Pass the signal on to other waiters */
|
||||||
up(&state->data_quota_event);
|
complete(&state->data_quota_event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -893,8 +893,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service,
|
||||||
service_quota->slot_use_count);
|
service_quota->slot_use_count);
|
||||||
VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
|
VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
|
||||||
mutex_unlock(&state->slot_mutex);
|
mutex_unlock(&state->slot_mutex);
|
||||||
if (down_interruptible(&service_quota->quota_event)
|
if (wait_for_completion_interruptible(
|
||||||
!= 0)
|
&service_quota->quota_event))
|
||||||
return VCHIQ_RETRY;
|
return VCHIQ_RETRY;
|
||||||
if (service->closing)
|
if (service->closing)
|
||||||
return VCHIQ_ERROR;
|
return VCHIQ_ERROR;
|
||||||
|
@ -1251,7 +1251,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue,
|
||||||
waiter = bulk->userdata;
|
waiter = bulk->userdata;
|
||||||
if (waiter) {
|
if (waiter) {
|
||||||
waiter->actual = bulk->actual;
|
waiter->actual = bulk->actual;
|
||||||
up(&waiter->event);
|
complete(&waiter->event);
|
||||||
}
|
}
|
||||||
spin_unlock(&bulk_waiter_spinlock);
|
spin_unlock(&bulk_waiter_spinlock);
|
||||||
} else if (bulk->mode ==
|
} else if (bulk->mode ==
|
||||||
|
@ -1274,7 +1274,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue,
|
||||||
}
|
}
|
||||||
|
|
||||||
queue->remove++;
|
queue->remove++;
|
||||||
up(&service->bulk_remove_event);
|
complete(&service->bulk_remove_event);
|
||||||
}
|
}
|
||||||
if (!retry_poll)
|
if (!retry_poll)
|
||||||
status = VCHIQ_SUCCESS;
|
status = VCHIQ_SUCCESS;
|
||||||
|
@ -1667,7 +1667,7 @@ parse_rx_slots(VCHIQ_STATE_T *state)
|
||||||
service->remoteport = remoteport;
|
service->remoteport = remoteport;
|
||||||
vchiq_set_service_state(service,
|
vchiq_set_service_state(service,
|
||||||
VCHIQ_SRVSTATE_OPEN);
|
VCHIQ_SRVSTATE_OPEN);
|
||||||
up(&service->remove_event);
|
complete(&service->remove_event);
|
||||||
} else
|
} else
|
||||||
vchiq_log_error(vchiq_core_log_level,
|
vchiq_log_error(vchiq_core_log_level,
|
||||||
"OPENACK received in state %s",
|
"OPENACK received in state %s",
|
||||||
|
@ -1721,7 +1721,7 @@ parse_rx_slots(VCHIQ_STATE_T *state)
|
||||||
"%d: prs CONNECT@%pK", state->id, header);
|
"%d: prs CONNECT@%pK", state->id, header);
|
||||||
state->version_common = ((VCHIQ_SLOT_ZERO_T *)
|
state->version_common = ((VCHIQ_SLOT_ZERO_T *)
|
||||||
state->slot_data)->version;
|
state->slot_data)->version;
|
||||||
up(&state->connect);
|
complete(&state->connect);
|
||||||
break;
|
break;
|
||||||
case VCHIQ_MSG_BULK_RX:
|
case VCHIQ_MSG_BULK_RX:
|
||||||
case VCHIQ_MSG_BULK_TX:
|
case VCHIQ_MSG_BULK_TX:
|
||||||
|
@ -2055,7 +2055,7 @@ sync_func(void *v)
|
||||||
vchiq_set_service_state(service,
|
vchiq_set_service_state(service,
|
||||||
VCHIQ_SRVSTATE_OPENSYNC);
|
VCHIQ_SRVSTATE_OPENSYNC);
|
||||||
service->sync = 1;
|
service->sync = 1;
|
||||||
up(&service->remove_event);
|
complete(&service->remove_event);
|
||||||
}
|
}
|
||||||
release_message_sync(state, header);
|
release_message_sync(state, header);
|
||||||
break;
|
break;
|
||||||
|
@ -2194,33 +2194,33 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero)
|
||||||
initialize events and mutexes
|
initialize events and mutexes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sema_init(&state->connect, 0);
|
init_completion(&state->connect);
|
||||||
mutex_init(&state->mutex);
|
mutex_init(&state->mutex);
|
||||||
sema_init(&state->trigger_event, 0);
|
init_completion(&state->trigger_event);
|
||||||
sema_init(&state->recycle_event, 0);
|
init_completion(&state->recycle_event);
|
||||||
sema_init(&state->sync_trigger_event, 0);
|
init_completion(&state->sync_trigger_event);
|
||||||
sema_init(&state->sync_release_event, 0);
|
init_completion(&state->sync_release_event);
|
||||||
|
|
||||||
mutex_init(&state->slot_mutex);
|
mutex_init(&state->slot_mutex);
|
||||||
mutex_init(&state->recycle_mutex);
|
mutex_init(&state->recycle_mutex);
|
||||||
mutex_init(&state->sync_mutex);
|
mutex_init(&state->sync_mutex);
|
||||||
mutex_init(&state->bulk_transfer_mutex);
|
mutex_init(&state->bulk_transfer_mutex);
|
||||||
|
|
||||||
sema_init(&state->slot_available_event, 0);
|
init_completion(&state->slot_available_event);
|
||||||
sema_init(&state->slot_remove_event, 0);
|
init_completion(&state->slot_remove_event);
|
||||||
sema_init(&state->data_quota_event, 0);
|
init_completion(&state->data_quota_event);
|
||||||
|
|
||||||
state->slot_queue_available = 0;
|
state->slot_queue_available = 0;
|
||||||
|
|
||||||
for (i = 0; i < VCHIQ_MAX_SERVICES; i++) {
|
for (i = 0; i < VCHIQ_MAX_SERVICES; i++) {
|
||||||
VCHIQ_SERVICE_QUOTA_T *service_quota =
|
VCHIQ_SERVICE_QUOTA_T *service_quota =
|
||||||
&state->service_quotas[i];
|
&state->service_quotas[i];
|
||||||
sema_init(&service_quota->quota_event, 0);
|
init_completion(&service_quota->quota_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = local->slot_first; i <= local->slot_last; i++) {
|
for (i = local->slot_first; i <= local->slot_last; i++) {
|
||||||
local->slot_queue[state->slot_queue_available++] = i;
|
local->slot_queue[state->slot_queue_available++] = i;
|
||||||
up(&state->slot_available_event);
|
complete(&state->slot_available_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->default_slot_quota = state->slot_queue_available/2;
|
state->default_slot_quota = state->slot_queue_available/2;
|
||||||
|
@ -2354,8 +2354,8 @@ vchiq_add_service_internal(VCHIQ_STATE_T *state,
|
||||||
service->service_use_count = 0;
|
service->service_use_count = 0;
|
||||||
init_bulk_queue(&service->bulk_tx);
|
init_bulk_queue(&service->bulk_tx);
|
||||||
init_bulk_queue(&service->bulk_rx);
|
init_bulk_queue(&service->bulk_rx);
|
||||||
sema_init(&service->remove_event, 0);
|
init_completion(&service->remove_event);
|
||||||
sema_init(&service->bulk_remove_event, 0);
|
init_completion(&service->bulk_remove_event);
|
||||||
mutex_init(&service->bulk_mutex);
|
mutex_init(&service->bulk_mutex);
|
||||||
memset(&service->stats, 0, sizeof(service->stats));
|
memset(&service->stats, 0, sizeof(service->stats));
|
||||||
|
|
||||||
|
@ -2470,7 +2470,7 @@ vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id)
|
||||||
QMFLAGS_IS_BLOCKING);
|
QMFLAGS_IS_BLOCKING);
|
||||||
if (status == VCHIQ_SUCCESS) {
|
if (status == VCHIQ_SUCCESS) {
|
||||||
/* Wait for the ACK/NAK */
|
/* Wait for the ACK/NAK */
|
||||||
if (down_interruptible(&service->remove_event) != 0) {
|
if (wait_for_completion_interruptible(&service->remove_event)) {
|
||||||
status = VCHIQ_RETRY;
|
status = VCHIQ_RETRY;
|
||||||
vchiq_release_service_internal(service);
|
vchiq_release_service_internal(service);
|
||||||
} else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) &&
|
} else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) &&
|
||||||
|
@ -2622,7 +2622,7 @@ close_service_complete(VCHIQ_SERVICE_T *service, int failstate)
|
||||||
if (is_server)
|
if (is_server)
|
||||||
service->closing = 0;
|
service->closing = 0;
|
||||||
|
|
||||||
up(&service->remove_event);
|
complete(&service->remove_event);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
vchiq_set_service_state(service, failstate);
|
vchiq_set_service_state(service, failstate);
|
||||||
|
@ -2663,7 +2663,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd)
|
||||||
vchiq_set_service_state(service,
|
vchiq_set_service_state(service,
|
||||||
VCHIQ_SRVSTATE_LISTENING);
|
VCHIQ_SRVSTATE_LISTENING);
|
||||||
}
|
}
|
||||||
up(&service->remove_event);
|
complete(&service->remove_event);
|
||||||
} else
|
} else
|
||||||
vchiq_free_service_internal(service);
|
vchiq_free_service_internal(service);
|
||||||
break;
|
break;
|
||||||
|
@ -2672,7 +2672,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd)
|
||||||
/* The open was rejected - tell the user */
|
/* The open was rejected - tell the user */
|
||||||
vchiq_set_service_state(service,
|
vchiq_set_service_state(service,
|
||||||
VCHIQ_SRVSTATE_CLOSEWAIT);
|
VCHIQ_SRVSTATE_CLOSEWAIT);
|
||||||
up(&service->remove_event);
|
complete(&service->remove_event);
|
||||||
} else {
|
} else {
|
||||||
/* Shutdown mid-open - let the other side know */
|
/* Shutdown mid-open - let the other side know */
|
||||||
status = queue_message(state, service,
|
status = queue_message(state, service,
|
||||||
|
@ -2805,7 +2805,7 @@ vchiq_free_service_internal(VCHIQ_SERVICE_T *service)
|
||||||
|
|
||||||
vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE);
|
vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE);
|
||||||
|
|
||||||
up(&service->remove_event);
|
complete(&service->remove_event);
|
||||||
|
|
||||||
/* Release the initial lock */
|
/* Release the initial lock */
|
||||||
unlock_service(service);
|
unlock_service(service);
|
||||||
|
@ -2837,11 +2837,11 @@ vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) {
|
if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) {
|
||||||
if (down_interruptible(&state->connect) != 0)
|
if (wait_for_completion_interruptible(&state->connect))
|
||||||
return VCHIQ_RETRY;
|
return VCHIQ_RETRY;
|
||||||
|
|
||||||
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
|
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
|
||||||
up(&state->connect);
|
complete(&state->connect);
|
||||||
}
|
}
|
||||||
|
|
||||||
return VCHIQ_SUCCESS;
|
return VCHIQ_SUCCESS;
|
||||||
|
@ -2936,7 +2936,7 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (down_interruptible(&service->remove_event) != 0) {
|
if (wait_for_completion_interruptible(&service->remove_event)) {
|
||||||
status = VCHIQ_RETRY;
|
status = VCHIQ_RETRY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2997,7 +2997,7 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle)
|
||||||
request_poll(service->state, service, VCHIQ_POLL_REMOVE);
|
request_poll(service->state, service, VCHIQ_POLL_REMOVE);
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
if (down_interruptible(&service->remove_event) != 0) {
|
if (wait_for_completion_interruptible(&service->remove_event)) {
|
||||||
status = VCHIQ_RETRY;
|
status = VCHIQ_RETRY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3054,7 +3054,7 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
|
||||||
break;
|
break;
|
||||||
case VCHIQ_BULK_MODE_BLOCKING:
|
case VCHIQ_BULK_MODE_BLOCKING:
|
||||||
bulk_waiter = (struct bulk_waiter *)userdata;
|
bulk_waiter = (struct bulk_waiter *)userdata;
|
||||||
sema_init(&bulk_waiter->event, 0);
|
init_completion(&bulk_waiter->event);
|
||||||
bulk_waiter->actual = 0;
|
bulk_waiter->actual = 0;
|
||||||
bulk_waiter->bulk = NULL;
|
bulk_waiter->bulk = NULL;
|
||||||
break;
|
break;
|
||||||
|
@ -3080,8 +3080,8 @@ VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle,
|
||||||
VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);
|
VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);
|
||||||
do {
|
do {
|
||||||
mutex_unlock(&service->bulk_mutex);
|
mutex_unlock(&service->bulk_mutex);
|
||||||
if (down_interruptible(&service->bulk_remove_event)
|
if (wait_for_completion_interruptible(
|
||||||
!= 0) {
|
&service->bulk_remove_event)) {
|
||||||
status = VCHIQ_RETRY;
|
status = VCHIQ_RETRY;
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
@ -3157,7 +3157,7 @@ waiting:
|
||||||
|
|
||||||
if (bulk_waiter) {
|
if (bulk_waiter) {
|
||||||
bulk_waiter->bulk = bulk;
|
bulk_waiter->bulk = bulk;
|
||||||
if (down_interruptible(&bulk_waiter->event) != 0)
|
if (wait_for_completion_interruptible(&bulk_waiter->event))
|
||||||
status = VCHIQ_RETRY;
|
status = VCHIQ_RETRY;
|
||||||
else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
|
else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
|
||||||
status = VCHIQ_ERROR;
|
status = VCHIQ_ERROR;
|
||||||
|
@ -3326,7 +3326,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle,
|
||||||
service_quota->message_use_count)) {
|
service_quota->message_use_count)) {
|
||||||
/* Signal the service that it may have
|
/* Signal the service that it may have
|
||||||
** dropped below its quota */
|
** dropped below its quota */
|
||||||
up(&service_quota->quota_event);
|
complete(&service_quota->quota_event);
|
||||||
}
|
}
|
||||||
status = VCHIQ_SUCCESS;
|
status = VCHIQ_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -3347,7 +3347,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle,
|
||||||
service_quota->slot_use_count))
|
service_quota->slot_use_count))
|
||||||
/* Signal the service that it may have
|
/* Signal the service that it may have
|
||||||
** dropped below its quota */
|
** dropped below its quota */
|
||||||
up(&service_quota->quota_event);
|
complete(&service_quota->quota_event);
|
||||||
status = VCHIQ_SUCCESS;
|
status = VCHIQ_SUCCESS;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#define VCHIQ_CORE_H
|
#define VCHIQ_CORE_H
|
||||||
|
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/semaphore.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
|
|
||||||
#include "vchiq_cfg.h"
|
#include "vchiq_cfg.h"
|
||||||
|
@ -307,8 +307,8 @@ typedef struct vchiq_service_struct {
|
||||||
VCHIQ_BULK_QUEUE_T bulk_tx;
|
VCHIQ_BULK_QUEUE_T bulk_tx;
|
||||||
VCHIQ_BULK_QUEUE_T bulk_rx;
|
VCHIQ_BULK_QUEUE_T bulk_rx;
|
||||||
|
|
||||||
struct semaphore remove_event;
|
struct completion remove_event;
|
||||||
struct semaphore bulk_remove_event;
|
struct completion bulk_remove_event;
|
||||||
struct mutex bulk_mutex;
|
struct mutex bulk_mutex;
|
||||||
|
|
||||||
struct service_stats_struct {
|
struct service_stats_struct {
|
||||||
|
@ -337,7 +337,7 @@ typedef struct vchiq_service_quota_struct {
|
||||||
unsigned short slot_use_count;
|
unsigned short slot_use_count;
|
||||||
unsigned short message_quota;
|
unsigned short message_quota;
|
||||||
unsigned short message_use_count;
|
unsigned short message_use_count;
|
||||||
struct semaphore quota_event;
|
struct completion quota_event;
|
||||||
int previous_tx_index;
|
int previous_tx_index;
|
||||||
} VCHIQ_SERVICE_QUOTA_T;
|
} VCHIQ_SERVICE_QUOTA_T;
|
||||||
|
|
||||||
|
@ -410,7 +410,7 @@ struct vchiq_state_struct {
|
||||||
unsigned short default_message_quota;
|
unsigned short default_message_quota;
|
||||||
|
|
||||||
/* Event indicating connect message received */
|
/* Event indicating connect message received */
|
||||||
struct semaphore connect;
|
struct completion connect;
|
||||||
|
|
||||||
/* Mutex protecting services */
|
/* Mutex protecting services */
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
|
@ -426,16 +426,16 @@ struct vchiq_state_struct {
|
||||||
struct task_struct *sync_thread;
|
struct task_struct *sync_thread;
|
||||||
|
|
||||||
/* Local implementation of the trigger remote event */
|
/* Local implementation of the trigger remote event */
|
||||||
struct semaphore trigger_event;
|
struct completion trigger_event;
|
||||||
|
|
||||||
/* Local implementation of the recycle remote event */
|
/* Local implementation of the recycle remote event */
|
||||||
struct semaphore recycle_event;
|
struct completion recycle_event;
|
||||||
|
|
||||||
/* Local implementation of the sync trigger remote event */
|
/* Local implementation of the sync trigger remote event */
|
||||||
struct semaphore sync_trigger_event;
|
struct completion sync_trigger_event;
|
||||||
|
|
||||||
/* Local implementation of the sync release remote event */
|
/* Local implementation of the sync release remote event */
|
||||||
struct semaphore sync_release_event;
|
struct completion sync_release_event;
|
||||||
|
|
||||||
char *tx_data;
|
char *tx_data;
|
||||||
char *rx_data;
|
char *rx_data;
|
||||||
|
@ -481,12 +481,12 @@ struct vchiq_state_struct {
|
||||||
int unused_service;
|
int unused_service;
|
||||||
|
|
||||||
/* Signalled when a free slot becomes available. */
|
/* Signalled when a free slot becomes available. */
|
||||||
struct semaphore slot_available_event;
|
struct completion slot_available_event;
|
||||||
|
|
||||||
struct semaphore slot_remove_event;
|
struct completion slot_remove_event;
|
||||||
|
|
||||||
/* Signalled when a free data slot becomes available. */
|
/* Signalled when a free data slot becomes available. */
|
||||||
struct semaphore data_quota_event;
|
struct completion data_quota_event;
|
||||||
|
|
||||||
struct state_stats_struct {
|
struct state_stats_struct {
|
||||||
int slot_stalls;
|
int slot_stalls;
|
||||||
|
@ -505,7 +505,7 @@ struct vchiq_state_struct {
|
||||||
|
|
||||||
struct bulk_waiter {
|
struct bulk_waiter {
|
||||||
VCHIQ_BULK_T *bulk;
|
VCHIQ_BULK_T *bulk;
|
||||||
struct semaphore event;
|
struct completion event;
|
||||||
int actual;
|
int actual;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,8 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)
|
||||||
queue->write = 0;
|
queue->write = 0;
|
||||||
queue->initialized = 1;
|
queue->initialized = 1;
|
||||||
|
|
||||||
sema_init(&queue->pop, 0);
|
init_completion(&queue->pop);
|
||||||
sema_init(&queue->push, 0);
|
init_completion(&queue->push);
|
||||||
|
|
||||||
queue->storage = kcalloc(size, sizeof(VCHIQ_HEADER_T *), GFP_KERNEL);
|
queue->storage = kcalloc(size, sizeof(VCHIQ_HEADER_T *), GFP_KERNEL);
|
||||||
if (!queue->storage) {
|
if (!queue->storage) {
|
||||||
|
@ -80,7 +80,7 @@ void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (queue->write == queue->read + queue->size) {
|
while (queue->write == queue->read + queue->size) {
|
||||||
if (down_interruptible(&queue->pop) != 0)
|
if (wait_for_completion_interruptible(&queue->pop))
|
||||||
flush_signals(current);
|
flush_signals(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,17 +100,17 @@ void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
|
||||||
|
|
||||||
queue->write++;
|
queue->write++;
|
||||||
|
|
||||||
up(&queue->push);
|
complete(&queue->push);
|
||||||
}
|
}
|
||||||
|
|
||||||
VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)
|
VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)
|
||||||
{
|
{
|
||||||
while (queue->write == queue->read) {
|
while (queue->write == queue->read) {
|
||||||
if (down_interruptible(&queue->push) != 0)
|
if (wait_for_completion_interruptible(&queue->push))
|
||||||
flush_signals(current);
|
flush_signals(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
up(&queue->push); // We haven't removed anything from the queue.
|
complete(&queue->push); // We haven't removed anything from the queue.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read from queue->storage must be visible after read from
|
* Read from queue->storage must be visible after read from
|
||||||
|
@ -126,7 +126,7 @@ VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
|
||||||
VCHIQ_HEADER_T *header;
|
VCHIQ_HEADER_T *header;
|
||||||
|
|
||||||
while (queue->write == queue->read) {
|
while (queue->write == queue->read) {
|
||||||
if (down_interruptible(&queue->push) != 0)
|
if (wait_for_completion_interruptible(&queue->push))
|
||||||
flush_signals(current);
|
flush_signals(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
|
||||||
|
|
||||||
queue->read++;
|
queue->read++;
|
||||||
|
|
||||||
up(&queue->pop);
|
complete(&queue->pop);
|
||||||
|
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#define VCHIQ_UTIL_H
|
#define VCHIQ_UTIL_H
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/semaphore.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
|
@ -60,8 +60,8 @@ typedef struct {
|
||||||
int write;
|
int write;
|
||||||
int initialized;
|
int initialized;
|
||||||
|
|
||||||
struct semaphore pop;
|
struct completion pop;
|
||||||
struct semaphore push;
|
struct completion push;
|
||||||
|
|
||||||
VCHIQ_HEADER_T **storage;
|
VCHIQ_HEADER_T **storage;
|
||||||
} VCHIU_QUEUE_T;
|
} VCHIU_QUEUE_T;
|
||||||
|
|
Loading…
Add table
Reference in a new issue