/work/svt-av1/Source/Lib/Codec/svt_threads.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright(c) 2019 Intel Corporation |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at https://www.aomedia.org/license/software-license. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license. |
10 | | */ |
11 | | |
12 | | #ifndef EbThreads_h |
13 | | #define EbThreads_h |
14 | | |
15 | | #include "definitions.h" |
16 | | |
17 | | #ifdef _WIN32 |
18 | | #include <windows.h> |
19 | | #endif |
20 | | |
21 | | #ifdef __cplusplus |
22 | | extern "C" { |
23 | | #endif |
24 | | // Create wrapper functions that hide thread calls, |
25 | | // semaphores, mutex, etc. These wrappers also hide |
26 | | // platform specific implementations of these objects. |
27 | | |
28 | | /************************************** |
29 | | * Threads |
30 | | **************************************/ |
31 | | EbHandle svt_create_thread(void* thread_function(void*), void* thread_context, const char* name); |
32 | | |
33 | | EbErrorType svt_destroy_thread(EbHandle thread_handle); |
34 | | |
35 | | // Format a per-instance worker thread name as `<prefix><index>` into a fixed |
36 | | // buffer (typical size 16 to match TASK_COMM_LEN). Used by EB_CREATE_THREAD_ARRAY. |
37 | | void svt_format_thread_name(char* buf, size_t size, const char* prefix, uint32_t index); |
38 | | |
39 | | /************************************** |
40 | | * Semaphores |
41 | | **************************************/ |
42 | | EbHandle svt_create_semaphore(uint32_t initial_count, uint32_t max_count); |
43 | | |
44 | | EbErrorType svt_post_semaphore(EbHandle semaphore_handle); |
45 | | |
46 | | EbErrorType svt_block_on_semaphore(EbHandle semaphore_handle); |
47 | | |
48 | | EbErrorType svt_destroy_semaphore(EbHandle semaphore_handle); |
49 | | |
50 | | /************************************** |
51 | | * Mutex |
52 | | **************************************/ |
53 | | EbHandle svt_create_mutex(void); |
54 | | EbErrorType svt_release_mutex(EbHandle mutex_handle); |
55 | | EbErrorType svt_block_on_mutex(EbHandle mutex_handle); |
56 | | EbErrorType svt_destroy_mutex(EbHandle mutex_handle); |
57 | | #ifndef _WIN32 |
58 | | #ifndef __USE_GNU |
59 | | #define __USE_GNU |
60 | | #endif |
61 | | #ifndef _GNU_SOURCE |
62 | | #define _GNU_SOURCE |
63 | | #endif |
64 | | #include <sched.h> |
65 | | #include <pthread.h> |
66 | | #endif |
67 | | #define EB_CREATE_THREAD_NAMED(pointer, thread_function, thread_context, name) \ |
68 | 13.3k | do { \ |
69 | 13.3k | pointer = svt_create_thread(thread_function, thread_context, name); \ |
70 | 13.3k | EB_ADD_MEM(pointer, 1, EB_THREAD); \ |
71 | 13.3k | } while (0) |
72 | | |
73 | | /* `thread_function` must be a bare identifier here; the macro derives the |
74 | | * thread name via # stringification, so any cast or member access (e.g. |
75 | | * `(kernel_t)fn`, `ctx->fn`) would leak into the thread name. */ |
76 | | #define EB_CREATE_THREAD(pointer, thread_function, thread_context) \ |
77 | 2.84k | EB_CREATE_THREAD_NAMED(pointer, thread_function, thread_context, #thread_function) |
78 | | #define EB_DESTROY_THREAD(pointer) \ |
79 | 13.3k | do { \ |
80 | 13.3k | if (pointer) { \ |
81 | 13.3k | svt_destroy_thread(pointer); \ |
82 | 13.3k | EB_REMOVE_MEM_ENTRY(pointer, EB_THREAD); \ |
83 | 13.3k | pointer = NULL; \ |
84 | 13.3k | } \ |
85 | 13.3k | } while (0); |
86 | | |
87 | | #define EB_CREATE_THREAD_ARRAY(pa, count, thread_function, thread_contexts, name_prefix) \ |
88 | 4.74k | do { \ |
89 | 4.74k | EB_ALLOC_PTR_ARRAY(pa, count); \ |
90 | 15.2k | for (uint32_t i = 0; i < count; i++) { \ |
91 | 10.5k | char _svt_thr_name[16]; \ |
92 | 10.5k | svt_format_thread_name(_svt_thr_name, sizeof(_svt_thr_name), name_prefix, i); \ |
93 | 10.5k | EB_CREATE_THREAD_NAMED(pa[i], thread_function, thread_contexts[i], _svt_thr_name); \ |
94 | 10.5k | } \ |
95 | 4.74k | } while (0) |
96 | | |
97 | | #define EB_DESTROY_THREAD_ARRAY(pa, count) \ |
98 | 4.74k | do { \ |
99 | 4.74k | if (pa) { \ |
100 | 15.2k | for (uint32_t i = 0; i < count; i++) \ |
101 | 10.5k | EB_DESTROY_THREAD(pa[i]); \ |
102 | 4.74k | EB_FREE_PTR_ARRAY(pa, count); \ |
103 | 4.74k | } \ |
104 | 4.74k | } while (0) |
105 | | |
106 | | void svt_aom_atomic_set_u32(AtomicVarU32* var, uint32_t in); |
107 | | |
108 | | /* |
109 | | Condition variable |
110 | | */ |
111 | | typedef struct CondVar { |
112 | | int32_t val; |
113 | | #ifdef _WIN32 |
114 | | CRITICAL_SECTION cs; |
115 | | CONDITION_VARIABLE cv; |
116 | | #else |
117 | | pthread_mutex_t m_mutex; |
118 | | pthread_cond_t m_cond; |
119 | | #endif |
120 | | } CondVar; |
121 | | |
122 | | EbErrorType svt_set_cond_var(CondVar* cond_var, int32_t newval); |
123 | | EbErrorType svt_wait_cond_var(CondVar* cond_var, int32_t input); |
124 | | EbErrorType svt_create_cond_var(CondVar* cond_var); |
125 | | |
126 | | // once related functions and macros |
127 | | #ifdef _WIN32 |
128 | | typedef INIT_ONCE OnceType; |
129 | | #define ONCE_INIT INIT_ONCE_STATIC_INIT |
130 | | #define ONCE_ROUTINE(name) BOOL CALLBACK name(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* lpContext) |
131 | | #define ONCE_ROUTINE_EPILOG \ |
132 | | do { \ |
133 | | return TRUE; \ |
134 | | } while (0) |
135 | | typedef PINIT_ONCE_FN OnceFn; |
136 | | #else |
137 | | typedef pthread_once_t OnceType; |
138 | | #define ONCE_INIT PTHREAD_ONCE_INIT |
139 | | #define ONCE_ROUTINE(name) void name(void) |
140 | | #define ONCE_ROUTINE_EPILOG \ |
141 | 4 | do { \ |
142 | 4 | return; \ |
143 | 4 | } while (0) |
144 | | typedef void (*OnceFn)(void); |
145 | | #endif |
146 | | #define DEFINE_ONCE(once_control) static OnceType once_control = ONCE_INIT |
147 | | |
148 | | // Macro to define a lazily-initialized mutex with once control |
149 | | // Usage: DEFINE_ONCE_MUTEX(my_mutex) |
150 | | // Then call: RUN_ONCE_MUTEX(my_mutex) before using svt_block_on_mutex(my_mutex) |
151 | | #define DEFINE_ONCE_MUTEX(mutex_name) \ |
152 | | static EbHandle mutex_name = NULL; \ |
153 | 2 | static void deinit_##mutex_name(void) { \ |
154 | 2 | if (mutex_name) { \ |
155 | 2 | svt_destroy_mutex(mutex_name); \ |
156 | 2 | mutex_name = NULL; \ |
157 | 2 | } \ |
158 | 2 | } \ |
159 | 2 | ONCE_ROUTINE(init_##mutex_name) { \ |
160 | 2 | mutex_name = svt_create_mutex(); \ |
161 | 2 | atexit(deinit_##mutex_name); \ |
162 | 2 | ONCE_ROUTINE_EPILOG; \ |
163 | 2 | } \ Line | Count | Source | 159 | 1 | ONCE_ROUTINE(init_##mutex_name) { \ | 160 | 1 | mutex_name = svt_create_mutex(); \ | 161 | 1 | atexit(deinit_##mutex_name); \ | 162 | 1 | ONCE_ROUTINE_EPILOG; \ | 163 | 1 | } \ |
init_common_rtcd_init_mutex Line | Count | Source | 159 | 1 | ONCE_ROUTINE(init_##mutex_name) { \ | 160 | 1 | mutex_name = svt_create_mutex(); \ | 161 | 1 | atexit(deinit_##mutex_name); \ | 162 | 1 | ONCE_ROUTINE_EPILOG; \ | 163 | 1 | } \ |
|
164 | | DEFINE_ONCE(mutex_name##_once) |
165 | | |
166 | 948 | #define RUN_ONCE_MUTEX(mutex_name) svt_run_once(&mutex_name##_once, init_##mutex_name) |
167 | | |
168 | | void svt_run_once(OnceType* once_control, OnceFn init_routine); |
169 | | |
170 | | #ifdef __cplusplus |
171 | | } |
172 | | #endif |
173 | | #endif // EbThreads_h |