diff mbox

[v2,2/8] IB/core: Replace semaphore sm_sem with completion

Message ID 1477396919-27669-3-git-send-email-binoy.jayan@linaro.org
State New
Headers show

Commit Message

Binoy Jayan Oct. 25, 2016, 12:01 p.m. UTC
The semaphore 'sm_sem' is used as completion, so convert it to
struct completion. Semaphores are going away in the future. The initial
status of the completion variable is marked as completed by a call to
the function 'complete' immediately following the initialization.

Signed-off-by: Binoy Jayan <binoy.jayan@linaro.org>

---
 drivers/infiniband/core/user_mad.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

Comments

Jack Wang Oct. 25, 2016, 12:43 p.m. UTC | #1
Hi Binoy,

snip
>

>         port->ib_dev   = device;

>         port->port_num = port_num;

> -       sema_init(&port->sm_sem, 1);

> +       init_completion(&port->sm_comp);

> +       complete(&port->sm_comp);


Why complete here?

>         mutex_init(&port->file_mutex);

>         INIT_LIST_HEAD(&port->file_list);

>

> --

KR,
Jinpu
Binoy Jayan Oct. 25, 2016, 3:08 p.m. UTC | #2
On 25 October 2016 at 18:13, Jack Wang <xjtuwjp@gmail.com> wrote:
> Hi Binoy,

>

> snip

>>

>>         port->ib_dev   = device;

>>         port->port_num = port_num;

>> -       sema_init(&port->sm_sem, 1);

>> +       init_completion(&port->sm_comp);

>> +       complete(&port->sm_comp);

>

> Why complete here?

>

>>         mutex_init(&port->file_mutex);

>>         INIT_LIST_HEAD(&port->file_list);

>>

>> --

> KR,

> Jinpu



Hi Jack,

ib_umad_sm_open() calls wait_for_completion_interruptible() which comes before
ib_umad_sm_close() that calls complete(). In the initial open() there
will not be
anybody to signal the completion, so the complete is called to mark
the initial state.
I am not sure if this is the right way to do it, though.

-Binoy
Jack Wang Oct. 25, 2016, 3:48 p.m. UTC | #3
Hi Binoy,
2016-10-25 17:08 GMT+02:00 Binoy Jayan <binoy.jayan@linaro.org>:
> On 25 October 2016 at 18:13, Jack Wang <xjtuwjp@gmail.com> wrote:

>> Hi Binoy,

>>

>> snip

>>>

>>>         port->ib_dev   = device;

>>>         port->port_num = port_num;

>>> -       sema_init(&port->sm_sem, 1);

>>> +       init_completion(&port->sm_comp);

>>> +       complete(&port->sm_comp);

>>

>> Why complete here?

>>

>>>         mutex_init(&port->file_mutex);

>>>         INIT_LIST_HEAD(&port->file_list);

>>>

>>> --

>> KR,

>> Jinpu

>

>

> Hi Jack,

>

> ib_umad_sm_open() calls wait_for_completion_interruptible() which comes before

> ib_umad_sm_close() that calls complete(). In the initial open() there

> will not be

> anybody to signal the completion, so the complete is called to mark

> the initial state.

> I am not sure if this is the right way to do it, though.

>

> -Binoy


From Documentation/scheduler/completion.txt ,
"
117 This is not implying any temporal order on wait_for_completion() and the
118 call to complete() - if the call to complete() happened before the call
119 to wait_for_completion() then the waiting side simply will continue
120 immediately as all dependencies are satisfied if not it will block until
121 completion is signaled by complete().
"
In this case here, if sm_open/sm_close are paired, it should work.

KR
Jack
Jason Gunthorpe Oct. 25, 2016, 3:48 p.m. UTC | #4
On Tue, Oct 25, 2016 at 08:38:21PM +0530, Binoy Jayan wrote:
> On 25 October 2016 at 18:13, Jack Wang <xjtuwjp@gmail.com> wrote:

> > Hi Binoy,

> >

> > snip

> >>

> >>         port->ib_dev   = device;

> >>         port->port_num = port_num;

> >> -       sema_init(&port->sm_sem, 1);

> >> +       init_completion(&port->sm_comp);

> >> +       complete(&port->sm_comp);

> >

> > Why complete here?

> >

> >>         mutex_init(&port->file_mutex);

> >>         INIT_LIST_HEAD(&port->file_list);

> >>

> > KR,

> > Jinpu

> 

> 

> Hi Jack,

