On Mon, Jun 12, 2023 at 09:27:09AM -0700, Linus Torvalds wrote: > The thing does not not go out of scope when the loop *iterates*. > > It only goes out of scope when the loop *ends*. > Or have I mis-understood something completely? I tried this before I used it and variables inside a for() loop have a scope of a single iteration. $ gcc -O2 -o guard guard.c && ./guard spin_lock ponies __raw_spin_lock_irqsave can haz raw_spin_unlock_irqrestore mutex_lock mutex_unlock mutex_lock mutex_unlock mutex_lock mutex_unlock mutex_lock mutex_unlock mutex_lock mutex_unlock spin_unlock --- #include <stdio.h> #include <stdbool.h> typedef struct { } raw_spinlock_t; typedef struct { } spinlock_t; typedef struct { } mutex_t; void raw_spin_lock(raw_spinlock_t *) { printf("%s\n", __FUNCTION__); } void raw_spin_unlock(raw_spinlock_t *) { printf("%s\n", __FUNCTION__); } unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock) { printf("%s\n", __FUNCTION__); return 0; } #define raw_spin_lock_irqsave(lock, flags) \ flags = __raw_spin_lock_irqsave(lock) void raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags) { printf("%s\n", __FUNCTION__); } void spin_lock(spinlock_t *) { printf("%s\n", __FUNCTION__); } void spin_unlock(spinlock_t *) { printf("%s\n", __FUNCTION__); } void mutex_lock(mutex_t *) { printf("%s\n", __FUNCTION__); } void mutex_unlock(mutex_t *) { printf("%s\n", __FUNCTION__); } #define DEFINE_LOCK_GUARD(_type, _Type, _Lock, _Unlock, ...) \ typedef struct { \ _Type *lock; \ __VA_ARGS__ \ } lock_guard_##_type##_t; \ \ static inline void lock_guard_##_type##_cleanup(void *_g) \ { \ lock_guard_##_type##_t *_G = _g; \ if (_G->lock) \ _Unlock; \ } \ \ static inline lock_guard_##_type##_t lock_guard_##_type##_init(_Type *lock) \ { \ lock_guard_##_type##_t _g = { .lock = lock }, *_G = &_g; \ _Lock; \ return _g; \ } DEFINE_LOCK_GUARD(raw, raw_spinlock_t, raw_spin_lock(_G->lock), raw_spin_unlock(_G->lock) ) DEFINE_LOCK_GUARD(spin, spinlock_t, spin_lock(_G->lock), spin_unlock(_G->lock) ) DEFINE_LOCK_GUARD(mutex, mutex_t, mutex_lock(_G->lock), mutex_unlock(_G->lock) ) DEFINE_LOCK_GUARD(raw_irqsave, raw_spinlock_t, raw_spin_lock_irqsave(_G->lock, _G->flags), raw_spin_unlock_irqrestore(_G->lock, _G->flags), unsigned long flags; ) #define __cleanup(func) __attribute__((__cleanup__(func))) #define lock_guard(_type, _name, _ptr) \ lock_guard_##_type##_t _name __cleanup(lock_guard_##_type##_cleanup) = \ lock_guard_##_type##_init(_ptr) #define lock_scope(_type, _ptr) \ for (struct { lock_guard_##_type##_t guard ; bool done; } _scope __cleanup(lock_guard_##_type##_cleanup) = \ { .guard = lock_guard_##_type##_init(_ptr), .done = false }; \ !_scope.done; _scope.done = true) raw_spinlock_t raw_lock; spinlock_t lock; mutex_t mutex; void main(void) { lock_guard(spin, guard, &lock); printf("ponies\n"); lock_scope(raw_irqsave, &raw_lock) { printf("can haz\n"); } for (int i=0; i<5; i++) { lock_guard(mutex, foo, &mutex); continue; } }