lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <3160105.1740674652@warthog.procyon.org.uk>
Date: Thu, 27 Feb 2025 16:44:12 +0000
From: David Howells <dhowells@...hat.com>
To: "H. Peter Anvin" <hpa@...or.com>
Cc: dhowells@...hat.com, linux-kernel@...r.kernel.org, pinskia@...il.com,
    Neal Gompa <neal@...pa.dev>
Subject: Convert the kernel to C++: Lock-holding class

Hi Peter,

I played with the code a bit and implemented a generic template class to hold
a lock:

	template<typename LOCK>
	struct Lock {
		LOCK &m;
		bool is_locked;
		Lock(LOCK &mutex) : m(mutex) {
			m.lock();
			is_locked = true;
		}
		~Lock() {
			if (is_locked)
				m.unlock();
		}
		void drop() {
			if (is_locked)
				m.unlock();
			is_locked = false;
		}
		void reget() {
			m.lock();
			is_locked = true;
		}
		operator bool() {
			return is_locked;
		}
	};

used something like with the Mutex, Semaphore and Inode classes below:

	int bar(Inode *inode, int x)
	{
		Lock m_lock = inode->m;

		for (int i = 0; i < 10; i++) {
			Lock m_sem(inode->s);
			do_something(inode);
			m_lock.drop();
			do_something_else(inode);
			m_lock.reget();
		}
	}

It seems that the storage for objects of this lock-holding class entirely
optimise away under reasonable conditions.  The compiler can keep track of
both the lock pointer/ref *and* the is_locked member without having to
actually store them - even when exception handling is thrown into the mix.

A further thing I've noticed is that zero-size classes can be passed in the
argument list without the consumption of register/stack space.  I wonder if it
might be possible to use an argument to indicate the possession of a lock?
E.g.:

	class Have_lock {};
	class Pass_lock {};
	template<typename LOCK>
	struct Lock {
		...
		operator Have_lock() {
			__builtin_compile_time_assert(is_locked);
			BUG_ON(!is_locked);
			return Have_lock();
		}
		operator Pass_lock() {
			__builtin_compile_time_assert(is_locked);
			BUG_ON(!is_locked);
			is_locked = false;
			return Have_lock();
		}
	};

	int do_something(Inode *i, Have_lock l);
	int do_something_and_unlock(Inode *i, Pass_lock l);

David
---

Silly, non-functional implementation of a mutex and a semaphore class so that
I could see it trivially in the .o file:

	struct Mutex {
		int counter;
		void lock() {
			__atomic_fetch_sub(&counter, 1, __ATOMIC_RELEASE);
		}
		void unlock() {
			__atomic_fetch_add(&counter, 1, __ATOMIC_ACQUIRE);
		}
	};

	struct Semaphore {
		int counter;
		void lock() {
			__atomic_fetch_sub(&counter, 1, __ATOMIC_RELEASE);
		}
		void unlock() {
			__atomic_fetch_add(&counter, 1, __ATOMIC_ACQUIRE);
		}
	};

	struct Inode {
		int ref;
		Mutex m;
		Semaphore s;
	};


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