Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2263baba authored by Pete Fotheringham's avatar Pete Fotheringham
Browse files

Merge branch 'lineage-18.1' into '3866-use-los18-kernel'

3866 Use Los18 Kernel

See merge request !3
parents 735f50a9 00e2feed
Loading
Loading
Loading
Loading
+168 −0
Original line number Diff line number Diff line
===================================
refcount_t API compared to atomic_t
===================================

.. contents:: :local:

Introduction
============

The goal of refcount_t API is to provide a minimal API for implementing
an object's reference counters. While a generic architecture-independent
implementation from lib/refcount.c uses atomic operations underneath,
there are a number of differences between some of the ``refcount_*()`` and
``atomic_*()`` functions with regards to the memory ordering guarantees.
This document outlines the differences and provides respective examples
in order to help maintainers validate their code against the change in
these memory ordering guarantees.

The terms used through this document try to follow the formal LKMM defined in
tools/memory-model/Documentation/explanation.txt.

memory-barriers.txt and atomic_t.txt provide more background to the
memory ordering in general and for atomic operations specifically.

Relevant types of memory ordering
=================================

.. note:: The following section only covers some of the memory
   ordering types that are relevant for the atomics and reference
   counters and used through this document. For a much broader picture
   please consult memory-barriers.txt document.

In the absence of any memory ordering guarantees (i.e. fully unordered)
atomics & refcounters only provide atomicity and
program order (po) relation (on the same CPU). It guarantees that
each ``atomic_*()`` and ``refcount_*()`` operation is atomic and instructions
are executed in program order on a single CPU.
This is implemented using :c:func:`READ_ONCE`/:c:func:`WRITE_ONCE` and
compare-and-swap primitives.

A strong (full) memory ordering guarantees that all prior loads and
stores (all po-earlier instructions) on the same CPU are completed
before any po-later instruction is executed on the same CPU.
It also guarantees that all po-earlier stores on the same CPU
and all propagated stores from other CPUs must propagate to all
other CPUs before any po-later instruction is executed on the original
CPU (A-cumulative property). This is implemented using :c:func:`smp_mb`.

A RELEASE memory ordering guarantees that all prior loads and
stores (all po-earlier instructions) on the same CPU are completed
before the operation. It also guarantees that all po-earlier
stores on the same CPU and all propagated stores from other CPUs
must propagate to all other CPUs before the release operation
(A-cumulative property). This is implemented using
:c:func:`smp_store_release`.

An ACQUIRE memory ordering guarantees that all post loads and
stores (all po-later instructions) on the same CPU are
completed after the acquire operation. It also guarantees that all
po-later stores on the same CPU must propagate to all other CPUs
after the acquire operation executes. This is implemented using
:c:func:`smp_acquire__after_ctrl_dep`.

A control dependency (on success) for refcounters guarantees that
if a reference for an object was successfully obtained (reference
counter increment or addition happened, function returned true),
then further stores are ordered against this operation.
Control dependency on stores are not implemented using any explicit
barriers, but rely on CPU not to speculate on stores. This is only
a single CPU relation and provides no guarantees for other CPUs.


Comparison of functions
=======================

case 1) - non-"Read/Modify/Write" (RMW) ops
-------------------------------------------

Function changes:

 * :c:func:`atomic_set` --> :c:func:`refcount_set`
 * :c:func:`atomic_read` --> :c:func:`refcount_read`

Memory ordering guarantee changes:

 * none (both fully unordered)


case 2) - increment-based ops that return no value
--------------------------------------------------

Function changes:

 * :c:func:`atomic_inc` --> :c:func:`refcount_inc`
 * :c:func:`atomic_add` --> :c:func:`refcount_add`

Memory ordering guarantee changes:

 * none (both fully unordered)

case 3) - decrement-based RMW ops that return no value
------------------------------------------------------

Function changes:

 * :c:func:`atomic_dec` --> :c:func:`refcount_dec`

Memory ordering guarantee changes:

 * fully unordered --> RELEASE ordering


case 4) - increment-based RMW ops that return a value
-----------------------------------------------------

Function changes:

 * :c:func:`atomic_inc_not_zero` --> :c:func:`refcount_inc_not_zero`
 * no atomic counterpart --> :c:func:`refcount_add_not_zero`

Memory ordering guarantees changes:

 * fully ordered --> control dependency on success for stores

.. note:: We really assume here that necessary ordering is provided as a
   result of obtaining pointer to the object!


case 5) - generic dec/sub decrement-based RMW ops that return a value
---------------------------------------------------------------------

Function changes:

 * :c:func:`atomic_dec_and_test` --> :c:func:`refcount_dec_and_test`
 * :c:func:`atomic_sub_and_test` --> :c:func:`refcount_sub_and_test`

Memory ordering guarantees changes:

 * fully ordered --> RELEASE ordering + ACQUIRE ordering on success


case 6) other decrement-based RMW ops that return a value
---------------------------------------------------------

Function changes:

 * no atomic counterpart --> :c:func:`refcount_dec_if_one`
 * ``atomic_add_unless(&var, -1, 1)`` --> ``refcount_dec_not_one(&var)``

Memory ordering guarantees changes:

 * fully ordered --> RELEASE ordering + control dependency

.. note:: :c:func:`atomic_add_unless` only provides full order on success.


case 7) - lock-based RMW
------------------------

Function changes:

 * :c:func:`atomic_dec_and_lock` --> :c:func:`refcount_dec_and_lock`
 * :c:func:`atomic_dec_and_mutex_lock` --> :c:func:`refcount_dec_and_mutex_lock`

Memory ordering guarantees changes:

 * fully ordered --> RELEASE ordering + control dependency + hold
   :c:func:`spin_lock` on success
