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