Commit f27e47bc authored by Nicolas Saenz Julienne's avatar Nicolas Saenz Julienne Committed by Greg Kroah-Hartman

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: default avatarNicolas Saenz Julienne <nsaenzjulienne@suse.de>
Acked-by: default avatarStefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 51c07126
......@@ -44,7 +44,7 @@
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/bug.h>
#include <linux/semaphore.h>
#include <linux/completion.h>
#include <linux/list.h>
#include <linux/of.h>
#include <linux/platform_device.h>
......@@ -121,9 +121,9 @@ typedef struct user_service_struct {
int message_available_pos;
int msg_insert;
int msg_remove;
struct semaphore insert_event;
struct semaphore remove_event;
struct semaphore close_event;
struct completion insert_event;
struct completion remove_event;
struct completion close_event;
VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE];
} USER_SERVICE_T;
......@@ -138,8 +138,8 @@ struct vchiq_instance_struct {
VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS];
int completion_insert;
int completion_remove;
struct semaphore insert_event;
struct semaphore remove_event;
struct completion insert_event;
struct completion remove_event;
struct mutex completion_mutex;
int connected;
......@@ -562,7 +562,8 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
vchiq_log_trace(vchiq_arm_log_level,
"%s - completion queue full", __func__);
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,
"service_callback interrupted");
return VCHIQ_RETRY;
......@@ -600,7 +601,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason,
insert++;
instance->completion_insert = insert;
up(&instance->insert_event);
complete(&instance->insert_event);
return VCHIQ_SUCCESS;
}
......@@ -673,7 +674,8 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
}
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
if (down_interruptible(&user_service->remove_event)
if (wait_for_completion_interruptible(
&user_service->remove_event)
!= 0) {
vchiq_log_info(vchiq_arm_log_level,
"%s interrupted", __func__);
......@@ -705,7 +707,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header,
}
spin_unlock(&msg_queue_spinlock);
up(&user_service->insert_event);
complete(&user_service->insert_event);
header = NULL;
}
......@@ -745,7 +747,7 @@ static void close_delivered(USER_SERVICE_T *user_service)
unlock_service(user_service->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;
}
......@@ -867,7 +869,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (status == VCHIQ_SUCCESS) {
/* Wake the completion thread and ask it to exit */
instance->closing = 1;
up(&instance->insert_event);
complete(&instance->insert_event);
}
break;
......@@ -948,9 +950,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
instance->completion_remove - 1;
user_service->msg_insert = 0;
user_service->msg_remove = 0;
sema_init(&user_service->insert_event, 0);
sema_init(&user_service->remove_event, 0);
sema_init(&user_service->close_event, 0);
init_completion(&user_service->insert_event);
init_completion(&user_service->remove_event);
init_completion(&user_service->close_event);
if (args.is_open) {
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
CLOSE_DELIVERED ioctl, signalling close_event. */
if (user_service->close_pending &&
down_interruptible(&user_service->close_event))
wait_for_completion_interruptible(
&user_service->close_event))
status = VCHIQ_RETRY;
break;
}
......@@ -1182,7 +1185,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
mutex_unlock(&instance->completion_mutex);
rc = down_interruptible(&instance->insert_event);
rc = wait_for_completion_interruptible(
&instance->insert_event);
mutex_lock(&instance->completion_mutex);
if (rc != 0) {
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
......@@ -1310,7 +1314,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
if (ret != 0)
up(&instance->remove_event);
complete(&instance->remove_event);
mutex_unlock(&instance->completion_mutex);
DEBUG_TRACE(AWAIT_COMPLETION_LINE);
} break;
......@@ -1350,8 +1354,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
do {
spin_unlock(&msg_queue_spinlock);
DEBUG_TRACE(DEQUEUE_MESSAGE_LINE);
if (down_interruptible(
&user_service->insert_event) != 0) {
if (wait_for_completion_interruptible(
&user_service->insert_event)) {
vchiq_log_info(vchiq_arm_log_level,
"DEQUEUE_MESSAGE interrupted");
ret = -EINTR;
......@@ -1373,7 +1377,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
user_service->msg_remove++;
spin_unlock(&msg_queue_spinlock);
up(&user_service->remove_event);
complete(&user_service->remove_event);
if (header == NULL)
ret = -ENOTCONN;
else if (header->size <= args.bufsize) {
......@@ -1979,8 +1983,8 @@ vchiq_open(struct inode *inode, struct file *file)
vchiq_debugfs_add_instance(instance);
sema_init(&instance->insert_event, 0);
sema_init(&instance->remove_event, 0);
init_completion(&instance->insert_event);
init_completion(&instance->remove_event);
mutex_init(&instance->completion_mutex);
mutex_init(&instance->bulk_waiter_list_mutex);
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 */
instance->closing = 1;
up(&instance->insert_event);
complete(&instance->insert_event);
mutex_unlock(&instance->completion_mutex);
/* Wake the slot handler if the completion queue is full. */
up(&instance->remove_event);
complete(&instance->remove_event);
/* Mark all services for termination... */
i = 0;
......@@ -2047,7 +2051,7 @@ vchiq_release(struct inode *inode, struct file *file)
USER_SERVICE_T *user_service = service->base.userdata;
/* 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);
unlock_service(service);
......@@ -2059,7 +2063,7 @@ vchiq_release(struct inode *inode, struct file *file)
!= NULL) {
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);
......@@ -2103,7 +2107,7 @@ vchiq_release(struct inode *inode, struct file *file)
/* Wake any blocked user-thread */
if (instance->use_close_delivered)
up(&user_service->close_event);
complete(&user_service->close_event);
unlock_service(service);
}
instance->completion_remove++;
......
......@@ -35,7 +35,7 @@
#define VCHIQ_CORE_H
#include <linux/mutex.h>
#include <linux/semaphore.h>
#include <linux/completion.h>
#include <linux/kthread.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_rx;
struct semaphore remove_event;
struct semaphore bulk_remove_event;
struct completion remove_event;
struct completion bulk_remove_event;
struct mutex bulk_mutex;
struct service_stats_struct {
......@@ -337,7 +337,7 @@ typedef struct vchiq_service_quota_struct {
unsigned short slot_use_count;
unsigned short message_quota;
unsigned short message_use_count;
struct semaphore quota_event;
struct completion quota_event;
int previous_tx_index;
} VCHIQ_SERVICE_QUOTA_T;
......@@ -410,7 +410,7 @@ struct vchiq_state_struct {
unsigned short default_message_quota;
/* Event indicating connect message received */
struct semaphore connect;
struct completion connect;
/* Mutex protecting services */
struct mutex mutex;
......@@ -426,16 +426,16 @@ struct vchiq_state_struct {
struct task_struct *sync_thread;
/* Local implementation of the trigger remote event */
struct semaphore trigger_event;
struct completion trigger_event;
/* Local implementation of the recycle remote event */
struct semaphore recycle_event;
struct completion recycle_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 */
struct semaphore sync_release_event;
struct completion sync_release_event;
char *tx_data;
char *rx_data;
......@@ -481,12 +481,12 @@ struct vchiq_state_struct {
int unused_service;
/* 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. */
struct semaphore data_quota_event;
struct completion data_quota_event;
struct state_stats_struct {
int slot_stalls;
......@@ -505,7 +505,7 @@ struct vchiq_state_struct {
struct bulk_waiter {
VCHIQ_BULK_T *bulk;
struct semaphore event;
struct completion event;
int actual;
};
......
......@@ -48,8 +48,8 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size)
queue->write = 0;
queue->initialized = 1;
sema_init(&queue->pop, 0);
sema_init(&queue->push, 0);
init_completion(&queue->pop);
init_completion(&queue->push);
queue->storage = kcalloc(size, sizeof(VCHIQ_HEADER_T *), GFP_KERNEL);
if (!queue->storage) {
......@@ -80,7 +80,7 @@ void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
return;
while (queue->write == queue->read + queue->size) {
if (down_interruptible(&queue->pop) != 0)
if (wait_for_completion_interruptible(&queue->pop))
flush_signals(current);
}
......@@ -100,17 +100,17 @@ void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header)
queue->write++;
up(&queue->push);
complete(&queue->push);
}
VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue)
{
while (queue->write == queue->read) {
if (down_interruptible(&queue->push) != 0)
if (wait_for_completion_interruptible(&queue->push))
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
......@@ -126,7 +126,7 @@ VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
VCHIQ_HEADER_T *header;
while (queue->write == queue->read) {
if (down_interruptible(&queue->push) != 0)
if (wait_for_completion_interruptible(&queue->push))
flush_signals(current);
}
......@@ -146,7 +146,7 @@ VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue)
queue->read++;
up(&queue->pop);
complete(&queue->pop);
return header;
}
......@@ -35,7 +35,7 @@
#define VCHIQ_UTIL_H
#include <linux/types.h>
#include <linux/semaphore.h>
#include <linux/completion.h>
#include <linux/mutex.h>
#include <linux/bitops.h>
#include <linux/kthread.h>
......@@ -60,8 +60,8 @@ typedef struct {
int write;
int initialized;
struct semaphore pop;
struct semaphore push;
struct completion pop;
struct completion push;
VCHIQ_HEADER_T **storage;
} VCHIU_QUEUE_T;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment