Skip to contentSkip to conversation

linux/compiler.h: Add __must_hold macro for functions called with a lock held

PATCH In review Josh Triplett 4 participants 5 messages Oct 8, 2012 – Oct 13, 2012 Sparse checker

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 linux/compiler.h: Add __must_hold macro for functions called with a lock held

linux/compiler.h has macros to denote functions that acquire or release locks, but not to denote functions called with a lock held that return with the lock still held. Add a __must_hold macro to cover that case.

---
 include/linux/compiler.h |    2 ++
 1 file changed, 2 insertions(+)
include/linux/compiler.h +2 -0
index f430e41..b121554 100644
@@ -10,6 +10,7 @@
 # define __force	__attribute__((force))
 # define __nocast	__attribute__((nocast))
 # define __iomem	__attribute__((noderef, address_space(2)))
+# define __must_hold(x)	__attribute__((context(x,1,1)))
 # define __acquires(x)	__attribute__((context(x,0,1)))
 # define __releases(x)	__attribute__((context(x,1,0)))
 # define __acquire(x)	__context__(x,1)
@@ -33,6 +34,7 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 # define __chk_user_ptr(x) (void)0
 # define __chk_io_ptr(x) (void)0
 # define __builtin_warning(x, y...) (1)
+# define __must_hold(x)
 # define __acquires(x)
 # define __releases(x)
 # define __acquire(x) (void)0
Signature · 1 line
1.7.10.4
#1 lore raw
Quoted 3 lines · On Sun, 7 Oct 2012 19:06:10 -0700 Josh Triplett <[email protected]> wrote:

linux/compiler.h has macros to denote functions that acquire or release locks, but not to denote functions called with a lock held that return with the lock still held. Add a __must_hold macro to cover that case.

hum. How does this work? Any code examples and sample sparse output? Does it apply to all lock types, etc?

IOW, where is all this stuff documented?

#2 lore raw
Quoted 9 lines · Andrew Morton
Quoted 3 lines · On Sun, 7 Oct 2012 19:06:10 -0700 Josh Triplett <[email protected]> wrote:

linux/compiler.h has macros to denote functions that acquire or release locks, but not to denote functions called with a lock held that return with the lock still held. Add a __must_hold macro to cover that case.

hum. How does this work? Any code examples and sample sparse output? Does it apply to all lock types, etc?

I accidentally found a bug in sparse where sparse should have been complaining about the locking in the aoe driver's aoenet.c:tx function, which enters with the txlock spinlock held and releases and reacquires it inside a loop.

When I modified the loop contents between lock release and acquisition in a patch that I'm preparing now, sparse began complaining about context imbalance. (Before the modifications to the tx function, sparse was exhibiting a bug by *not* complaining.) Here's the complaint:

CHECK drivers/block/aoe/aoenet.c
/build/ecashin/git/linux/arch/x86/include/asm/spinlock.h:81:9: warning: context imbalance in 'tx' - unexpected unlock
CC [M] drivers/block/aoe/aoenet.o

... although I used a smaller file to hone in on the issue when discussing it on the linux-sparse mailing list:

http://thread.gmane.org/gmane.comp.parsers.sparse/3091

Josh Triplett suggested I add an annotation telling sparse that the function enters and exits with the lock held, but after reading the sparse man page, where the context feature is described, it looked like that meant specifying a 1 for both
parameters: __attribute__((context(x,1,1))), but there was no macro for that.

The new patch from Josh Triplett adds the macro that I can use to keep sparse informed about the locking requirements for the tx function.

Quoted 1 line

IOW, where is all this stuff documented?

It wasn't real easy to find it, but it's basically something you can infer from reading include/linux/compiler.h and the sparse.1 man page that's included with sparse. I think a brief mention in Documentation/sparse.txt of the relationship between the sparse "context" feature and the locking annotations like __acquires and __must_hold would be a nice addition.

I can take a stab at it if folks agree.

Signature · 2 lines
  Ed Cashin
  [email protected]
#3 lore raw
In reply to Andrew Morton
Quoted 9 lines · Andrew Morton
Quoted 3 lines · On Sun, 7 Oct 2012 19:06:10 -0700 Josh Triplett <[email protected]> wrote:

linux/compiler.h has macros to denote functions that acquire or release locks, but not to denote functions called with a lock held that return with the lock still held. Add a __must_hold macro to cover that case.

hum. How does this work? Any code examples and sample sparse output? Does it apply to all lock types, etc?

It applies to all the same lock types that __acquires and __releases apply to: currently everything since Sparse doesn't actually do anything with the parameter, just the context value.

Various code examples already exist in the kernel tree for __acquires and __releases, and the mailing list contains many reports of the Sparse context warnings.

Just as __acquires and __release annotate functions that return with a lock acquired and get called with a lock that they drop (respectively), __must_hold annotates a function called with a lock acquired that return with that lock still acquired.

Quoted 1 line

IOW, where is all this stuff documented?

The Sparse manpage documents the context bits reasonably well. Other than that, nowhere that I know of other than the Sparse testsuite and the source trees of projects like Linux that use Sparse.

- Josh Triplett

#4 lore raw
Quoted 24 lines · Josh Triplett
Quoted 9 lines · Andrew Morton
Quoted 3 lines · On Sun, 7 Oct 2012 19:06:10 -0700 Josh Triplett <[email protected]> wrote:

linux/compiler.h has macros to denote functions that acquire or release locks, but not to denote functions called with a lock held that return with the lock still held. Add a __must_hold macro to cover that case.

hum. How does this work? Any code examples and sample sparse output? Does it apply to all lock types, etc?

It applies to all the same lock types that __acquires and __releases apply to: currently everything since Sparse doesn't actually do anything with the parameter, just the context value.

Various code examples already exist in the kernel tree for __acquires and __releases, and the mailing list contains many reports of the Sparse context warnings.

Just as __acquires and __release annotate functions that return with a lock acquired and get called with a lock that they drop (respectively), __must_hold annotates a function called with a lock acquired that return with that lock still acquired.

Quoted 5 lines
Quoted 1 line

IOW, where is all this stuff documented?

The Sparse manpage documents the context bits reasonably well. Other than that, nowhere that I know of other than the Sparse testsuite and the source trees of projects like Linux that use Sparse.

The kernel specific macros should be documented in:

Documentation/sparse.txt

For now only __bitwise is documentd, but when we introduce new sparse annotation macros in the kernel the documentation should be mandatory.

Sam