+10 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ Required properties:
- qcom,has-48mhz-xo: boolean flag to determine the usage of 24MHz XO from RF
- qcom,has-pronto-hw: boolean flag to determine the revId of the WLAN subsystem
- qcom,wcnss-adc_tm: ADC handle for vbatt notification APIs.
- qcom,wcnss-vadc: VADC handle for battery voltage notification APIs.
- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
- pinctrl-names : Names corresponding to the numbered pinctrl states
- clocks: from common clock binding: handle to xo and rf_clk clocks.
@@ -42,6 +43,9 @@ according to the ponto HW version
- qcom,is-pronto-v3: boolean flag to determine the pronto hardware version
in use. subsequently correct workqueue will be used by DXE engine to push frames
in TX data path and correct voting to RPM will be decided for booting.
- qcom,is-pronto-v4: boolean flag to determine the pronto hardware version
in use. subsequently correct workqueue will be used by DXE engine to push frames
in TX data path.
- qcom,wcnss-pm : <Core rail LDO#, PA rail LDO#, XO settling time,
		   RPM power collapse enabled, standalone power collapse enabled>
	Power manager related parameter for LDO configuration.
@@ -51,7 +55,12 @@ in TX data path and correct voting to RPM will be decided for booting.
	1      -  WCN RPM power collapse enabled
	1      -  WCN standalone power collapse enabled
	6      -  GPIO strength value

- qcom,wlan-indication-enabled: boolean flag to determine if WLAN indication-LED
will be turned on/off when WLAN is enabled/disabled respectively.
- qcom,has-vsys-adc-channel: boolean flag to determine which ADC HW channel need
to use for VBATT feature.
- qcom,pc-disable-latency: is a configurable value to configure
pc disable latency value.

Example:

+20 −7
Original line number Diff line number Diff line
@@ -344,25 +344,38 @@ prototypes:


locking rules:
			file_lock_lock	may block
			inode->i_lock	may block
fl_copy_lock:		yes		no
fl_release_private:	maybe		no

----------------------- lock_manager_operations ---------------------------
prototypes:
	int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
	unsigned long (*lm_owner_key)(struct file_lock *);
	void (*lm_notify)(struct file_lock *);  /* unblock callback */
	int (*lm_grant)(struct file_lock *, struct file_lock *, int);
	void (*lm_break)(struct file_lock *); /* break_lease callback */
	int (*lm_change)(struct file_lock **, int);

locking rules:
			file_lock_lock	may block
lm_compare_owner:	yes		no
lm_notify:		yes		no
lm_grant:		no		no
lm_break:		yes		no
lm_change		yes		no

			inode->i_lock	blocked_lock_lock	may block
lm_compare_owner:	yes[1]		maybe			no
lm_owner_key		yes[1]		yes			no
lm_notify:		yes		yes			no
lm_grant:		no		no			no
lm_break:		yes		no			no
lm_change		yes		no			no

[1]:	->lm_compare_owner and ->lm_owner_key are generally called with
*an* inode->i_lock held. It may not be the i_lock of the inode
associated with either file_lock argument! This is the case with deadlock
detection, since the code has to chase down the owners of locks that may
be entirely unrelated to the one on which the lock is being acquired.
For deadlock detection however, the blocked_lock_lock is also held. The
fact that these locks are held ensures that the file_locks do not
disappear out from under you while doing the comparison or generating an
owner key.

--------------------------- buffer_head -----------------------------------
prototypes:
+13 −9
Original line number Diff line number Diff line
@@ -171,23 +171,19 @@ output must be passed to the seq_file code. Some utility functions have
been defined which make this task easy.

Most code will simply use seq_printf(), which works pretty much like
printk(), but which requires the seq_file pointer as an argument. It is
common to ignore the return value from seq_printf(), but a function
producing complicated output may want to check that value and quit if
something non-zero is returned; an error return means that the seq_file
buffer has been filled and further output will be discarded.
printk(), but which requires the seq_file pointer as an argument.

For straight character output, the following functions may be used:

	int seq_putc(struct seq_file *m, char c);
	int seq_puts(struct seq_file *m, const char *s);
	int seq_escape(struct seq_file *m, const char *s, const char *esc);
	seq_putc(struct seq_file *m, char c);
	seq_puts(struct seq_file *m, const char *s);
	seq_escape(struct seq_file *m, const char *s, const char *esc);

The first two output a single character and a string, just like one would
expect. seq_escape() is like seq_puts(), except that any character in s
which is in the string esc will be represented in octal form in the output.

There is also a pair of functions for printing filenames:
There are also a pair of functions for printing filenames:

	int seq_path(struct seq_file *m, struct path *path, char *esc);
	int seq_path_root(struct seq_file *m, struct path *path,
@@ -200,6 +196,14 @@ root is desired, it can be used with seq_path_root(). Note that, if it
turns out that path cannot be reached from root, the value of root will be
changed in seq_file_root() to a root which *does* work.

A function producing complicated output may want to check
	bool seq_has_overflowed(struct seq_file *m);
and avoid further seq_<output> calls if true is returned.

A true return from seq_has_overflowed means that the seq_file buffer will
be discarded and the seq_show function will attempt to allocate a larger
buffer and retry printing.


Making it all work

+5 −0
Original line number Diff line number Diff line
@@ -4955,6 +4955,11 @@ F: arch/powerpc/platforms/pasemi/
F:	drivers/*/*pasemi*
F:	drivers/*/*/*pasemi*

LINUX KERNEL DUMP TEST MODULE (LKDTM)
M:	Kees Cook <keescook@chromium.org>
S:	Maintained
F:	drivers/misc/lkdtm/*

LINUX SECURITY MODULE (LSM) FRAMEWORK
M:	Chris Wright <chrisw@sous-sol.org>
L:	linux-security-module@vger.kernel.org
Loading