BRL-CAD
|
Cross platform API for parallel processing, handling issues like threads and semaphores. More...
Modules | |
Multithreading | |
Single Instruction Multiple Data | |
Single Instruction Multiple Data support. | |
Macros | |
#define | MAX_PSW 1024 |
#define | BU_SEMAPHORE_DEFINE(x) x = bu_semaphore_register(CPP_STR(x)) |
#define | BU_SETJUMP setjmp((bu_setjmp_valid[bu_parallel_id()]=1, bu_jmpbuf[bu_parallel_id()])) |
#define | BU_UNSETJUMP (bu_setjmp_valid[bu_parallel_id()]=0) |
Functions | |
DEPRECATED int | bu_is_parallel (void) |
subroutine to determine if we are multi-threaded More... | |
int | bu_parallel_id (void) |
int | bu_thread_id (void) |
void | bu_nice_set (int newnice) |
routines for parallel processing More... | |
size_t | bu_avail_cpus (void) |
void | bu_parallel (void(*func)(int func_cpu_id, void *func_data), size_t ncpu, void *data) |
int | bu_semaphore_register (const char *name) |
semaphore implementation More... | |
void | bu_semaphore_init (unsigned int nsemaphores) |
void | bu_semaphore_free (void) |
void | bu_semaphore_acquire (unsigned int i) |
void | bu_semaphore_release (unsigned int i) |
Variables | |
int | BU_SEM_GENERAL |
int | BU_SEM_SYSCALL |
int | BU_SEM_MAPPEDFILE |
int | bu_setjmp_valid [MAX_PSW] |
jmp_buf | bu_jmpbuf [MAX_PSW] |
Cross platform API for parallel processing, handling issues like threads and semaphores.
Thread based parallelism routines.
#define MAX_PSW 1024 |
MAX_PSW - The maximum number of processors that can be expected on this hardware. Used to allocate application-specific per-processor tables at compile-time and represent a hard limit on the number of processors/threads that may be spawned. The actual number of available processors is found at runtime by calling bu_avail_cpus()
Definition at line 45 of file parallel.h.
#define BU_SEMAPHORE_DEFINE | ( | x | ) | x = bu_semaphore_register(CPP_STR(x)) |
emaphores available for both library and application use.
Definition at line 213 of file parallel.h.
#define BU_SETJUMP setjmp((bu_setjmp_valid[bu_parallel_id()]=1, bu_jmpbuf[bu_parallel_id()])) |
Definition at line 244 of file parallel.h.
#define BU_UNSETJUMP (bu_setjmp_valid[bu_parallel_id()]=0) |
Definition at line 245 of file parallel.h.
DEPRECATED int bu_is_parallel | ( | void | ) |
subroutine to determine if we are multi-threaded
This subroutine is separated off from parallel.c so that bu_bomb() and others can call it, without causing either parallel.c or semaphore.c to get referenced and thus causing the loader to drag in all the parallel processing stuff from the vendor library. This routine is DEPRECATED, do not use it. If you need a means to determine when an application is running bu_parallel(), please report this to our developers.
Previously, this was a library-stateful way for bu_bomb() to tell if a parallel application is running. This routine now simply returns zero all the time, which permits BU_SETJUMP() error handling during bu_bomb().
int bu_parallel_id | ( | void | ) |
Returns the CPU number of the current bu_parallel() invoked thread.
This routine is intended for indexing into per-cpu memory buffers. Values will be any number in the range of 0 to MAX_PSW. They are not guaranteed to be in any range except for non-parallel applications which will have ID 0 for the main process's thread.
int bu_thread_id | ( | void | ) |
Returns the OS thread ID of the calling thread.
This routine is intended for diagnostic and unique ID purposes, not for indexing into per-cpu memory buffers as values can be anything.
void bu_nice_set | ( | int | newnice | ) |
routines for parallel processing
Machine-specific routines for portable parallel processing. Without knowing what the current UNIX "nice" value is, change to a new absolute "nice" value. (The system routine makes a relative change).
size_t bu_avail_cpus | ( | void | ) |
Return the maximum number of physical CPUs that are considered to be available to this process now.
void bu_parallel | ( | void(*)(int func_cpu_id, void *func_data) | func, |
size_t | ncpu, | ||
void * | data | ||
) |
Create parallel threads of execution.
This function creates (at most) 'ncpu' copies of function 'func' all running in parallel, passing 'data' to each invocation. Specifying ncpu=0 will specify automatic parallelization, invoking parallel threads as cores become available. This is particularly useful during recursive invocations where the ncpu core count is limited by the parent context.
Locking and work dispatching are handled by 'func' using a "self-dispatching" paradigm. This means you must manually protect shared data structures, e.g., via bu_semaphore_acquire().
Lock-free execution is typically possible by creating data containers with MAX_PSW elements as bu_parallel will never execute more than that many threads. Calling bu_parallel_id() provides the id of the current thread, which can be used as an index into a MAX_PSW per-cpu array. The id is also passed as the func_cpu_id parameter to the bu_parallel callback function.
All invocations of the specified 'func' callback function are passed two parameters: 1) it's assigned thread number and 2) a shared 'data' pointer for application use. Threads are assigned increasing numbers, starting with zero. Processes may also call bu_parallel_id() to obtain their thread number.
Threads created with bu_parallel() may specify utilization of affinity locking to keep threads on a given physical CPU core. This behavior can be enabled at runtime by setting the environment variable LIBBU_AFFINITY=1. Note that this option may increase or even decrease performance, particularly on platforms with advanced scheduling, so testing is recommended.
This function will not return control until all invocations of the subroutine are finished.
In following is a working stand-alone example demonstrating how to call the bu_parallel() interface.
int bu_semaphore_register | ( | const char * | name | ) |
semaphore implementation
Machine-specific routines for parallel processing. Primarily for handling semaphores to protect critical sections of code.
The new paradigm: semaphores are referred to, not by a pointer, but by a small integer. This module is now responsible for obtaining whatever storage is needed to implement each semaphore.
Note that these routines can't use bu_log() for error logging, because bu_log() acquires semaphore #0 (BU_SEM_SYSCALL).
void bu_semaphore_init | ( | unsigned int | nsemaphores | ) |
Prepare 'nsemaphores' independent critical section semaphores. Die on error.
Takes the place of 'n' separate calls to old RES_INIT(). Start by allocating array of "struct bu_semaphores", which has been arranged to contain whatever this system needs.
void bu_semaphore_free | ( | void | ) |
Release all initialized semaphores and any associated memory.
void bu_semaphore_acquire | ( | unsigned int | i | ) |
void bu_semaphore_release | ( | unsigned int | i | ) |
|
extern |
This semaphore is intended for short-lived protection.
It is provided for both library and application use, code that doesn't call into a BRL-CAD library.
|
extern |
This semaphore is intended to protect general system calls.
It is provided for both library and application use, code that doesn't call into a BRL-CAD library.
|
extern |
|
extern |
|
extern |