/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * 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-2014 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2018 Triad National Security, LLC. All rights * reserved. * * Copyright (c) 2020 Intel, Inc. 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 BEGIN_C_DECLS #include "opal_config.h" #include "opal/mca/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); /** * 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). * * Returns 0 if no progress has been observed, non-zero otherwise. */ OPAL_DECLSPEC int 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_NONBLOCK | OPAL_EVLOOP_ONCE * * OPAL_EVLOOP_NONBLOCK means that if there is no active events, * opal_event_loop() should return immediately (instead of * waiting for active events). * * OPAL_EVLOOP_ONCE means opal_event_loop() should onlyrun one * iteration, which includes poll the event queue and process * the active events. * * @param flags One of the valid flags 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); OPAL_DECLSPEC int opal_progress_register_lp(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); #if OPAL_ENABLE_DEBUG OPAL_DECLSPEC extern bool opal_progress_debug; #endif OPAL_DECLSPEC extern int opal_progress_spin_count; /* do we want to call sched_yield() if nothing happened */ OPAL_DECLSPEC extern bool opal_progress_yield_when_idle; /** * Progress until flag is true or poll iterations completed */ static inline bool opal_progress_spin(volatile bool *complete) { int32_t c; for (c = 0; c < opal_progress_spin_count; c++) { if (true == *complete) { return true; } opal_progress(); } return false; } END_C_DECLS #endif