1/*
2* Copyright(c) 2019 Intel Corporation
3* SPDX - License - Identifier: BSD - 2 - Clause - Patent
4*/
5
6#ifndef EbThreads_h
7#define EbThreads_h
8
9#include "EbDefinitions.h"
10#include "EbDefinitions.h"
11
12#ifdef _WIN32
13#include <windows.h>
14#endif
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19// Create wrapper functions that hide thread calls,
20// semaphores, mutex, etc. These wrappers also hide
21// platform specific implementations of these objects.
22
23/**************************************
24 * Threads
25 **************************************/
26extern EbHandle eb_vp9_create_thread(
27    void *thread_function(void *),
28    void *thread_context);
29extern EbErrorType eb_start_thread(
30    EbHandle thread_handle);
31extern EbErrorType eb_stop_thread(
32    EbHandle thread_handle);
33extern EbErrorType eb_vp9_destroy_thread(
34    EbHandle thread_handle);
35
36/**************************************
37 * Semaphores
38 **************************************/
39extern EbHandle eb_vp9_create_semaphore(
40    uint32_t initial_count,
41    uint32_t max_count);
42extern EbErrorType eb_vp9_post_semaphore(
43    EbHandle semaphore_handle);
44extern EbErrorType eb_vp9_block_on_semaphore(
45    EbHandle semaphore_handle);
46extern EbErrorType eb_vp9_destroy_semaphore(
47    EbHandle semaphore_handle);
48/**************************************
49 * Mutex
50 **************************************/
51extern EbHandle eb_vp9_create_mutex(
52    void);
53extern EbErrorType eb_vp9_release_mutex(
54    EbHandle mutex_handle);
55extern EbErrorType eb_vp9_block_on_mutex(
56    EbHandle mutex_handle);
57extern EbErrorType eb_vp9_block_on_mutex_timeout(
58    EbHandle mutex_handle,
59    uint32_t timeout);
60extern EbErrorType eb_vp9_destroy_mutex(
61    EbHandle mutex_handle);
62
63extern    EbMemoryMapEntry *memory_map;                // library Memory table
64extern    uint32_t         *memory_map_index;          // library memory index
65extern    uint64_t         *total_lib_memory;          // library Memory malloc'd
66
67#ifdef _WIN32
68
69#define EB_CREATETHREAD(type, pointer, n_elements, pointer_class, thread_function, thread_context) \
70    pointer = eb_vp9_create_thread(thread_function, thread_context); \
71    if (pointer == (type)EB_NULL) { \
72        return EB_ErrorInsufficientResources; \
73    } \
74    else { \
75        memory_map[*(memory_map_index)].ptr_type = pointer_class; \
76        memory_map[(*(memory_map_index))++].ptr = pointer; \
77        if (n_elements % 8 == 0) { \
78            *total_lib_memory += (n_elements); \
79        } \
80        else { \
81            *total_lib_memory += ((n_elements) + (8 - ((n_elements) % 8))); \
82        } \
83        if (eb_vp9_num_groups == 2 && eb_vp9_alternate_groups){ \
84            eb_vp9_group_affinity.Group = 1 - eb_vp9_group_affinity.Group; \
85            SetThreadGroupAffinity(pointer,&eb_vp9_group_affinity,NULL); \
86        } \
87        else if (eb_vp9_num_groups == 2 && !eb_vp9_alternate_groups){ \
88            SetThreadGroupAffinity(pointer,&eb_vp9_group_affinity,NULL); \
89        } \
90    } \
91    if (*(memory_map_index) >= MAX_NUM_PTR) { \
92        return EB_ErrorInsufficientResources; \
93    } \
94    lib_thread_count++;
95#elif defined(__linux__)
96#define EB_CREATETHREAD(type, pointer, n_elements, pointer_class, thread_function, thread_context) \
97    pointer = eb_vp9_create_thread(thread_function, thread_context); \
98    if (pointer == (type)EB_NULL) { \
99        return EB_ErrorInsufficientResources; \
100    } \
101    else { \
102        pthread_setaffinity_np(*((pthread_t*)pointer),sizeof(cpu_set_t),&eb_vp9_group_affinity); \
103        memory_map[*(memory_map_index)].ptr_type = pointer_class; \
104        memory_map[(*(memory_map_index))++].ptr = pointer; \
105        if (n_elements % 8 == 0) { \
106            *total_lib_memory += (n_elements); \
107        } \
108        else { \
109            *total_lib_memory += ((n_elements) + (8 - ((n_elements) % 8))); \
110        } \
111    } \
112    if (*(memory_map_index) >= MAX_NUM_PTR) { \
113        return EB_ErrorInsufficientResources; \
114    } \
115    lib_thread_count++;
116#else
117#define EB_CREATETHREAD(type, pointer, n_elements, pointer_class, thread_function, thread_context) \
118    pointer = eb_vp9_create_thread(thread_function, thread_context); \
119    if (pointer == (type)EB_NULL) { \
120        return EB_ErrorInsufficientResources; \
121    } \
122   else { \
123        memory_map[*(memory_map_index)].ptr_type = pointer_class; \
124        memory_map[(*(memory_map_index))++].ptr = pointer; \
125        if (n_elements % 8 == 0) { \
126            *total_lib_memory += (n_elements); \
127        } \
128        else { \
129            *total_lib_memory += ((n_elements) + (8 - ((n_elements) % 8))); \
130        } \
131    } \
132    if (*(memory_map_index) >= MAX_NUM_PTR) { \
133        return EB_ErrorInsufficientResources; \
134    } \
135    lib_thread_count++;
136#endif
137
138#ifdef __cplusplus
139}
140#endif
141#endif // EbThreads_h
142