File: fftw_threads-int.h

package info (click to toggle)
fftw 2.1.5-8
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 6,768 kB
  • sloc: ansic: 65,239; sh: 7,399; ml: 3,084; perl: 2,894; makefile: 377; fortran: 102
file content (332 lines) | stat: -rw-r--r-- 10,466 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/*
 * Copyright (c) 1997-1999, 2003 Massachusetts Institute of Technology
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifndef FFTW_THREADS_INT_H
#define FFTW_THREADS_INT_H

/***** alloca declarations, as recommended by the autoconf manual: *****/

/* We have to include config.h here for the alloca stuff, which (due
   to AIX lossage) must be the first thing in the file) */
#include "config.h"

/* AIX requires this to be the first thing in the file.  */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
#  include <alloca.h>
# else
#  ifdef _AIX
 #pragma alloca
#  else
#   ifndef alloca /* predefined by HP cc +Olibcalls */
#     ifdef __cplusplus
        extern "C"
#     endif /* __cplusplus */
        char *alloca ();
#   endif
#  endif
# endif
#endif

/***********************************************************************/

#include "fftw-int.h"
#include "fftw_threads.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/************************* Thread Glue *************************/

/* Adding support for a new shared memory thread API should be easy.  You
   simply do the following things (look at the POSIX and Solaris
   threads code for examples):

   * Invent a symbol of the form FFTW_USING_FOO_THREADS to denote
     the use of your thread API, and add an 
              #elif defined(FFTW_USING_FOO_THREADS)
      before the #else clause below.  This is where you will put
      your thread definitions.  In this #elif, insert the following:

      -- #include any header files needed to use the thread API.

      -- Typedef fftw_thread_function to be a function pointer
         of the type used as a argument to fftw_thread_spawn
	 (i.e. the entry function for a thread).

      -- Define fftw_thread_id, via a typedef, to be the type
         that is used for thread identifiers.

      -- #define fftw_thread_spawn(tid_ptr, proc, data) to
         call whatever function to spawn a new thread.  The
         new thread should call proc(data) as its starting point,
         and tid_ptr is a pointer to a fftw_thread_id that
         is set to an identifier for the thread.  You can also
         define this as a subroutine (put it in fftw_threads.c)
	 if it is too complicated for a macro.  The prototype should
	 be:

	 void fftw_thread_spawn(fftw_thread_id *tid_ptr,
	                        fftw_thread_function proc,
				void *data);

      -- #define fftw_thread_wait(tid) to block until the thread
         whose identifier is tid has terminated.  You can also
         define this as a subroutine (put it in fftw_threads.c) if
	 it is too complicated for a macro.  The prototype should be:
	
	 void fftw_thread_wait(fftw_thread_id tid);

   * If you need to perform any initialization before using threads,
     put your initialization code in the fftw_threads_init() function
     in fftw_threads.c, bracketed by the appropriate #ifdef of course.

   * Also, of course, you should modify fftw/config.h to #define
     FFTW_USING_FOO_THREADS, or better yet modify config.h.in
     and configure.in so that autoconf can automatically detect
     your threads library.

   * Finally, if you do implement support for a new threads API, be
     sure to let us know at fftw@fftw.org so that we can distribute
     your code to others!

*/

/************************** Solaris Threads ****************************/
      
#if defined(FFTW_USING_SOLARIS_THREADS)

/* Solaris threads glue.  Tested. */

/* link with -lthread */

#include <thread.h>

/* Thread entry point: */
typedef void * (*fftw_thread_function) (void *);

typedef thread_t fftw_thread_id;

#define fftw_thread_spawn(tid_ptr, proc, data) \
     thr_create(0,0,proc,data,THR_BOUND,tid_ptr)

#define fftw_thread_wait(tid) thr_join(tid,0,0)

/************************** BeOS Threads ****************************/
      
#elif defined(FFTW_USING_BEOS_THREADS)

/* BeOS threads glue.  Tested for DR8.2. */

#include <OS.h>

/* Thread entry point: */
typedef thread_entry fftw_thread_function;

typedef thread_id fftw_thread_id;

#define fftw_thread_spawn(tid_ptr, proc, data) { \
     *(tid_ptr) = spawn_thread(proc,"FFTW",B_NORMAL_PRIORITY,data); \
     resume_thread(*(tid_ptr)); \
}

/* wait_for_thread requires that we pass a valid pointer as the
   second argument, even if we're not interested in the result. */
#define fftw_thread_wait(tid) {long exit_val;wait_for_thread(tid, &exit_val);}

/************************** MacOS Threads ****************************/

#elif defined(FFTW_USING_MACOS_THREADS)

/* MacOS MP threads glue. Experimental, untested! I do not have an
   MP MacOS system available to me...I just read the documentation.
   There is actually a good chance that this will work (since the
   code below is so short), but I make no guarantees.  Consider
   it to be a starting point for your own implementation. 

   I also had to insert some code in fftw_threads.c. 

   MacOS X will have real SMP support, thank goodness. */

