![]() |
|
|||
0001 /* 0002 * Copyright 2019 Advanced Micro Devices, Inc. 0003 * 0004 * Permission is hereby granted, free of charge, to any person obtaining a 0005 * copy of this software and associated documentation files (the "Software"), 0006 * to deal in the Software without restriction, including without limitation 0007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 0008 * and/or sell copies of the Software, and to permit persons to whom the 0009 * Software is furnished to do so, subject to the following conditions: 0010 * 0011 * The above copyright notice and this permission notice shall be included in 0012 * all copies or substantial portions of the Software. 0013 * 0014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 0017 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 0018 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 0019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 0020 * OTHER DEALINGS IN THE SOFTWARE. 0021 * 0022 */ 0023 #include <linux/semaphore.h> 0024 #include <linux/atomic.h> 0025 0026 /* 0027 * Reusable 2 PHASE task barrier (randevouz point) implementation for N tasks. 0028 * Based on the Little book of sempahores - https://greenteapress.com/wp/semaphores/ 0029 */ 0030 0031 0032 0033 #ifndef DRM_TASK_BARRIER_H_ 0034 #define DRM_TASK_BARRIER_H_ 0035 0036 /* 0037 * Represents an instance of a task barrier. 0038 */ 0039 struct task_barrier { 0040 unsigned int n; 0041 atomic_t count; 0042 struct semaphore enter_turnstile; 0043 struct semaphore exit_turnstile; 0044 }; 0045 0046 static inline void task_barrier_signal_turnstile(struct semaphore *turnstile, 0047 unsigned int n) 0048 { 0049 int i; 0050 0051 for (i = 0 ; i < n; i++) 0052 up(turnstile); 0053 } 0054 0055 static inline void task_barrier_init(struct task_barrier *tb) 0056 { 0057 tb->n = 0; 0058 atomic_set(&tb->count, 0); 0059 sema_init(&tb->enter_turnstile, 0); 0060 sema_init(&tb->exit_turnstile, 0); 0061 } 0062 0063 static inline void task_barrier_add_task(struct task_barrier *tb) 0064 { 0065 tb->n++; 0066 } 0067 0068 static inline void task_barrier_rem_task(struct task_barrier *tb) 0069 { 0070 tb->n--; 0071 } 0072 0073 /* 0074 * Lines up all the threads BEFORE the critical point. 0075 * 0076 * When all thread passed this code the entry barrier is back to locked state. 0077 */ 0078 static inline void task_barrier_enter(struct task_barrier *tb) 0079 { 0080 if (atomic_inc_return(&tb->count) == tb->n) 0081 task_barrier_signal_turnstile(&tb->enter_turnstile, tb->n); 0082 0083 down(&tb->enter_turnstile); 0084 } 0085 0086 /* 0087 * Lines up all the threads AFTER the critical point. 0088 * 0089 * This function is used to avoid any one thread running ahead if the barrier is 0090 * used repeatedly . 0091 */ 0092 static inline void task_barrier_exit(struct task_barrier *tb) 0093 { 0094 if (atomic_dec_return(&tb->count) == 0) 0095 task_barrier_signal_turnstile(&tb->exit_turnstile, tb->n); 0096 0097 down(&tb->exit_turnstile); 0098 } 0099 0100 /* Convinieince function when nothing to be done in between entry and exit */ 0101 static inline void task_barrier_full(struct task_barrier *tb) 0102 { 0103 task_barrier_enter(tb); 0104 task_barrier_exit(tb); 0105 } 0106 0107 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |