00001
00052
00053 #include "basics.h"
00054
00055 #ifndef TBCI_SMP_H
00056 #define TBCI_SMP_H
00057
00058
00059
00060
00061
00062 #if defined(SMP) && defined(HAVE_PTHREADS)
00063
00064
00065
00066 #include <signal.h>
00067 #ifndef HAVE_NO_NEW_HEADERS_BUG
00068 # include <cstdlib>
00069 # include <cstdarg>
00070 #else
00071 # include <stdlib.h>
00072 # include <stdarg.h>
00073 #endif
00074 #include <sys/types.h>
00075
00076
00077 #define __need_sigset_t
00078 #ifdef BUGGY_PTHREAD
00079 # include <sigset.h>
00080 typedef __sigset_t sigset_t;
00081 #endif
00082
00083 #undef _POSIX_C_SOURCE
00084 #define _POSIX_C_SOURCE 200112L
00085 #include <pthread.h>
00086
00087 #ifndef CACHELINE_SZ
00088 # define CACHELINE_SZ 32
00089 #endif
00090
00091 NAMESPACE_TBCI
00092
00093 #ifdef __GNUC__
00094 # define smp_barrier() asm ("": : :"memory")
00095 #else
00096
00097 # define smp_barrier()
00098 #endif
00099
00100 extern pid_t main_thread_pid;
00101 #define MAIN_PID (main_thread_pid)
00102 extern bool bound_main;
00103 #endif
00104
00105 #if defined(NEED_SMP_DECLS) || defined(SMP)
00106 #ifdef HAVE_PTHREADS
00107 #include <pthread.h>
00108 #else
00109 #error NEED pthread.h if NEED_SMP_DECLS is set
00110 #endif
00111
00112 typedef void (*thr_job_t) (struct thr_ctrl*);
00113 typedef void* (*useful_job_t) (void*);
00114
00115 #define THREAD_MAX_ARGS 5
00116 #define THREAD_MAX_RES_LN 16
00117
00121 struct thr_ctrl {
00122
00123 pthread_mutex_t t_setup;
00124 pthread_cond_t t_setup_cond;
00125 thr_job_t t_job;
00126 unsigned long t_size;
00127 unsigned long t_off;
00128 void* t_par[THREAD_MAX_ARGS];
00129
00130 volatile int t_setup_done, t_done_done;
00131 pthread_mutex_t t_done;
00132 pthread_cond_t t_done_cond;
00133 long t_retval;
00134
00135
00136 union {
00137 volatile char t_res_dummy[16];
00138 LONG_DOUBLE t_res;
00139 long t_res_l;
00140 };
00141
00142 pid_t t_pid;
00143 int t_no;
00144 pthread_t t_id;
00145 } ALIGN(64);
00146 #endif
00147
00148 #if defined(SMP) && defined(HAVE_PTHREADS)
00149
00157 int init_threads (const int thr = 0);
00159 void free_threads ();
00161 int threads_avail (const int = 0);
00163 void disable_threads ();
00165 void reenable_threads ();
00176 void bind_threads (bool bind_main = false);
00177
00178
00182 void thread_start (const int thr_no, thr_job_t job, const unsigned long sz, ...);
00183 void thread_start_off (const int thr_no , thr_job_t job,
00184 const unsigned long offset, const unsigned long sz, ...);
00185 void thread_wait (const int);
00186 void* thread_wait_useful (const int, useful_job_t = 0, void* = 0);
00187
00188 LONG_DOUBLE thread_wait_result (const int);
00189
00190
00191 template <typename T>
00192 static inline unsigned long slice_offset(int thr, int no_thr, unsigned long dim, T* ptr){
00193 if (thr == no_thr)
00194 return dim;
00195 else if (thr == 0)
00196 return 0;
00197 BCHK(thr < 0 || thr > no_thr, NumErr, Illegal thread in slice_offset, thr, 0);
00198 const unsigned step = dim/no_thr;
00199 unsigned long offs = thr*dim/no_thr + (128/sizeof(T) > step-1? step-1: 128/sizeof(T));
00200 unsigned long misalign = (unsigned long)(ptr+offs)%64 / sizeof(T);
00201
00202
00203 return offs - misalign;
00204 }
00205
00206
00207
00208 extern int num_threads;
00209 extern struct thr_ctrl *threads;
00210 extern THREAD__ int ismainthread;
00211 extern THREAD__ int thrno;
00212 extern THREAD__ struct thr_ctrl *this_thread;
00213
00214
00215 typedef void cbackfn(void *ptr, const int thr);
00216 void thread_reg_callback(cbackfn ctor, cbackfn dtor, void *parm);
00217 void thread_dereg_callback(cbackfn ctor, cbackfn dtor, void *parm);
00218
00219 NAMESPACE_END
00220
00221 #if defined(SMP) && (!defined(_REENTRANT) && !defined(_THREAD_SAFE))
00222 # warning "Define _REENTRANT and/or _THREAD_SAFE for multithreaded (SMP) compilation!"
00223 #endif
00224
00225 #else
00226 # define MAIN_PID (getpid())
00227 # undef SMP
00228 # define num_threads (0)
00229 # define thrno (0)
00230 # define ismainthread (1)
00231 #endif
00232
00233 #endif