2004-11-22 00:37:56 +00:00
|
|
|
/*
|
2004-11-22 01:38:40 +00:00
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
|
|
|
* All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
|
|
|
|
* All rights reserved.
|
2004-11-28 20:09:25 +00:00
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
2005-03-24 12:43:37 +00:00
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
2004-11-22 01:38:40 +00:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
2004-11-22 00:37:56 +00:00
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
2004-10-20 01:03:09 +00:00
|
|
|
#include "ompi_config.h"
|
2005-03-14 20:57:21 +00:00
|
|
|
|
2005-01-20 00:03:23 +00:00
|
|
|
#ifdef HAVE_SCHED_H
|
2004-12-07 15:39:57 +00:00
|
|
|
#include <sched.h>
|
2005-01-20 00:03:23 +00:00
|
|
|
#endif
|
2005-03-14 20:57:21 +00:00
|
|
|
|
2004-04-06 16:32:40 +00:00
|
|
|
#include "event/event.h"
|
|
|
|
#include "mca/pml/pml.h"
|
2004-06-07 15:33:53 +00:00
|
|
|
#include "runtime/ompi_progress.h"
|
2005-03-14 20:57:21 +00:00
|
|
|
#include "include/constants.h"
|
2005-05-01 00:47:35 +00:00
|
|
|
#include "mca/errmgr/errmgr.h"
|
2005-04-14 18:55:53 +00:00
|
|
|
#include "mca/ns/ns.h"
|
|
|
|
#include "mca/gpr/gpr.h"
|
2005-05-01 00:53:00 +00:00
|
|
|
#include "mca/schema/schema.h"
|
2004-12-12 15:29:29 +00:00
|
|
|
|
2005-04-21 14:58:25 +00:00
|
|
|
/*
|
|
|
|
* default parameters
|
|
|
|
*/
|
2004-10-28 15:40:46 +00:00
|
|
|
static int ompi_progress_event_flag = OMPI_EVLOOP_ONCE;
|
2005-04-21 14:58:25 +00:00
|
|
|
static const int ompi_progress_default_tick_rate = 100;
|
2005-03-30 01:40:26 +00:00
|
|
|
|
2005-04-21 14:58:25 +00:00
|
|
|
/*
|
|
|
|
* Local variables
|
|
|
|
*/
|
2005-03-28 21:02:02 +00:00
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
2005-02-16 17:42:07 +00:00
|
|
|
static ompi_lock_t progress_lock;
|
2005-03-28 21:02:02 +00:00
|
|
|
#endif /* OMPI_HAVE_THREAD_SUPPORT */
|
2005-03-30 01:40:26 +00:00
|
|
|
|
2005-04-21 14:58:25 +00:00
|
|
|
/* callbacks to progress */
|
2005-03-14 20:57:21 +00:00
|
|
|
static ompi_progress_callback_t *callbacks = NULL;
|
|
|
|
static size_t callbacks_len = 0;
|
|
|
|
static size_t callbacks_size = 0;
|
2004-12-12 15:29:29 +00:00
|
|
|
|
2005-04-21 14:58:25 +00:00
|
|
|
/* do we want to call sched_yield() if nothing happened */
|
2005-03-30 01:40:26 +00:00
|
|
|
static int call_yield = 1;
|
|
|
|
|
2005-04-21 14:58:25 +00:00
|
|
|
/* current count down until we tick the event library */
|
2005-03-30 01:40:26 +00:00
|
|
|
static long event_progress_counter = 0;
|
2005-04-21 14:58:25 +00:00
|
|
|
/* reset value for counter when it hits 0 */
|
2005-03-30 01:40:26 +00:00
|
|
|
static long event_progress_counter_reset = 0;
|
2005-04-21 14:58:25 +00:00
|
|
|
/* users of the event library from MPI cause the tick rate to
|
|
|
|
be every time */
|
|
|
|
static int32_t event_num_mpi_users = 0;
|
2005-03-30 01:40:26 +00:00
|
|
|
|
|
|
|
|
2005-04-14 18:55:53 +00:00
|
|
|
static void
|
|
|
|
node_schedule_callback(orte_gpr_notify_data_t *notify_data, void *user_tag)
|
|
|
|
{
|
2005-05-01 00:47:35 +00:00
|
|
|
size_t proc_slots = 0;
|
|
|
|
size_t used_proc_slots = 0;
|
|
|
|
int param;
|
|
|
|
size_t i;
|
2005-04-14 18:55:53 +00:00
|
|
|
|
|
|
|
/* parse the response */
|
|
|
|
for(i = 0 ; i < notify_data->cnt ; i++) {
|
|
|
|
orte_gpr_value_t* value = notify_data->values[i];
|
2005-05-01 00:47:35 +00:00
|
|
|
size_t k;
|
2005-04-14 18:55:53 +00:00
|
|
|
|
|
|
|
for(k = 0 ; k < value->cnt ; k++) {
|
|
|
|
orte_gpr_keyval_t* keyval = value->keyvals[k];
|
|
|
|
if(strcmp(keyval->key, ORTE_NODE_SLOTS_KEY) == 0) {
|
2005-05-01 00:47:35 +00:00
|
|
|
proc_slots = keyval->value.size;
|
2005-04-14 18:55:53 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(strncmp(keyval->key, ORTE_NODE_SLOTS_ALLOC_KEY,
|
|
|
|
strlen(ORTE_NODE_SLOTS_ALLOC_KEY)) == 0) {
|
2005-05-01 00:47:35 +00:00
|
|
|
used_proc_slots += keyval->value.size;
|
2005-04-14 18:55:53 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
param = mca_base_param_find("mpi", NULL, "yield_when_idle");
|
|
|
|
mca_base_param_set_int(param, (used_proc_slots <= proc_slots) ? 0 : 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
register_node_schedule_callback(void)
|
|
|
|
{
|
|
|
|
orte_gpr_notify_id_t rctag;
|
|
|
|
orte_gpr_value_t trig, *trigs;
|
|
|
|
orte_gpr_subscription_t sub, *subs;
|
2005-05-01 00:53:00 +00:00
|
|
|
orte_jobid_t jobid;
|
2005-04-14 18:55:53 +00:00
|
|
|
int rc;
|
|
|
|
char **tokens;
|
2005-05-01 00:47:35 +00:00
|
|
|
size_t num_tokens;
|
2005-04-14 18:55:53 +00:00
|
|
|
char *my_name_string;
|
|
|
|
orte_cellid_t cellid;
|
|
|
|
|
|
|
|
/* query our node... */
|
|
|
|
rc = orte_ns.get_proc_name_string(&my_name_string,
|
|
|
|
orte_process_info.my_name);
|
2005-05-01 00:47:35 +00:00
|
|
|
if (ORTE_SUCCESS != rc) {
|
|
|
|
ORTE_ERROR_LOG(rc);
|
|
|
|
return rc;
|
|
|
|
}
|
2005-04-14 18:55:53 +00:00
|
|
|
|
|
|
|
rc = orte_ns.get_cellid(&cellid, orte_process_info.my_name);
|
2005-05-01 00:47:35 +00:00
|
|
|
if (ORTE_SUCCESS != rc) {
|
|
|
|
ORTE_ERROR_LOG(rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = orte_ns.get_jobid(&jobid, orte_process_info.my_name);
|
|
|
|
if (ORTE_SUCCESS != rc) {
|
|
|
|
ORTE_ERROR_LOG(rc);
|
|
|
|
return rc;
|
|
|
|
}
|
2005-04-14 18:55:53 +00:00
|
|
|
|
|
|
|
rc = orte_schema.get_node_tokens(&tokens, &num_tokens,
|
|
|
|
cellid,
|
|
|
|
my_name_string);
|
2005-05-01 00:47:35 +00:00
|
|
|
if (ORTE_SUCCESS != rc) {
|
|
|
|
ORTE_ERROR_LOG(rc);
|
|
|
|
return rc;
|
|
|
|
}
|
2005-04-14 18:55:53 +00:00
|
|
|
|
|
|
|
/* setup the subscription definition */
|
|
|
|
OBJ_CONSTRUCT(&sub, orte_gpr_subscription_t);
|
|
|
|
sub.addr_mode = ORTE_GPR_KEYS_OR | ORTE_GPR_TOKENS_OR;
|
2005-04-14 22:13:12 +00:00
|
|
|
sub.segment = strdup(ORTE_NODE_SEGMENT);
|
2005-04-14 18:55:53 +00:00
|
|
|
sub.tokens = tokens;
|
|
|
|
sub.num_tokens = num_tokens;
|
|
|
|
sub.num_keys = 0;
|
|
|
|
sub.keys = NULL;
|
|
|
|
sub.cbfunc = node_schedule_callback;
|
|
|
|
sub.user_tag = NULL;
|
|
|
|
|
|
|
|
/* setup the trigger definition */
|
|
|
|
OBJ_CONSTRUCT(&trig, orte_gpr_value_t);
|
|
|
|
trig.addr_mode = ORTE_GPR_TOKENS_XAND;
|
|
|
|
if (ORTE_SUCCESS != (rc = orte_schema.get_job_segment_name(&(trig.segment), jobid))) {
|
|
|
|
OBJ_DESTRUCT(&sub);
|
|
|
|
OBJ_DESTRUCT(&trig);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
trig.tokens = (char**)malloc(sizeof(char*));
|
|
|
|
if (NULL == trig.tokens) {
|
|
|
|
OBJ_DESTRUCT(&sub);
|
|
|
|
OBJ_DESTRUCT(&trig);
|
|
|
|
return ORTE_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
trig.tokens[0] = strdup(ORTE_JOB_GLOBALS);
|
|
|
|
trig.num_tokens = 1;
|
|
|
|
|
|
|
|
trig.cnt = 2;
|
|
|
|
trig.keyvals = (orte_gpr_keyval_t**)malloc(2*sizeof(orte_gpr_keyval_t*));
|
|
|
|
if (NULL == trig.keyvals) {
|
|
|
|
OBJ_DESTRUCT(&sub);
|
|
|
|
OBJ_DESTRUCT(&trig);
|
|
|
|
return ORTE_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
trig.keyvals[0] = OBJ_NEW(orte_gpr_keyval_t);
|
|
|
|
if (NULL == trig.keyvals[0]) {
|
|
|
|
OBJ_DESTRUCT(&sub);
|
|
|
|
OBJ_DESTRUCT(&trig);
|
|
|
|
return ORTE_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
trig.keyvals[0]->key = strdup(ORTE_JOB_SLOTS_KEY);
|
|
|
|
trig.keyvals[0]->type = ORTE_NULL;
|
|
|
|
|
|
|
|
trig.keyvals[1] = OBJ_NEW(orte_gpr_keyval_t);
|
|
|
|
if (NULL == trig.keyvals[1]) {
|
|
|
|
OBJ_DESTRUCT(&sub);
|
|
|
|
OBJ_DESTRUCT(&trig);
|
|
|
|
return ORTE_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
trig.keyvals[1]->key = strdup(ORTE_PROC_NUM_AT_STG1);
|
|
|
|
trig.keyvals[1]->type = ORTE_NULL;
|
|
|
|
|
|
|
|
|
|
|
|
/* register the subscription */
|
|
|
|
subs = ⊂
|
|
|
|
trigs = &trig;
|
|
|
|
rc = orte_gpr.subscribe(
|
2005-05-01 00:47:35 +00:00
|
|
|
ORTE_GPR_TRIG_ALL_CMP,
|
2005-04-14 18:55:53 +00:00
|
|
|
1, &subs,
|
2005-05-01 00:47:35 +00:00
|
|
|
1, &trigs,
|
|
|
|
&rctag);
|
2005-04-14 18:55:53 +00:00
|
|
|
if(ORTE_SUCCESS != rc) {
|
2005-05-01 00:47:35 +00:00
|
|
|
ORTE_ERROR_LOG(rc);
|
2005-04-14 18:55:53 +00:00
|
|
|
OBJ_DESTRUCT(&sub);
|
|
|
|
OBJ_DESTRUCT(&trig);
|
|
|
|
return OMPI_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
OBJ_DESTRUCT(&sub);
|
|
|
|
OBJ_DESTRUCT(&trig);
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* init the progress engine - called from orte_init */
|
2005-02-16 17:42:07 +00:00
|
|
|
int
|
|
|
|
ompi_progress_init(void)
|
|
|
|
{
|
2005-03-30 01:40:26 +00:00
|
|
|
/* reentrant issues */
|
2005-03-28 21:02:02 +00:00
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
2005-02-16 17:42:07 +00:00
|
|
|
ompi_atomic_init(&progress_lock, OMPI_ATOMIC_UNLOCKED);
|
2005-03-28 21:02:02 +00:00
|
|
|
#endif /* OMPI_HAVE_THREAD_SUPPORT */
|
2005-03-30 01:40:26 +00:00
|
|
|
|
|
|
|
/* always call sched yield when in the rte only... */
|
|
|
|
call_yield = 1;
|
|
|
|
|
|
|
|
event_progress_counter = event_progress_counter_reset = 0;
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-14 18:55:53 +00:00
|
|
|
/* do all the registration stuff during the compound command */
|
2005-03-30 01:40:26 +00:00
|
|
|
int
|
|
|
|
ompi_progress_mpi_init(void)
|
2005-04-14 18:55:53 +00:00
|
|
|
{
|
|
|
|
int param, value, rc;
|
|
|
|
/* call sched yield when oversubscribed. */
|
|
|
|
param = mca_base_param_find("mpi", NULL, "yield_when_idle");
|
|
|
|
mca_base_param_lookup_int(param, &value);
|
|
|
|
|
|
|
|
if (value < 0) {
|
|
|
|
/* no default given. Register a callback so that we have a
|
|
|
|
value when we get to mpi_enable() */
|
|
|
|
rc = register_node_schedule_callback();
|
2005-05-01 00:47:35 +00:00
|
|
|
if (OMPI_SUCCESS != rc) {
|
|
|
|
ORTE_ERROR_LOG(rc);
|
|
|
|
return rc;
|
|
|
|
}
|
2005-04-14 18:55:53 +00:00
|
|
|
}
|
|
|
|
|
2005-04-21 14:58:25 +00:00
|
|
|
event_num_mpi_users = 0;
|
|
|
|
|
2005-04-14 18:55:53 +00:00
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* turn on MPI optimizations */
|
|
|
|
int
|
|
|
|
ompi_progress_mpi_enable(void)
|
2005-03-30 01:40:26 +00:00
|
|
|
{
|
|
|
|
int param, value;
|
|
|
|
|
2005-04-14 18:55:53 +00:00
|
|
|
/* call sched yield when oversubscribed. */
|
2005-03-30 01:40:26 +00:00
|
|
|
param = mca_base_param_find("mpi", NULL, "yield_when_idle");
|
2005-04-14 18:55:53 +00:00
|
|
|
mca_base_param_lookup_int(param, &value);
|
|
|
|
|
|
|
|
if (value < 0) {
|
|
|
|
/* this should never happen (as mpi_enable should be called
|
|
|
|
after the compound command is executed). set to 1 if this
|
|
|
|
happens */
|
|
|
|
call_yield = 1;
|
|
|
|
} else {
|
|
|
|
call_yield = value;
|
|
|
|
}
|
|
|
|
|
2005-03-30 01:40:26 +00:00
|
|
|
/* set the event tick rate */
|
|
|
|
param = mca_base_param_find("mpi", NULL, "event_tick_rate");
|
|
|
|
mca_base_param_lookup_int(param, &value);
|
|
|
|
|
2005-04-14 18:55:53 +00:00
|
|
|
if (value < 0) {
|
2005-04-21 14:58:25 +00:00
|
|
|
/* user didn't specify - default tick rate */
|
|
|
|
event_progress_counter_reset = ompi_progress_default_tick_rate;
|
2005-04-14 18:55:53 +00:00
|
|
|
} else if (value == 0) {
|
2005-04-21 14:58:25 +00:00
|
|
|
/* user specified as never tick - don't count often */
|
2005-03-30 01:40:26 +00:00
|
|
|
event_progress_counter_reset = INT_MAX;
|
|
|
|
} else {
|
|
|
|
/* subtract one so that we can do post-fix subtraction
|
|
|
|
in the inner loop and go faster */
|
|
|
|
event_progress_counter_reset = value - 1;
|
|
|
|
}
|
|
|
|
|
2005-04-21 14:58:25 +00:00
|
|
|
/* it's possible that an init function bumped up our tick rate.
|
|
|
|
* If so, set the event_progress counter to 0. Otherwise, set it to
|
|
|
|
* the reset value */
|
|
|
|
event_progress_counter = (event_num_mpi_users > 0) ?
|
|
|
|
0 : event_progress_counter_reset;
|
2005-03-30 01:40:26 +00:00
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2005-04-14 18:55:53 +00:00
|
|
|
ompi_progress_mpi_disable(void)
|
2005-03-30 01:40:26 +00:00
|
|
|
{
|
|
|
|
/* always call sched yield from here on... */
|
|
|
|
call_yield = 1;
|
|
|
|
|
|
|
|
/* always tick the event library */
|
|
|
|
event_progress_counter = event_progress_counter_reset = 0;
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
ompi_progress_finalize(void)
|
|
|
|
{
|
|
|
|
/* don't need to free the progess lock */
|
|
|
|
|
|
|
|
/* free memory associated with the callbacks */
|
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
|
|
|
ompi_atomic_lock(&progress_lock);
|
|
|
|
#endif
|
|
|
|
|
2005-03-30 18:03:08 +00:00
|
|
|
if (NULL != callbacks) {
|
|
|
|
free(callbacks);
|
|
|
|
callbacks = NULL;
|
|
|
|
}
|
2005-03-30 01:40:26 +00:00
|
|
|
callbacks_len = 0;
|
|
|
|
callbacks_size = 0;
|
|
|
|
|
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
|
|
|
ompi_atomic_unlock(&progress_lock);
|
|
|
|
#endif
|
|
|
|
|
2005-02-16 17:42:07 +00:00
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2005-03-30 01:40:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ompi_progress_events(int flag)
|
2004-10-28 15:40:46 +00:00
|
|
|
{
|
2004-12-14 16:35:38 +00:00
|
|
|
ompi_progress_event_flag = flag;
|
2004-10-28 15:40:46 +00:00
|
|
|
}
|
2004-12-12 15:29:29 +00:00
|
|
|
|
|
|
|
|
2005-04-05 17:58:43 +00:00
|
|
|
/*
|
|
|
|
* Progress the event library and any functions that have registered to
|
|
|
|
* be called. We don't propogate errors from the progress functions,
|
|
|
|
* so no action is taken if they return failures. The functions are
|
|
|
|
* expected to return the number of events progressed, to determine
|
|
|
|
* whether or not we should call sched_yield() during MPI progress.
|
|
|
|
* This is only losely tracked, as an error return can cause the number
|
|
|
|
* of progressed events to appear lower than it actually is. We don't
|
|
|
|
* care, as the cost of that happening is far outweighed by the cost
|
|
|
|
* of the if checks (they were resulting in bad pipe stalling behabior)
|
|
|
|
*/
|
2005-03-30 01:40:26 +00:00
|
|
|
void
|
|
|
|
ompi_progress(void)
|
2004-04-06 16:32:40 +00:00
|
|
|
{
|
2005-03-14 20:57:21 +00:00
|
|
|
size_t i;
|
2005-04-05 17:58:43 +00:00
|
|
|
int events = 0;
|
2005-03-30 01:40:26 +00:00
|
|
|
|
2005-02-16 17:42:07 +00:00
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
|
|
|
/* NOTE: BWB - XXX - FIXME: Currently, there are some progress functions
|
|
|
|
(the event library, for one) that are not reentrant. It is not known
|
|
|
|
if the PTL progress functions are all reentrant or not. The I/O
|
|
|
|
code should all be reentrant. Because of the uncertainty, we are
|
|
|
|
preventing more than one thread of execution from progressing the
|
|
|
|
via ompi_progress (which is usually only called when there are
|
|
|
|
no PROGRESS_THREADS running). This should be made more fine-grained
|
|
|
|
at some point in the future. */
|
|
|
|
if (! ompi_atomic_trylock(&progress_lock)) {
|
|
|
|
/* someone is already progressing - return */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if OMPI_ENABLE_PROGRESS_THREADS == 0
|
2005-03-30 01:40:26 +00:00
|
|
|
/* trip the event library if we've reached our tick rate and we are
|
|
|
|
enabled */
|
|
|
|
if (event_progress_counter-- <= 0 && ompi_progress_event_flag != 0) {
|
2005-04-21 14:58:25 +00:00
|
|
|
event_progress_counter =
|
|
|
|
(event_num_mpi_users > 0) ? 1 : event_progress_counter_reset;
|
2005-04-05 17:58:43 +00:00
|
|
|
events += ompi_event_loop(ompi_progress_event_flag);
|
2004-12-12 15:29:29 +00:00
|
|
|
}
|
2004-12-07 15:39:57 +00:00
|
|
|
#endif
|
2005-03-14 20:57:21 +00:00
|
|
|
|
2005-03-30 01:40:26 +00:00
|
|
|
/* progress all registered callbacks */
|
2005-03-14 20:57:21 +00:00
|
|
|
for (i = 0 ; i < callbacks_len ; ++i) {
|
2005-04-05 17:58:43 +00:00
|
|
|
#if OMPI_ENABLE_DEBUG
|
2005-03-18 03:43:59 +00:00
|
|
|
if (NULL != callbacks[i]) {
|
2005-04-05 17:58:43 +00:00
|
|
|
#endif
|
|
|
|
events += (callbacks[i])();
|
|
|
|
#if OMPI_ENABLE_DEBUG
|
|
|
|
} else {
|
|
|
|
ompi_output(0, "WARNING: ompi_progess attempted to call NULL"
|
|
|
|
" function at line %d, index %d.", __LINE__, i);
|
|
|
|
}
|
|
|
|
#endif
|
2005-03-14 20:57:21 +00:00
|
|
|
}
|
|
|
|
|
2005-02-23 08:21:02 +00:00
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
2005-02-16 17:42:07 +00:00
|
|
|
/* release the lock before yielding, for obvious reasons */
|
|
|
|
ompi_atomic_unlock(&progress_lock);
|
2005-02-23 08:21:02 +00:00
|
|
|
#endif /* OMPI_HAVE_THREAD_SUPPORT */
|
2005-02-16 17:42:07 +00:00
|
|
|
|
2005-05-23 22:06:50 +00:00
|
|
|
if (events <= 0) {
|
2005-04-21 14:58:25 +00:00
|
|
|
/* If there is nothing to do - yield the processor - otherwise
|
2005-03-30 01:40:26 +00:00
|
|
|
* we could consume the processor for the entire time slice. If
|
|
|
|
* the processor is oversubscribed - this will result in a best-case
|
|
|
|
* latency equivalent to the time-slice.
|
|
|
|
*/
|
2005-01-20 00:03:23 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
/* TODO: Find the windows equivalent for this */
|
2005-03-28 21:03:24 +00:00
|
|
|
sched_yield();
|
2005-01-20 00:03:23 +00:00
|
|
|
#endif
|
2004-12-12 15:29:29 +00:00
|
|
|
}
|
2004-04-06 16:32:40 +00:00
|
|
|
}
|
|
|
|
|
2005-03-14 20:57:21 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
ompi_progress_register(ompi_progress_callback_t cb)
|
|
|
|
{
|
2005-03-30 01:40:26 +00:00
|
|
|
int ret = OMPI_SUCCESS;
|
|
|
|
|
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
|
|
|
ompi_atomic_lock(&progress_lock);
|
|
|
|
#endif
|
|
|
|
|
2005-03-14 20:57:21 +00:00
|
|
|
/* see if we need to allocate more space */
|
|
|
|
if (callbacks_len + 1 > callbacks_size) {
|
|
|
|
ompi_progress_callback_t *tmp;
|
|
|
|
tmp = realloc(callbacks, callbacks_size + 4);
|
2005-03-30 01:40:26 +00:00
|
|
|
if (tmp == NULL) {
|
|
|
|
ret = OMPI_ERR_TEMP_OUT_OF_RESOURCE;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2005-03-14 20:57:21 +00:00
|
|
|
|
|
|
|
callbacks = tmp;
|
|
|
|
callbacks_size += 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
callbacks[callbacks_len++] = cb;
|
|
|
|
|
2005-03-30 01:40:26 +00:00
|
|
|
cleanup:
|
|
|
|
|
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
|
|
|
ompi_atomic_unlock(&progress_lock);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
2005-03-14 20:57:21 +00:00
|
|
|
}
|
2005-03-18 03:43:59 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
ompi_progress_unregister(ompi_progress_callback_t cb)
|
|
|
|
{
|
|
|
|
size_t i;
|
2005-04-14 20:10:27 +00:00
|
|
|
int ret = OMPI_ERR_NOT_FOUND;
|
2005-03-30 01:40:26 +00:00
|
|
|
|
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
|
|
|
ompi_atomic_lock(&progress_lock);
|
|
|
|
#endif
|
2005-03-18 03:43:59 +00:00
|
|
|
|
|
|
|
for (i = 0 ; i < callbacks_len ; ++i) {
|
|
|
|
if (cb == callbacks[i]) {
|
|
|
|
callbacks[i] = NULL;
|
2005-03-30 01:40:26 +00:00
|
|
|
ret = OMPI_SUCCESS;
|
2005-04-05 17:58:43 +00:00
|
|
|
break;
|
2005-03-18 03:43:59 +00:00
|
|
|
}
|
|
|
|
}
|
2005-04-05 17:58:43 +00:00
|
|
|
|
2005-04-14 20:10:27 +00:00
|
|
|
/* If we found the function we're unregistering: If callbacks_len
|
|
|
|
is 0, we're not goig to do anything interesting anyway, so
|
|
|
|
skip. If callbacks_len is 1, it will soon be 0, so no need to
|
|
|
|
do any repacking. size_t can be unsigned, so 0 - 1 is bad for
|
|
|
|
a loop condition :). */
|
|
|
|
if (OMPI_SUCCESS == ret) {
|
|
|
|
if (callbacks_len > 1 ) {
|
|
|
|
/* now tightly pack the array */
|
|
|
|
for ( ; i < callbacks_len - 1 ; ++i) {
|
|
|
|
callbacks[i] = callbacks[i + 1];
|
|
|
|
}
|
2005-04-06 20:17:45 +00:00
|
|
|
}
|
2005-04-14 20:10:27 +00:00
|
|
|
callbacks[callbacks_len - 1] = NULL;
|
|
|
|
callbacks_len--;
|
2005-04-05 17:58:43 +00:00
|
|
|
}
|
2005-03-30 01:40:26 +00:00
|
|
|
|
|
|
|
#if OMPI_HAVE_THREAD_SUPPORT
|
|
|
|
ompi_atomic_unlock(&progress_lock);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
2005-03-18 03:43:59 +00:00
|
|
|
}
|
2005-04-21 14:58:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
ompi_progress_event_increment()
|
|
|
|
{
|
|
|
|
int32_t val;
|
|
|
|
val = ompi_atomic_add_32(&event_num_mpi_users, 1);
|
|
|
|
/* always reset the tick rate - can't hurt */
|
|
|
|
event_progress_counter = 0;
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
ompi_progress_event_decrement()
|
|
|
|
{
|
|
|
|
int32_t val;
|
|
|
|
val = ompi_atomic_sub_32(&event_num_mpi_users, 1);
|
|
|
|
if (val >= 0) {
|
|
|
|
event_progress_counter = event_progress_counter_reset;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|