rcu: Add automatically released rcu_read_lock variants
RCU_READ_LOCK_GUARD() takes the rcu_read_lock and then uses glib's
g_auto infrastructure (and thus whatever the compiler's hooks are) to
release it on all exits of the block.
WITH_RCU_READ_LOCK_GUARD() is similar but is used as a wrapper for the
lock, i.e.:
   WITH_RCU_READ_LOCK_GUARD() {
       stuff under lock
   }
Note the 'unused' attribute is needed to work around clang bug:
  https://bugs.llvm.org/show_bug.cgi?id=43482
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20191007143642.301445-2-dgilbert@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
			
			
This commit is contained in:
		| @@ -187,6 +187,22 @@ The following APIs must be used before RCU is used in a thread: | ||||
| Note that these APIs are relatively heavyweight, and should _not_ be | ||||
| nested. | ||||
|  | ||||
| Convenience macros | ||||
| ================== | ||||
|  | ||||
| Two macros are provided that automatically release the read lock at the | ||||
| end of the scope. | ||||
|  | ||||
|       RCU_READ_LOCK_GUARD() | ||||
|  | ||||
|          Takes the lock and will release it at the end of the block it's | ||||
|          used in. | ||||
|  | ||||
|       WITH_RCU_READ_LOCK_GUARD()  { code } | ||||
|  | ||||
|          Is used at the head of a block to protect the code within the block. | ||||
|  | ||||
| Note that 'goto'ing out of the guarded block will also drop the lock. | ||||
|  | ||||
| DIFFERENCES WITH LINUX | ||||
| ====================== | ||||
|   | ||||
| @@ -154,6 +154,31 @@ extern void call_rcu1(struct rcu_head *head, RCUCBFunc *func); | ||||
|       }),                                                                \ | ||||
|       (RCUCBFunc *)g_free); | ||||
|  | ||||
| typedef void RCUReadAuto; | ||||
| static inline RCUReadAuto *rcu_read_auto_lock(void) | ||||
| { | ||||
|     rcu_read_lock(); | ||||
|     /* Anything non-NULL causes the cleanup function to be called */ | ||||
|     return (void *)(uintptr_t)0x1; | ||||
| } | ||||
|  | ||||
| static inline void rcu_read_auto_unlock(RCUReadAuto *r) | ||||
| { | ||||
|     rcu_read_unlock(); | ||||
| } | ||||
|  | ||||
| G_DEFINE_AUTOPTR_CLEANUP_FUNC(RCUReadAuto, rcu_read_auto_unlock) | ||||
|  | ||||
| #define WITH_RCU_READ_LOCK_GUARD() \ | ||||
|     WITH_RCU_READ_LOCK_GUARD_(_rcu_read_auto##__COUNTER__) | ||||
|  | ||||
| #define WITH_RCU_READ_LOCK_GUARD_(var) \ | ||||
|     for (g_autoptr(RCUReadAuto) var = rcu_read_auto_lock(); \ | ||||
|         (var); rcu_read_auto_unlock(var), (var) = NULL) | ||||
|  | ||||
| #define RCU_READ_LOCK_GUARD() \ | ||||
|     g_autoptr(RCUReadAuto) _rcu_read_auto __attribute__((unused)) = rcu_read_auto_lock() | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user