/* Using this code in the MacOS: (See the README file for general
   documenation on the FFTW threads code.)  To use this code, you have
   to do two things.  First of all, you have to #define the symbol
   FFTW_USING_MACOS_THREADS. This can be done at the top of this file
   or perhaps in your compiler options.  Second, you have to weak-link
   your project to the MP library.

   In your code, you should check at run-time with MPLibraryIsLoaded()
   to see if the MP library is available. If it is not, it is
   still safe to call the fftw_threads routines...in this case,
   however, you must always pass 1 for the nthreads parameter!
   (Otherwise, you will probably want to pass the value of
   MPProcessors() for the nthreads parameter.) */

#include <MP.h>

typedef TaskProc fftw_thread_function;

typedef MPQueueID fftw_thread_id;

#define fftw_thread_spawn(tid_ptr, proc, data) { \
     MPTaskID task; \
     MPCreateQueue(tid_ptr); \
     MPCreateTask(proc,data,kMPUseDefaultStackSize,*(tid_ptr),0,0, \
		  kMPNormalTaskOptions,&task); \
}

#define fftw_thread_wait(tid) { \
     void *param1,*param2,*param3; \
     MPWaitOnQueue(tid,&param1,&param2,&param3,kDurationForever); \
     MPDeleteQueue(tid); \
}

/************************** Win32 Threads ****************************/

#elif defined(FFTW_USING_WIN32_THREADS)

/* Win32 threads glue.  We have not tested this code!  (I just implemented
   it by looking at a Win32 threads manual.)  Users have reported that this
   code works under NT using Microsoft compilers.
   
   To use it, you should #define the symbol FFTW_USING_WIN32_THREADS. */

#include <windows.h>

typedef LPTHREAD_START_ROUTINE fftw_thread_function;
typedef HANDLE fftw_thread_id;

#define fftw_thread_spawn(tid_ptr, proc, data) { \
     DWORD thrid; \
     *(tid_ptr) = CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0, \
			       (fftw_thread_function) proc, (LPVOID) data, \
			       0, &thrid); \
}

#define fftw_thread_wait(tid) { \
     WaitForSingleObject(tid, INFINITE); \
     CloseHandle(tid); \
}

/************************** Mach cthreads ****************************/

#elif defined(FFTW_USING_MACH_THREADS)

#ifdef HAVE_MACH_CTHREADS_H
#include <mach/cthreads.h>
#elif defined(HAVE_CTHREADS_H)
#include <cthreads.h>
#elif defined(HAVE_CTHREAD_H)
#include <cthread.h>
#endif

typedef cthread_fn_t fftw_thread_function;

typedef cthread_t fftw_thread_id;

#define fftw_thread_spawn(tid_ptr, proc, data) \
     *(tid_ptr) = cthread_fork(proc, (any_t) (data))

#define fftw_thread_wait(tid) cthread_join(tid)

/************************** MP directive Threads ****************************/

#elif defined(FFTW_USING_OPENMP_THREADS) || defined(FFTW_USING_SGIMP_THREADS)

/* Use MP compiler directives to induce parallelism, in which case
   we don't need any of the thread spawning/waiting macros: */

typedef void * (*fftw_thread_function) (void *);

typedef char fftw_thread_id;  /* dummy */

#define fftw_thread_spawn(tid_ptr, proc, data) ((proc)(data))
#define fftw_thread_wait(tid) (0) /* do nothing */

#define FFTW_USING_COMPILER_THREADS 1

/************************** POSIX Threads ****************************/

#else /* use the default, POSIX threads: */

/* POSIX threads glue.  Tested. */

#ifndef FFTW_USING_POSIX_THREADS
#define FFTW_USING_POSIX_THREADS
#endif

/* link with -lpthread */

#include <pthread.h>

/* Thread entry point: */
typedef void * (*fftw_thread_function) (void *);

extern pthread_attr_t *fftw_pthread_attributes_p;

typedef pthread_t fftw_thread_id;

#define fftw_thread_spawn(tid_ptr, proc, data) { \
     if (pthread_create(tid_ptr,fftw_pthread_attributes_p,proc,data)) \
	  fftw_die("error in pthread_create"); \
}

#define fftw_thread_wait(tid) { \
     if (pthread_join(tid,0)) \
	  fftw_die("error in pthread_join"); \
}

#endif

/************************ Function prototypes ***********************/

/* Use alloca instead of malloc, if possible, in the hope that alloca
   will be faster at allocating the small blocks we need.  (In principle,
   alloca just needs to increment the stack pointer.) */
#ifdef HAVE_ALLOCA
#     define ALLOCA(n) alloca(n)
#     define ALLOCA_CLEANUP(p) ;
#else
#     define ALLOCA(n) fftw_malloc(n)
#     define ALLOCA_CLEANUP(p) fftw_free(p);
#endif

typedef struct {
     int min, max, thread_num;
     void *data;
} fftw_loop_data;

typedef void *(*fftw_loop_function) (fftw_loop_data *);

extern void fftw_thread_spawn_loop(int loopmax, int nthreads,
				   fftw_loop_function proc, void *data);

extern void fftw_executor_many_inplace_threads(int n, fftw_complex *in,
					       fftw_complex *work,
					       fftw_plan_node *p,
					       int istride,
					       int howmany, int idist,
					       int nthreads);

#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */

#endif /* FFTW_THREADS_INT_H */