source: CIVL/examples/mpi-omp/AMG2013/utilities/threading.c

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 7.1 KB
RevLine 
[2aa6644]1/*BHEADER**********************************************************************
2 * Copyright (c) 2008, Lawrence Livermore National Security, LLC.
3 * Produced at the Lawrence Livermore National Laboratory.
4 * This file is part of HYPRE. See file COPYRIGHT for details.
5 *
6 * HYPRE is free software; you can redistribute it and/or modify it under the
7 * terms of the GNU Lesser General Public License (as published by the Free
8 * Software Foundation) version 2.1 dated February 1999.
9 *
10 * $Revision: 2.4 $
11 ***********************************************************************EHEADER*/
12
13
14#include <stdlib.h>
15#include <stdio.h>
16#include "utilities.h"
17
18#if defined(HYPRE_USING_OPENMP) || defined (HYPRE_USING_PGCC_SMP)
19
20int
21hypre_NumThreads( )
22{
23 int num_threads;
24
25#ifdef HYPRE_USING_OPENMP
26#pragma omp parallel
27 num_threads = omp_get_num_threads();
28#endif
29#ifdef HYPRE_USING_PGCC_SMP
30 num_threads = 2;
31#endif
32
33 return num_threads;
34}
35/* This next function must be called from within a parallel region! */
36
37int
38hypre_NumActiveThreads( )
39{
40 int num_threads;
41
42 num_threads = omp_get_num_threads();
43
44 return num_threads;
45}
46
47/* This next function must be called from within a parallel region! */
48
49int
50hypre_GetThreadNum( )
51{
52 int my_thread_num;
53
54 my_thread_num = omp_get_thread_num();
55
56 return my_thread_num;
57}
58
59#endif
60
61/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
62/* The pthreads stuff needs to be reworked */
63
64#define HYPRE_THREAD_GLOBALS
65
66#ifdef HYPRE_USE_PTHREADS
67
68#ifdef HYPRE_USE_UMALLOC
69#include "umalloc_local.h"
70#endif
71
72int iteration_counter = 0;
73volatile int hypre_thread_counter;
74volatile int work_continue = 1;
75
76
77int HYPRE_InitPthreads( int num_threads )
78{
79 int err;
80 int i;
81 hypre_qptr =
82 (hypre_workqueue_t) malloc(sizeof(struct hypre_workqueue_struct));
83
84 hypre_NumThreads = num_threads;
85 initial_thread = pthread_self();
86
87 if (hypre_qptr != NULL) {
88 pthread_mutex_init(&hypre_qptr->lock, NULL);
89 pthread_cond_init(&hypre_qptr->work_wait, NULL);
90 pthread_cond_init(&hypre_qptr->finish_wait, NULL);
91 hypre_qptr->n_working = hypre_qptr->n_waiting = hypre_qptr->n_queue = 0;
92 hypre_qptr->inp = hypre_qptr->outp = 0;
93 for (i=0; i < hypre_NumThreads; i++) {
94#ifdef HYPRE_USE_UMALLOC
95 /* Get initial area to start heap */
96 hypre_assert ((_uinitial_block[i] = malloc(INITIAL_HEAP_SIZE))!=NULL);
97
98 /* Create a user heap */
99 hypre_assert ((_uparam[i].myheap = _ucreate(initial_block[i],
100 INITIAL_HEAP_SIZE,
101 _BLOCK_CLEAN,
102 _HEAP_REGULAR,
103 _uget_fn,
104 _urelease_fn)) != NULL);
105#endif
106 err=pthread_create(&hypre_thread[i], NULL,
107 (void *(*)(void *))hypre_pthread_worker,
108 (void *)i);
109 hypre_assert(err == 0);
110 }
111 }
112
113 pthread_mutex_init(&hypre_mutex_boxloops, NULL);
114 pthread_mutex_init(&mpi_mtx, NULL);
115 pthread_mutex_init(&talloc_mtx, NULL);
116 pthread_mutex_init(&time_mtx, NULL);
117 pthread_mutex_init(&worker_mtx, NULL);
118 hypre_thread_counter = 0;
119 hypre_thread_release = 0;
120
121 return (err);
122}
123
124void hypre_StopWorker(void *i)
125{
126 work_continue = 0;
127}
128
129void HYPRE_DestroyPthreads( void )
130{
131 int i;
132 void *status;
133
134 for (i=0; i < hypre_NumThreads; i++) {
135 hypre_work_put(hypre_StopWorker, (void *) &i);
136 }
137
138#ifdef HYPRE_USE_UMALLOC
139 for (i=0; i<hypre_NumThreads; i++)
140 {
141 _udestroy (_uparam[i].myheap, _FORCE);
142 }
143#endif
144
145 for (i=0; i<hypre_NumThreads; i++)
146 pthread_join(hypre_thread[i], &status);
147 pthread_mutex_destroy(&hypre_qptr->lock);
148 pthread_mutex_destroy(&hypre_mutex_boxloops);
149 pthread_mutex_destroy(&mpi_mtx);
150 pthread_mutex_destroy(&talloc_mtx);
151 pthread_mutex_destroy(&time_mtx);
152 pthread_mutex_destroy(&worker_mtx);
153 pthread_cond_destroy(&hypre_qptr->work_wait);
154 pthread_cond_destroy(&hypre_qptr->finish_wait);
155 free (hypre_qptr);
156}
157
158
159void hypre_pthread_worker( int threadid )
160{
161 void *argptr;
162 hypre_work_proc_t funcptr;
163
164 pthread_mutex_lock(&hypre_qptr->lock);
165
166 hypre_qptr->n_working++;
167
168 while(work_continue) {
169 while (hypre_qptr->n_queue == 0) {
170 if (--hypre_qptr->n_working == 0)
171 pthread_cond_signal(&hypre_qptr->finish_wait);
172 hypre_qptr->n_waiting++;
173 pthread_cond_wait(&hypre_qptr->work_wait, &hypre_qptr->lock);
174 hypre_qptr->n_waiting--;
175 hypre_qptr->n_working++;
176 }
177 hypre_qptr->n_queue--;
178 funcptr = hypre_qptr->worker_proc_queue[hypre_qptr->outp];
179 argptr = hypre_qptr->argqueue[hypre_qptr->outp];
180
181 hypre_qptr->outp = (hypre_qptr->outp + 1) % MAX_QUEUE;
182
183 pthread_mutex_unlock(&hypre_qptr->lock);
184
185 (*funcptr)(argptr);
186
187 hypre_barrier(&worker_mtx, 0);
188
189 if (work_continue)
190 pthread_mutex_lock(&hypre_qptr->lock);
191 }
192}
193
194void
195hypre_work_put( hypre_work_proc_t funcptr, void *argptr )
196{
197 pthread_mutex_lock(&hypre_qptr->lock);
198 if (hypre_qptr->n_waiting) {
199 /* idle workers to be awakened */
200 pthread_cond_signal(&hypre_qptr->work_wait);
201 }
202 hypre_assert(hypre_qptr->n_queue != MAX_QUEUE);
203
204 hypre_qptr->n_queue++;
205 hypre_qptr->worker_proc_queue[hypre_qptr->inp] = funcptr;
206 hypre_qptr->argqueue[hypre_qptr->inp] = argptr;
207 hypre_qptr->inp = (hypre_qptr->inp + 1) % MAX_QUEUE;
208 pthread_mutex_unlock(&hypre_qptr->lock);
209}
210
211
212/* Wait until all work is done and workers quiesce. */
213void
214hypre_work_wait( void )
215{
216 pthread_mutex_lock(&hypre_qptr->lock);
217 while(hypre_qptr->n_queue !=0 || hypre_qptr->n_working != 0)
218 pthread_cond_wait(&hypre_qptr->finish_wait, &hypre_qptr->lock);
219 pthread_mutex_unlock(&hypre_qptr->lock);
220}
221
222
223int
224hypre_fetch_and_add( int *w )
225{
226 int temp;
227
228 temp = *w;
229 *w += 1;
230
231 return temp;
232}
233
234int
235ifetchadd( int *w, pthread_mutex_t *mutex_fetchadd )
236{
237 int n;
238
239 pthread_mutex_lock(mutex_fetchadd);
240 n = *w;
241 *w += 1;
242 pthread_mutex_unlock(mutex_fetchadd);
243
244 return n;
245}
246
247static volatile int thb_count = 0;
248static volatile int thb_release = 0;
249
250void hypre_barrier(pthread_mutex_t *mtx, int unthreaded)
251{
252 if (!unthreaded) {
253 pthread_mutex_lock(mtx);
254 thb_count++;
255
256 if (thb_count < hypre_NumThreads) {
257 pthread_mutex_unlock(mtx);
258 while (!thb_release);
259 pthread_mutex_lock(mtx);
260 thb_count--;
261 pthread_mutex_unlock(mtx);
262 while (thb_release);
263 }
264 else if (thb_count == hypre_NumThreads) {
265 thb_count--;
266 pthread_mutex_unlock(mtx);
267 thb_release++;
268 while (thb_count);
269 thb_release = 0;
270 }
271 }
272}
273
274int
275hypre_GetThreadID( void )
276{
277 int i;
278
279 if (pthread_equal(pthread_self(), initial_thread))
280 return hypre_NumThreads;
281
282 for (i = 0; i < hypre_NumThreads; i++)
283 {
284 if (pthread_equal(pthread_self(), hypre_thread[i]))
285 return i;
286 }
287
288 return -1;
289}
290
291#endif
292/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
Note: See TracBrowser for help on using the repository browser.