Loading Documentation/core-api/refcount-vs-atomic.rst 0 → 100644 +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 Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt +10 −1 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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. Loading @@ -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: Loading Documentation/filesystems/Locking +20 −7 Original line number Diff line number Diff line Loading @@ -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: Loading Documentation/filesystems/seq_file.txt +13 −9 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 Loading MAINTAINERS +5 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
Documentation/core-api/refcount-vs-atomic.rst 0 → 100644 +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
Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt +10 −1 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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. Loading @@ -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: Loading
Documentation/filesystems/Locking +20 −7 Original line number Diff line number Diff line Loading @@ -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: Loading
Documentation/filesystems/seq_file.txt +13 −9 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 Loading
MAINTAINERS +5 −0 Original line number Diff line number Diff line Loading @@ -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