1 /*
2     cs_par_base.h:
3 
4     Copyright (C) 2011, 2017 John ffitch and Stephen Kyne
5 
6     This file is part of Csound.
7 
8     The Csound Library is free software; you can redistribute it
9     and/or modify it under the terms of the GNU Lesser General Public
10     License as published by the Free Software Foundation; either
11     version 2.1 of the License, or (at your option) any later version.
12 
13     Csound is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU Lesser General Public License for more details.
17 
18     You should have received a copy of the GNU Lesser General Public
19     License along with Csound; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21     02110-1301 USA
22 */
23 
24 #ifndef __CS_PAR_BASE_H__
25 #define __CS_PAR_BASE_H__
26 
27 // Semaphone.h only exists when using pthreads, doesn't apply to Windows
28 #ifndef WIN32
29   #include <semaphore.h>
30 #endif
31 
32 /* #define TAKE_LOCK(x) pthread_spin_lock(x)
33 #define RELS_LOCK(x) pthread_spin_unlock(x)
34 #define LOCK_TYPE  pthread_spinlock_t
35 #define INIT_LOCK(x)  pthread_spin_init(&(x), PTHREAD_PROCESS_PRIVATE)*/
36 
37 /* #define TAKE_LOCK(x) pthread_mutex_lock(x) */
38 /* #define RELS_LOCK(x) pthread_mutex_unlock(x) */
39 /* #define LOCK_TYPE  pthread_mutex_t */
40 /* #define INIT_LOCK(x)  pthread_mutex_init(&(x), NULL) */
41 
42 #if !defined(HAVE_PTHREAD_SPIN_LOCK)
43 // Windows environment should use native threads
44 # if WIN32
45  #define TAKE_LOCK(x) csoundLockMutex(x)
46  #define RELS_LOCK(x) csoundUnlockMutex(x)
47  #define LOCK_TYPE  LPCRITICAL_SECTION
48  // PTHREAD: FIXME no init function? unless createMutex should be used
49  //          but has a different function signature
50  #define INIT_LOCK(x) csoundCreateMutex(0)
51 # else
52  /* VL: 18.05.2011 enabled this to allow OSX build */
53  #define TAKE_LOCK(x) pthread_mutex_lock(x)
54  #define RELS_LOCK(x) pthread_mutex_unlock(x)
55  #define LOCK_TYPE  pthread_mutex_t
56  #define INIT_LOCK(x)  pthread_mutex_init(&(x), NULL)
57 # endif
58  #else
59  #define TAKE_LOCK(x) pthread_spin_lock(x)
60  #define RELS_LOCK(x) pthread_spin_unlock(x)
61  #define LOCK_TYPE  pthread_spinlock_t
62  #define INIT_LOCK(x)  pthread_spin_init(&(x), PTHREAD_PROCESS_PRIVATE)
63 #endif
64 
65 #define DYNAMIC_2_SERIALIZE_PAR
66 
67 /* #define TIMING */
68 
69 /* #define SPINLOCK_BARRIER */
70 /* #define SPINLOCK_2_BARRIER */
71 
72 #define HASH_CACHE
73 /* #define HYBRID_HASH_CACHE */
74 /* #define LINEAR_CACHE */
75 
76 /* #define CACLULATE_WEIGHTS_BUILD */
77 #define LOOKUP_WEIGHTS
78 
79 #define KPERF_SYM 0x31
80 #define BARRIER_1_WAIT_SYM 0x32
81 #define BARRIER_2_WAIT_SYM 0x33
82 
83 /* return thread index of caller */
84 int csp_thread_index_get(CSOUND *csound);
85 
86 /* structure headers */
87 #define HDR_LEN                 4
88 //#define INSTR_WEIGHT_INFO_HDR   "IWI"
89 #define INSTR_SEMANTICS_HDR     "SEM"
90 #define SET_ELEMENT_HDR         "STE"
91 #define SET_HDR                 "SET"
92 //#define DAG_2_HDR               "DG2"
93 //#define DAG_NODE_2_HDR          "DN2"
94 //#define SEMAPHORE_HDR           "SPS"
95 #define GLOBAL_VAR_LOCK_HDR     "GVL"
96 //#define SERIALIZED_DAG_HDR      "SDG"
97 
98 /*
99  * set structures
100  *
101  * set maintains insertion order of elements
102  * implemented as a singly linked list
103  */
104 struct set_element_t {
105     char                 hdr[4];
106     void                 *data;
107     struct set_element_t *next;
108 };
109 
110 struct set_t {
111     char                  hdr[4];
112     struct set_element_t *head;
113     struct set_element_t *tail;
114     int                  count;
115     int     (*ele_eq_func)(struct set_element_t *, struct set_element_t *);
116     void    (*ele_print_func)(CSOUND *, struct set_element_t *);
117     struct set_element_t **cache;
118 };
119 
120 /* function pointer types for set member equality */
121 typedef int (set_element_data_eq)(struct set_element_t *, struct set_element_t *);
122 int csp_set_element_string_eq(struct set_element_t *ele1,
123                               struct set_element_t *ele2);
124 int csp_set_element_ptr_eq(struct set_element_t *ele1,
125                            struct set_element_t *ele2);
126 
127 /* function pointer types for set member printing */
128 typedef void (set_element_data_print)(CSOUND *, struct set_element_t *);
129 void csp_set_element_string_print(CSOUND *csound, struct set_element_t *ele);
130 void csp_set_element_ptr_print(CSOUND *csound, struct set_element_t *ele);
131 
132 /* allocating sets with specification of element equality and printing functions */
133 struct set_t *csp_set_alloc(CSOUND *csound,
134                             set_element_data_eq *ele_eq_func,
135                             set_element_data_print *ele_print_func);
136 void csp_set_dealloc(CSOUND *csound, struct set_t **set);
137 /* shortcut to get a set of strings uses string element equality and
138    printing functions */
139 struct set_t *csp_set_alloc_string(CSOUND *csound);
140 
141 /* functions to manipulate set, return CSOUND_SUCCESS if successful */
142 void csp_set_add(CSOUND *csound,     struct set_t *set, void *data);
143 void csp_set_remove(CSOUND *csound,  struct set_t *set, void *data);
144 /* check element existance returns 1 if data exists */
145 void csp_set_print(CSOUND *csound, struct set_t *set);
146 
147 /* get a count and access members */
148 int csp_set_count(struct set_t *set);
149 
150 /*
151  * set union and intersection
152  * allocates a new set in result
153  * union/intersect first and second putting into result
154  */
155 struct set_t *csp_set_union(CSOUND *csound, struct set_t *first,
156                    struct set_t *second);
157 struct set_t *csp_set_intersection(CSOUND *csound, struct set_t *first,
158                           struct set_t *second);
159 
160 /* spinlock */
161 
162 /* semaphore */
163 /* struct semaphore_spin_t { */
164 /*     char    hdr[HDR_LEN]; */
165 /*     int     thread_count; */
166 /*     int     max_threads; */
167 /*     int     arrived; */
168 /*     int     held; */
169 /*     int     spinlock; */
170 /*     int     count; */
171 /*     int     lock; */
172 /*     int     *key; */
173 /*     int     locks[]; */
174 /* }; */
175 
176 // Kludge to allow us to pass in HANDLE objects to be used as semaphore whilst
177 // supporting the traditional pthread way for non Windows platforms
178 // FIXME, does this even work? API's take ** versions of sem_t
179 #ifdef WIN32
180 typedef HANDLE sem_t;
181 #endif
182 
183 /* create a semaphore with a maximum number of threads
184  * initially 1 thread is allowed in
185  */
186 void csp_semaphore_alloc(CSOUND *csound, sem_t **sem,
187                          int max_threads);
188 void csp_semaphore_dealloc(CSOUND *csound, sem_t **sem);
189 /* wait at the semaphore. if the number allowed in is greater than the
190  * number arrived calling thread continues
191  * otherwise thread blocks until semaphore is grown
192  */
193 void csp_semaphore_wait(CSOUND *csound, sem_t *sem);
194 /* increase the number of threads allowed in by 1 */
195 void csp_semaphore_grow(CSOUND *csound, sem_t *sem);
196 /* reduce the number of threads allowed in and the arrive count by 1
197  * call this when calling thread is finished with the semaphore. */
198 void csp_semaphore_release(CSOUND *csound, sem_t *sem);
199 /* call when all threads are done with the resource the semaphore is protecting.
200  * releases all blocked threads. */
201 void csp_semaphore_release_end(CSOUND *csound, sem_t *sem);
202 /* print semaphore info */
203 void csp_semaphore_release_print(CSOUND *csound, sem_t *sem);
204 
205 #endif /* end of include guard: __CS_PAR_BASE_H__ */
206