/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2006 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2006 Los Alamos National Security, LLC. All rights * reserved. * * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ /** * @file * * Progress engine for Open MPI */ #ifndef OPAL_RUNTIME_OPAL_PROGRESS_H #define OPAL_RUNTIME_OPAL_PROGRESS_H #if defined(c_plusplus) || defined(__cplusplus) extern "C" { #endif #include "opal_config.h" #include "opal/threads/mutex.h" /** * Initialize the progress engine * * Initialize the progress engine, including constructing the * proper locks and allocating space for the progress registration * functions. At this point, any function in the progress engine * interface may be called. */ OPAL_DECLSPEC int opal_progress_init(void); /** * Shut down the progress engine * * Shut down the progress engine. This includes deregistering all * registered callbacks and freeing all resources. After finalize * returns, no calls into the progress interface are allowed. */ OPAL_DECLSPEC int opal_progress_finalize(void); /** * Progress all pending events * * Progress all pending events. All registered event handlers will be * called every call into opal_progress(). The event library will be * called if opal_progress_event_users is greater than 0 (adjustments * can be made by calling opal_progress_event_users_add() and * opal_progress_event_users_delete()) or the time since the last call * into the event library is greater than the progress tick rate (by * default, 10ms). */ OPAL_DECLSPEC void opal_progress(void); /** * Control how the event library is called * * Adjust the flags argument used to call opal_event_loop() from * opal_progress(). The default argument is OPAL_EVLOOP_ONELOOP, * meaning that the call to opal_event_loop() will block pending * events, but may block for a period of time. * * @param flags One of the valid vlags argument to * opal_event_loop(). * @return Previous value of flags used to call * opal_event_loop(). */ OPAL_DECLSPEC int opal_progress_set_event_flag(int flags); /** * Increase the number of users of the event library * * Increase the number of users of the event library. This count is * used by opal_progress to determine if opal_event_loop() should be * called every call to opal_progress() or only after a time has * elapsed since the last call (by default, 10ms). The count defaults * to 0, meaning that opal_progress_event_users_increment() must be * called at least once for the event loop to be called on every entry * to opal_progress(). * */ OPAL_DECLSPEC void opal_progress_event_users_increment(void); /** * Decrease the number of users of the event library * * Decrease the number of users of the event library. This count is * used by opal_progress to determine if opal_event_loop() should be * called every call to opal_progress() or only after a time has * elapsed since the last call (by default, 10ms). */ OPAL_DECLSPEC void opal_progress_event_users_decrement(void); /** * Set whether opal_progress() should yield when idle * * Set whether opal_progress() should yield the processor (either by * sched_yield() or SwitchToThread()) if no events were progressed * during the progress loop. The return value of the callback * functions is used to determine whether or not yielding is required. * By default, the event loop will yield when the progress function is * idle. * * @param yieldopt Whether to yield when idle. * @return Previous value of the yield_when_idle option. */ OPAL_DECLSPEC bool opal_progress_set_yield_when_idle(bool yieldopt); /** * Set time between calls into the event library * * Set time between calls into the event library when there are no * users of the event library (set by * opal_progress_event_users_increment() and * opal_progress_event_users_decrement()). * * @param polltime Time (in microseconds) between calls to the event * library */ OPAL_DECLSPEC void opal_progress_set_event_poll_rate(int microseconds); /** * Progress callback function typedef * * Prototype for the a progress function callback. Progress function * callbacks can be registered with opal_progress_register() and * deregistered with opal_progress_deregister(). It should be noted * that either registering or deregistering a function callback is an * extraordinarily expensive operation and should not be used for * potentially short callback lifetimes. * * @return Number of events progressed during the callback */ typedef int (*opal_progress_callback_t)(void); /** * Register an event to be progressed * * Register an event to be progressed during calls to opal_progress(). * Please read the note in opal_progress_callback_t. */ OPAL_DECLSPEC int opal_progress_register(opal_progress_callback_t cb); /** * Deregister previously registered event * * Deregister an event to be progressed during calls to opal_progress(). * Please read the note in opal_progress_callback_t. */ OPAL_DECLSPEC int opal_progress_unregister(opal_progress_callback_t cb); OPAL_DECLSPEC extern volatile int32_t opal_progress_thread_count; OPAL_DECLSPEC extern int opal_progress_spin_count; static inline bool opal_progress_threads(void) { return (opal_progress_thread_count > 0); } /** * Progress until flag is true or poll iterations completed */ static inline bool opal_progress_spin(volatile bool* complete) { int32_t c; OPAL_THREAD_ADD32(&opal_progress_thread_count,1); for (c = 0; c < opal_progress_spin_count; c++) { if (true == *complete) { OPAL_THREAD_ADD32(&opal_progress_thread_count,-1); return true; } opal_progress(); } OPAL_THREAD_ADD32(&opal_progress_thread_count,-1); return false; } /** * \internal * Don't use this variable; use the opal_progress_recursion_depth() * function. */ OPAL_DECLSPEC extern #if OPAL_HAVE_THREAD_SUPPORT volatile #endif uint32_t opal_progress_recursion_depth_counter; /** * Return the current level of recursion -- 0 means that we are not * under an opal_progress() call at all. 1 means that you're in the * top-level opal_progress() function (i.e., not deep in recursion). * Higher values mean that you're that many levels deep in recursion. */ static inline uint32_t opal_progress_recursion_depth(void) { return opal_progress_recursion_depth_counter; } #if defined(c_plusplus) || defined(__cplusplus) } #endif #endif