00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #if 0
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <stdio.h>
00032
00033
00034
00035
00036 #if defined(__linux)
00037 #if defined(VMDTHR_COMPAT_GLIBC232)
00038 #include <gnu/libc-version.h>
00039 #endif
00040 #define _GNU_SOURCE 1
00041 #endif
00042
00043 #include "VMDThreads.h"
00044
00045 #ifdef _MSC_VER
00046 #include <windows.h>
00047 #include <winbase.h>
00048 #endif
00049
00050
00051 #if defined(__sun) || defined(__linux) || defined(__irix) || defined(_CRAY) || defined(__osf__) || defined(_AIX)
00052 #include<unistd.h>
00053 #endif
00054
00055 #if defined(__APPLE__) && defined(VMDTHREADS)
00056 #include <Carbon/Carbon.h>
00057 #endif
00058
00059 #if defined(__hpux)
00060 #include <sys/mpctl.h>
00061 #endif
00062
00063
00064 #ifdef __cplusplus
00065 extern "C" {
00066 #endif
00067
00068
00069 int vmd_thread_numphysprocessors(void) {
00070 int a=1;
00071
00072 #ifdef VMDTHREADS
00073 #if defined(__APPLE__)
00074 a = MPProcessorsScheduled();
00075 #endif
00076
00077 #ifdef _MSC_VER
00078 struct _SYSTEM_INFO sysinfo;
00079 GetSystemInfo(&sysinfo);
00080 a = sysinfo.dwNumberOfProcessors;
00081 #endif
00082
00083 #if defined(_CRAY)
00084 a = sysconf(_SC_CRAY_NCPU);
00085 #endif
00086
00087 #if defined(__sun) || defined(__linux) || defined(__osf__) || defined(_AIX)
00088 a = sysconf(_SC_NPROCESSORS_ONLN);
00089 #endif
00090
00091 #if defined(__irix)
00092 a = sysconf(_SC_NPROC_ONLN);
00093 #endif
00094
00095 #if defined(__hpux)
00096 a = mpctl(MPC_GETNUMSPUS, 0, 0);
00097 #endif
00098 #endif
00099
00100 return a;
00101 }
00102
00103 int vmd_thread_numprocessors(void) {
00104 int a=1;
00105
00106 #ifdef VMDTHREADS
00107
00108
00109 char *forcecount = getenv("VMDFORCECPUCOUNT");
00110 if (forcecount != NULL) {
00111 if (sscanf(forcecount, "%d", &a) == 1) {
00112 return a;
00113 } else {
00114 a=1;
00115 }
00116 }
00117
00118
00119 a = vmd_thread_numphysprocessors();
00120
00121
00122
00123
00124 #endif
00125
00126 return a;
00127 }
00128
00129 #if defined(__linux) && defined(VMDTHR_COMPAT_GLIBC232)
00130 int glib232compat_getaffinity(pid_t pid,
00131 unsigned int cpusetsize,
00132 cpu_set_t* mask,
00133 int (*p)(pid_t,cpu_set_t*)) {
00134 typedef int(*pt2Func)(pid_t,unsigned int,cpu_set_t*);
00135 if (strncmp(gnu_get_libc_version(),"2.3.2",6) == 0){
00136 return (*p)(pid,mask);
00137 }
00138 return ((pt2Func)(*p))(pid,cpusetsize,mask);
00139 }
00140
00141 int glib232compat_setaffinity(pid_t pid,
00142 unsigned int cpusetsize,
00143 cpu_set_t* mask,
00144 int (*p)(pid_t,const cpu_set_t*)) {
00145 typedef int(*pt2Func)(pid_t,unsigned int,cpu_set_t*);
00146 if(strncmp(gnu_get_libc_version(),"2.3.2",6) == 0){
00147 return (*p)(pid,mask);
00148 }
00149 return ((pt2Func)(*p))(pid,cpusetsize,mask);
00150 }
00151 #endif
00152
00153
00154
00155 int * vmd_cpu_affinitylist(int *cpuaffinitycount) {
00156 int *affinitylist = NULL;
00157 *cpuaffinitycount = -1;
00158
00159
00160
00161 #if 0 && defined(_MSC_VER)
00162 HANDLE myproc = GetCurrentProcess();
00163 DWORD affinitymask, sysaffinitymask;
00164
00165 if (!GetProcessAffinityMask(myproc, &affinitymask, &sysaffinitymask)) {
00166
00167 int affinitycount=0;
00168 int i;
00169 for (i=0; i<31; i++) {
00170 affinitycount += (affinitymask >> i) & 0x1;
00171 }
00172
00173
00174 if (affinitycount > 0) {
00175 affinitylist = (int *) malloc(affinitycount * sizeof(int));
00176 if (affinitylist == NULL)
00177 return NULL;
00178
00179 int curcount = 0;
00180 for (i=0; i<CPU_SETSIZE; i++) {
00181 if (CPU_ISSET(i, &affinitymask)) {
00182 affinitylist[curcount] = i;
00183 curcount++;
00184 }
00185 }
00186 }
00187
00188 *cpuaffinitycount = affinitycount;
00189 }
00190 #endif
00191
00192
00193 #if defined(__linux)
00194
00195
00196 #if defined(CPU_SETSIZE)
00197 int i;
00198 cpu_set_t affinitymask;
00199 int affinitycount=0;
00200
00201 #if defined(VMDTHR_COMPAT_GLIBC232)
00202 typedef int(*pt2Func)(pid_t,cpu_set_t*);
00203
00204 if (glib232compat_getaffinity(0, sizeof(affinitymask), &affinitymask,(pt2Func)&sched_getaffinity) < 0) {
00205 #else
00206
00207 if (sched_getaffinity(0, sizeof(affinitymask), &affinitymask) < 0) {
00208 #endif
00209 perror("vmd_cpu_affinitylist: sched_getaffinity");
00210 return NULL;
00211 }
00212
00213
00214 for (i=0; i<CPU_SETSIZE; i++) {
00215 affinitycount += CPU_ISSET(i, &affinitymask);
00216 }
00217
00218
00219 if (affinitycount > 0) {
00220 affinitylist = (int *) malloc(affinitycount * sizeof(int));
00221 if (affinitylist == NULL)
00222 return NULL;
00223
00224 int curcount = 0;
00225 for (i=0; i<CPU_SETSIZE; i++) {
00226 if (CPU_ISSET(i, &affinitymask)) {
00227 affinitylist[curcount] = i;
00228 curcount++;
00229 }
00230 }
00231 }
00232
00233 *cpuaffinitycount = affinitycount;
00234 #endif
00235 #endif
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 return affinitylist;
00247 }
00248
00249
00250 int vmd_thread_set_self_cpuaffinity(int cpu) {
00251 int status=-1;
00252
00253 #ifdef VMDTHREADS
00254
00255 #if defined(__linux)
00256 #if 0
00257
00258
00259
00260 cpu_set_t affinitymask;
00261 CPU_ZERO(&affinitymask);
00262 CPU_SET(cpu, &affinitymask);
00263 status = pthread_setaffinity_np(pthread_self(), sizeof(affinitymask), &affinitymask);
00264 #else
00265
00266 cpu_set_t affinitymask;
00267 CPU_ZERO(&affinitymask);
00268 CPU_SET(cpu, &affinitymask);
00269
00270 #if defined(VMDTHR_COMPAT_GLIBC232)
00271 typedef int(*pt2Func)(pid_t,const cpu_set_t*);
00272
00273 if ((status=glib232compat_setaffinity(0,sizeof(affinitymask),&affinitymask,(pt2Func)&sched_setaffinity)) < 0) {
00274 #else
00275
00276 if ((status=sched_setaffinity(0, sizeof(affinitymask), &affinitymask)) < 0) {
00277 #endif
00278 perror("vmd_thread_set_self_cpuaffinitylist: sched_setaffinity");
00279 return status;
00280 }
00281 #endif
00282
00283
00284 sched_yield();
00285 #endif
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 #endif
00296
00297 return status;
00298 }
00299
00300
00301 int vmd_thread_setconcurrency(int nthr) {
00302 int status=0;
00303
00304 #ifdef VMDTHREADS
00305 #if defined(__sun)
00306 #ifdef USEPOSIXTHREADS
00307 status = pthread_setconcurrency(nthr);
00308 #else
00309 status = thr_setconcurrency(nthr);
00310 #endif
00311 #endif
00312
00313 #if defined(__irix) || defined(_AIX)
00314 status = pthread_setconcurrency(nthr);
00315 #endif
00316 #endif
00317
00318 return status;
00319 }
00320
00321
00322
00323
00324 #ifdef __cplusplus
00325 extern "C" {
00326 #endif
00327 typedef void * (*VMDTHREAD_START_ROUTINE)(void *);
00328 #ifdef __cplusplus
00329 }
00330 #endif
00331
00332 int vmd_thread_create(vmd_thread_t * thr, void * fctn(void *), void * arg) {
00333 int status=0;
00334
00335 #ifdef VMDTHREADS
00336 #ifdef _MSC_VER
00337 DWORD tid;
00338 *thr = CreateThread(NULL, 8192, (LPTHREAD_START_ROUTINE) fctn, arg, 0, &tid);
00339 if (*thr == NULL) {
00340 status = -1;
00341 }
00342 #endif
00343
00344 #ifdef USEPOSIXTHREADS
00345 #if defined(_AIX)
00346 {
00347 pthread_attr_t attr;
00348 pthread_attr_init(&attr);
00349 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
00350 status = pthread_create(thr, &attr, fctn, arg);
00351 pthread_attr_destroy(&attr);
00352 }
00353 #else
00354 status = pthread_create(thr, NULL, (VMDTHREAD_START_ROUTINE)fctn, arg);
00355 #endif
00356 #endif
00357 #endif
00358
00359 return status;
00360 }
00361
00362
00363 int vmd_thread_join(vmd_thread_t thr, void ** stat) {
00364 int status=0;
00365
00366 #ifdef VMDTHREADS
00367 #ifdef _MSC_VER
00368 DWORD wstatus = 0;
00369
00370 wstatus = WAIT_TIMEOUT;
00371
00372 while (wstatus != WAIT_OBJECT_0) {
00373 wstatus = WaitForSingleObject(thr, INFINITE);
00374 }
00375 #endif
00376
00377 #ifdef USEPOSIXTHREADS
00378 status = pthread_join(thr, stat);
00379 #endif
00380 #endif
00381
00382 return status;
00383 }
00384
00385
00386 int vmd_mutex_init(vmd_mutex_t * mp) {
00387 int status=0;
00388
00389 #ifdef VMDTHREADS
00390 #ifdef _MSC_VER
00391 InitializeCriticalSection(mp);
00392 #endif
00393
00394 #ifdef USEPOSIXTHREADS
00395 status = pthread_mutex_init(mp, 0);
00396 #endif
00397 #endif
00398
00399 return status;
00400 }
00401
00402
00403 int vmd_mutex_lock(vmd_mutex_t * mp) {
00404 int status=0;
00405
00406 #ifdef VMDTHREADS
00407 #ifdef _MSC_VER
00408 EnterCriticalSection(mp);
00409 #endif
00410
00411 #ifdef USEPOSIXTHREADS
00412 status = pthread_mutex_lock(mp);
00413 #endif
00414 #endif
00415
00416 return status;
00417 }
00418
00419
00420 int vmd_mutex_unlock(vmd_mutex_t * mp) {
00421 int status=0;
00422
00423 #ifdef VMDTHREADS
00424 #ifdef _MSC_VER
00425 LeaveCriticalSection(mp);
00426 #endif
00427
00428 #ifdef USEPOSIXTHREADS
00429 status = pthread_mutex_unlock(mp);
00430 #endif
00431 #endif
00432
00433 return status;
00434 }
00435
00436
00437 int vmd_mutex_destroy(vmd_mutex_t * mp) {
00438 int status=0;
00439
00440 #ifdef VMDTHREADS
00441 #ifdef _MSC_VER
00442 DeleteCriticalSection(mp);
00443 #endif
00444
00445 #ifdef USEPOSIXTHREADS
00446 status = pthread_mutex_destroy(mp);
00447 #endif
00448 #endif
00449
00450 return status;
00451 }
00452
00453
00454
00455 int vmd_cond_init(vmd_cond_t * cvp) {
00456 int status=0;
00457
00458 #ifdef VMDTHREADS
00459 #ifdef _MSC_VER
00460 #if defined(VMDUSEWIN2008CONDVARS)
00461 InitializeConditionVariable(cvp);
00462 #else
00463
00464 cvp->waiters = 0;
00465
00466
00467 cvp->events[VMD_COND_SIGNAL] = CreateEvent(NULL,
00468 FALSE,
00469 FALSE,
00470 NULL);
00471
00472
00473 cvp->events[VMD_COND_BROADCAST] = CreateEvent(NULL,
00474 TRUE,
00475 FALSE,
00476 NULL);
00477 #endif
00478 #endif
00479
00480 #ifdef USEPOSIXTHREADS
00481 status = pthread_cond_init(cvp, NULL);
00482 #endif
00483 #endif
00484
00485 return status;
00486 }
00487
00488 int vmd_cond_destroy(vmd_cond_t * cvp) {
00489 int status=0;
00490
00491 #ifdef VMDTHREADS
00492 #ifdef _MSC_VER
00493 #if defined(VMDUSEWIN2008CONDVARS)
00494
00495 #else
00496 CloseHandle(cvp->events[VMD_COND_SIGNAL]);
00497 CloseHandle(cvp->events[VMD_COND_BROADCAST]);
00498 #endif
00499 #endif
00500
00501 #ifdef USEPOSIXTHREADS
00502 status = pthread_cond_destroy(cvp);
00503 #endif
00504 #endif
00505
00506 return status;
00507 }
00508
00509 int vmd_cond_wait(vmd_cond_t * cvp, vmd_mutex_t * mp) {
00510 int status=0;
00511
00512 #ifdef VMDTHREADS
00513 #ifdef _MSC_VER
00514 #if defined(VMDUSEWIN2008CONDVARS)
00515 SleepConditionVariableCS(cvp, mp, INFINITE)
00516 #else
00517 #if !defined(VMDUSEINTERLOCKEDATOMICOPS)
00518 EnterCriticalSection(&cvp->waiters_lock);
00519 cvp->waiters++;
00520 LeaveCriticalSection(&cvp->waiters_lock);
00521 #else
00522 InterlockedIncrement(&cvp->waiters);
00523 #endif
00524
00525 LeaveCriticalSection(mp);
00526
00527
00528 int result = WaitForMultipleObjects(2, cvp->events, FALSE, INFINITE);
00529
00530 #if !defined(VMDUSEINTERLOCKEDATOMICOPS)
00531 EnterCriticalSection (&cvp->waiters_lock);
00532 cvp->waiters--;
00533 LONG last_waiter =
00534 ((result == (WAIT_OBJECT_0 + VMD_COND_BROADCAST)) && cvp->waiters == 0);
00535 LeaveCriticalSection (&cvp->waiters_lock);
00536 #else
00537 LONG my_waiter = InterlockedDecrement(&cvp->waiters);
00538 LONG last_waiter =
00539 ((result == (WAIT_OBJECT_0 + VMD_COND_BROADCAST)) && my_waiter == 0);
00540 #endif
00541
00542
00543 if (last_waiter)
00544
00545
00546 ResetEvent(cvp->events[VMD_COND_BROADCAST]);
00547
00548 EnterCriticalSection(mp);
00549 #endif
00550 #endif
00551
00552 #ifdef USEPOSIXTHREADS
00553 status = pthread_cond_wait(cvp, mp);
00554 #endif
00555 #endif
00556
00557 return status;
00558 }
00559
00560 int vmd_cond_signal(vmd_cond_t * cvp) {
00561 int status=0;
00562
00563 #ifdef VMDTHREADS
00564 #ifdef _MSC_VER
00565 #if defined(VMDUSEWIN2008CONDVARS)
00566 WakeConditionVariable(cvp);
00567 #else
00568 #if !defined(VMDUSEINTERLOCKEDATOMICOPS)
00569 EnterCriticalSection(&cvp->waiters_lock);
00570 int have_waiters = (cvp->waiters > 0);
00571 LeaveCriticalSection(&cvp->waiters_lock);
00572 if (have_waiters)
00573 SetEvent (cvp->events[VMD_COND_SIGNAL]);
00574 #else
00575 if (InterlockedExchangeAdd(&cvp->waiters, 0) > 0)
00576 SetEvent(cvp->events[VMD_COND_SIGNAL]);
00577 #endif
00578 #endif
00579 #endif
00580
00581 #ifdef USEPOSIXTHREADS
00582 status = pthread_cond_signal(cvp);
00583 #endif
00584 #endif
00585
00586 return status;
00587 }
00588
00589 int vmd_cond_broadcast(vmd_cond_t * cvp) {
00590 int status=0;
00591
00592 #ifdef VMDTHREADS
00593 #ifdef _MSC_VER
00594 #if defined(VMDUSEWIN2008CONDVARS)
00595 WakeAllConditionVariable(cvp);
00596 #else
00597 #if !defined(VMDUSEINTERLOCKEDATOMICOPS)
00598 EnterCriticalSection(&cvp->waiters_lock);
00599 int have_waiters = (cvp->waiters > 0);
00600 LeaveCriticalSection(&cvp->waiters_lock);
00601 if (have_waiters)
00602 SetEvent(cvp->events[VMD_COND_BROADCAST]);
00603 #else
00604 if (InterlockedExchangeAdd(&cvp->waiters, 0) > 0)
00605 SetEvent(cvp->events[VMD_COND_BROADCAST]);
00606 #endif
00607
00608 #endif
00609 #endif
00610
00611 #ifdef USEPOSIXTHREADS
00612 status = pthread_cond_broadcast(cvp);
00613 #endif
00614 #endif
00615
00616 return status;
00617 }
00618
00619
00620
00621 #if !defined(VMDTHREADS)
00622
00623 int vmd_thread_barrier_init_proc_shared(vmd_barrier_t *barrier, int n_clients) {
00624 return 0;
00625 }
00626
00627 void vmd_thread_barrier_destroy(vmd_barrier_t *barrier) {
00628 }
00629
00630 int vmd_thread_barrier(vmd_barrier_t *barrier, int increment) {
00631 return 0;
00632 }
00633
00634 #else
00635
00636 #ifdef USEPOSIXTHREADS
00637
00638
00639
00640
00641
00642
00643
00644 int vmd_thread_barrier_init_proc_shared(vmd_barrier_t *barrier, int n_clients) {
00645 if (barrier != NULL) {
00646 barrier->n_clients = n_clients;
00647 barrier->n_waiting = 0;
00648 barrier->phase = 0;
00649 barrier->sum = 0;
00650
00651 pthread_mutexattr_t mattr;
00652 pthread_condattr_t cattr;
00653
00654 printf("Setting barriers to have system scope...\n");
00655
00656 pthread_mutexattr_init(&mattr);
00657 if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED) != 0) {
00658 printf("WARNING: could not set mutex to process shared scope\n");
00659 }
00660
00661 pthread_condattr_init(&cattr);
00662 if (pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED) != 0) {
00663 printf("WARNING: could not set mutex to process shared scope\n");
00664 }
00665
00666 pthread_mutex_init(&barrier->lock, &mattr);
00667 pthread_cond_init(&barrier->wait_cv, &cattr);
00668
00669 pthread_condattr_destroy(&cattr);
00670 pthread_mutexattr_destroy(&mattr);
00671 }
00672
00673 return 0;
00674 }
00675
00676 void vmd_thread_barrier_destroy(vmd_barrier_t *barrier) {
00677 pthread_mutex_destroy(&barrier->lock);
00678 pthread_cond_destroy(&barrier->wait_cv);
00679 }
00680
00681 int vmd_thread_barrier(vmd_barrier_t *barrier, int increment) {
00682 int my_phase;
00683 int my_result;
00684
00685 pthread_mutex_lock(&barrier->lock);
00686 my_phase = barrier->phase;
00687 barrier->sum += increment;
00688 barrier->n_waiting++;
00689
00690 if (barrier->n_waiting == barrier->n_clients) {
00691 barrier->result = barrier->sum;
00692 barrier->sum = 0;
00693 barrier->n_waiting = 0;
00694 barrier->phase = 1 - my_phase;
00695 pthread_cond_broadcast(&barrier->wait_cv);
00696 }
00697
00698 while (barrier->phase == my_phase) {
00699 pthread_cond_wait(&barrier->wait_cv, &barrier->lock);
00700 }
00701
00702 my_result = barrier->result;
00703
00704 pthread_mutex_unlock(&barrier->lock);
00705
00706 return my_result;
00707 }
00708
00709 #endif
00710
00711 #endif
00712
00713 #ifdef __cplusplus
00714 }
00715 #endif
00716
00717 #endif