diff options
Diffstat (limited to 'include/linux/percpu.h')
| -rw-r--r-- | include/linux/percpu.h | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 27c3c6fcfad..3a5c4449fd3 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h | |||
| @@ -255,6 +255,30 @@ extern void __bad_size_call_parameter(void); | |||
| 255 | pscr2_ret__; \ | 255 | pscr2_ret__; \ |
| 256 | }) | 256 | }) |
| 257 | 257 | ||
| 258 | /* | ||
| 259 | * Special handling for cmpxchg_double. cmpxchg_double is passed two | ||
| 260 | * percpu variables. The first has to be aligned to a double word | ||
| 261 | * boundary and the second has to follow directly thereafter. | ||
| 262 | */ | ||
| 263 | #define __pcpu_double_call_return_bool(stem, pcp1, pcp2, ...) \ | ||
| 264 | ({ \ | ||
| 265 | bool pdcrb_ret__; \ | ||
| 266 | __verify_pcpu_ptr(&pcp1); \ | ||
| 267 | BUILD_BUG_ON(sizeof(pcp1) != sizeof(pcp2)); \ | ||
| 268 | VM_BUG_ON((unsigned long)(&pcp1) % (2 * sizeof(pcp1))); \ | ||
| 269 | VM_BUG_ON((unsigned long)(&pcp2) != \ | ||
| 270 | (unsigned long)(&pcp1) + sizeof(pcp1)); \ | ||
| 271 | switch(sizeof(pcp1)) { \ | ||
| 272 | case 1: pdcrb_ret__ = stem##1(pcp1, pcp2, __VA_ARGS__); break; \ | ||
| 273 | case 2: pdcrb_ret__ = stem##2(pcp1, pcp2, __VA_ARGS__); break; \ | ||
| 274 | case 4: pdcrb_ret__ = stem##4(pcp1, pcp2, __VA_ARGS__); break; \ | ||
| 275 | case 8: pdcrb_ret__ = stem##8(pcp1, pcp2, __VA_ARGS__); break; \ | ||
| 276 | default: \ | ||
| 277 | __bad_size_call_parameter(); break; \ | ||
| 278 | } \ | ||
| 279 | pdcrb_ret__; \ | ||
| 280 | }) | ||
| 281 | |||
| 258 | #define __pcpu_size_call(stem, variable, ...) \ | 282 | #define __pcpu_size_call(stem, variable, ...) \ |
| 259 | do { \ | 283 | do { \ |
| 260 | __verify_pcpu_ptr(&(variable)); \ | 284 | __verify_pcpu_ptr(&(variable)); \ |
| @@ -501,6 +525,45 @@ do { \ | |||
| 501 | #endif | 525 | #endif |
| 502 | 526 | ||
| 503 | /* | 527 | /* |
| 528 | * cmpxchg_double replaces two adjacent scalars at once. The first | ||
| 529 | * two parameters are per cpu variables which have to be of the same | ||
| 530 | * size. A truth value is returned to indicate success or failure | ||
| 531 | * (since a double register result is difficult to handle). There is | ||
| 532 | * very limited hardware support for these operations, so only certain | ||
| 533 | * sizes may work. | ||
| 534 | */ | ||
| 535 | #define _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 536 | ({ \ | ||
| 537 | int ret__; \ | ||
| 538 | preempt_disable(); \ | ||
| 539 | ret__ = __this_cpu_generic_cmpxchg_double(pcp1, pcp2, \ | ||
| 540 | oval1, oval2, nval1, nval2); \ | ||
| 541 | preempt_enable(); \ | ||
| 542 | ret__; \ | ||
| 543 | }) | ||
| 544 | |||
| 545 | #ifndef this_cpu_cmpxchg_double | ||
| 546 | # ifndef this_cpu_cmpxchg_double_1 | ||
| 547 | # define this_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 548 | _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 549 | # endif | ||
| 550 | # ifndef this_cpu_cmpxchg_double_2 | ||
| 551 | # define this_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 552 | _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 553 | # endif | ||
| 554 | # ifndef this_cpu_cmpxchg_double_4 | ||
| 555 | # define this_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 556 | _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 557 | # endif | ||
| 558 | # ifndef this_cpu_cmpxchg_double_8 | ||
| 559 | # define this_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 560 | _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 561 | # endif | ||
| 562 | # define this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 563 | __pcpu_double_call_return_bool(this_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2)) | ||
| 564 | #endif | ||
| 565 | |||
| 566 | /* | ||
| 504 | * Generic percpu operations that do not require preemption handling. | 567 | * Generic percpu operations that do not require preemption handling. |
| 505 | * Either we do not care about races or the caller has the | 568 | * Either we do not care about races or the caller has the |
| 506 | * responsibility of handling preemptions issues. Arch code can still | 569 | * responsibility of handling preemptions issues. Arch code can still |
| @@ -703,6 +766,39 @@ do { \ | |||
| 703 | __pcpu_size_call_return2(__this_cpu_cmpxchg_, pcp, oval, nval) | 766 | __pcpu_size_call_return2(__this_cpu_cmpxchg_, pcp, oval, nval) |
| 704 | #endif | 767 | #endif |
| 705 | 768 | ||
| 769 | #define __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 770 | ({ \ | ||
| 771 | int __ret = 0; \ | ||
| 772 | if (__this_cpu_read(pcp1) == (oval1) && \ | ||
| 773 | __this_cpu_read(pcp2) == (oval2)) { \ | ||
| 774 | __this_cpu_write(pcp1, (nval1)); \ | ||
| 775 | __this_cpu_write(pcp2, (nval2)); \ | ||
| 776 | __ret = 1; \ | ||
| 777 | } \ | ||
| 778 | (__ret); \ | ||
| 779 | }) | ||
| 780 | |||
| 781 | #ifndef __this_cpu_cmpxchg_double | ||
| 782 | # ifndef __this_cpu_cmpxchg_double_1 | ||
| 783 | # define __this_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 784 | __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 785 | # endif | ||
| 786 | # ifndef __this_cpu_cmpxchg_double_2 | ||
| 787 | # define __this_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 788 | __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 789 | # endif | ||
| 790 | # ifndef __this_cpu_cmpxchg_double_4 | ||
| 791 | # define __this_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 792 | __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 793 | # endif | ||
| 794 | # ifndef __this_cpu_cmpxchg_double_8 | ||
| 795 | # define __this_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 796 | __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 797 | # endif | ||
| 798 | # define __this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 799 | __pcpu_double_call_return_bool(__this_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2)) | ||
| 800 | #endif | ||
| 801 | |||
| 706 | /* | 802 | /* |
| 707 | * IRQ safe versions of the per cpu RMW operations. Note that these operations | 803 | * IRQ safe versions of the per cpu RMW operations. Note that these operations |
| 708 | * are *not* safe against modification of the same variable from another | 804 | * are *not* safe against modification of the same variable from another |
| @@ -823,4 +919,36 @@ do { \ | |||
| 823 | __pcpu_size_call_return2(irqsafe_cpu_cmpxchg_, (pcp), oval, nval) | 919 | __pcpu_size_call_return2(irqsafe_cpu_cmpxchg_, (pcp), oval, nval) |
| 824 | #endif | 920 | #endif |
| 825 | 921 | ||
| 922 | #define irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 923 | ({ \ | ||
| 924 | int ret__; \ | ||
| 925 | unsigned long flags; \ | ||
| 926 | local_irq_save(flags); \ | ||
| 927 | ret__ = __this_cpu_generic_cmpxchg_double(pcp1, pcp2, \ | ||
| 928 | oval1, oval2, nval1, nval2); \ | ||
| 929 | local_irq_restore(flags); \ | ||
| 930 | ret__; \ | ||
| 931 | }) | ||
| 932 | |||
| 933 | #ifndef irqsafe_cpu_cmpxchg_double | ||
| 934 | # ifndef irqsafe_cpu_cmpxchg_double_1 | ||
| 935 | # define irqsafe_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 936 | irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 937 | # endif | ||
| 938 | # ifndef irqsafe_cpu_cmpxchg_double_2 | ||
| 939 | # define irqsafe_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 940 | irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 941 | # endif | ||
| 942 | # ifndef irqsafe_cpu_cmpxchg_double_4 | ||
| 943 | # define irqsafe_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 944 | irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 945 | # endif | ||
| 946 | # ifndef irqsafe_cpu_cmpxchg_double_8 | ||
| 947 | # define irqsafe_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 948 | irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) | ||
| 949 | # endif | ||
| 950 | # define irqsafe_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2) \ | ||
| 951 | __pcpu_double_call_return_int(irqsafe_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2)) | ||
| 952 | #endif | ||
| 953 | |||
| 826 | #endif /* __LINUX_PERCPU_H */ | 954 | #endif /* __LINUX_PERCPU_H */ |