> 

> ib_umad_sm_open() calls wait_for_completion_interruptible() which

> comes before ib_umad_sm_close() that calls complete(). In the

> initial open() there will not be anybody to signal the completion,

> so the complete is called to mark the initial state.  I am not sure

> if this is the right way to do it, though.


Using a completion to model exclusive ownership seems convoluted to
me - is that a thing now? What about an atomic?

open:

while (true) {
   wait_event_interruptible(priv->queue,test_bit(CLAIMED_BIT, &priv->flags));
   if (!test_and_set_bit(CLAIMED_BIT, &priv->flags))
        break;
}

close():

   clear_bit(CLAIMED_BIT, &priv->flags)
   wake_up(&priv->queue);

??

Jason
Arnd Bergmann Oct. 25, 2016, 8:15 p.m. UTC | #5
On Tuesday, October 25, 2016 9:48:22 AM CEST Jason Gunthorpe wrote:
> 

> Using a completion to model exclusive ownership seems convoluted to

> me - is that a thing now? What about an atomic?


I also totally missed how this is used. I initially mentioned to Binoy
that almost all semaphores can either be converted to a mutex or a
completion unless they rely on the counting behavior of the semaphore.

This driver clearly falls into another category and none of the above
apply here.

> open:

> 

> while (true) {

>    wait_event_interruptible(priv->queue,test_bit(CLAIMED_BIT, &priv->flags));

>    if (!test_and_set_bit(CLAIMED_BIT, &priv->flags))

>         break;

> }


I'd fold the test_and_set_bit() into the wait_event() and get rid of the
loop here, otherwise this looks nice.

I'm generally a bit suspicious of open() functions that try to
protect you from having multiple file descriptors open, as dup()
or fork() will also result in extra file descriptors, but this
use here seems harmless, as the device itself only supports
open() and close() and the only thing it does is to keep track
of whether it is open or not.

It's also interesting that the ib_modify_port() function also
keeps track of the a flag that is set in open() and cleared
in close(), so in principle we should be able to unify this
with the semaphore, but the wait_event() approach is certainly
much simpler.

	Arnd
diff mbox

Patch

diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 415a318..df070cc 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -47,6 +47,7 @@ 
 #include <linux/kref.h>
 #include <linux/compat.h>
 #include <linux/sched.h>
+#include <linux/completion.h>
 #include <linux/semaphore.h>
 #include <linux/slab.h>
 
@@ -87,7 +88,7 @@  struct ib_umad_port {
 
 	struct cdev           sm_cdev;
 	struct device	      *sm_dev;
-	struct semaphore       sm_sem;
+	struct completion      sm_comp;
 
 	struct mutex	       file_mutex;
 	struct list_head       file_list;
@@ -1030,12 +1031,12 @@  static int ib_umad_sm_open(struct inode *inode, struct file *filp)
 	port = container_of(inode->i_cdev, struct ib_umad_port, sm_cdev);
 
 	if (filp->f_flags & O_NONBLOCK) {
-		if (down_trylock(&port->sm_sem)) {
+		if (!try_wait_for_completion(&port->sm_comp)) {
 			ret = -EAGAIN;
 			goto fail;
 		}
 	} else {
-		if (down_interruptible(&port->sm_sem)) {
+		if (wait_for_completion_interruptible(&port->sm_comp)) {
 			ret = -ERESTARTSYS;
 			goto fail;
 		}
@@ -1060,7 +1061,7 @@  static int ib_umad_sm_open(struct inode *inode, struct file *filp)
 	ib_modify_port(port->ib_dev, port->port_num, 0, &props);
 
 err_up_sem:
-	up(&port->sm_sem);
+	complete(&port->sm_comp);
 
 fail:
 	return ret;
@@ -1079,7 +1080,7 @@  static int ib_umad_sm_close(struct inode *inode, struct file *filp)
 		ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
 	mutex_unlock(&port->file_mutex);
 
-	up(&port->sm_sem);
+	complete(&port->sm_comp);
 
 	kobject_put(&port->umad_dev->kobj);
 
@@ -1177,7 +1178,8 @@  static int ib_umad_init_port(struct ib_device *device, int port_num,
 
 	port->ib_dev   = device;
 	port->port_num = port_num;
-	sema_init(&port->sm_sem, 1);
+	init_completion(&port->sm_comp);
+	complete(&port->sm_comp);
 	mutex_init(&port->file_mutex);
 	INIT_LIST_HEAD(&port->file_list);