/* * Copyright (c) 2004-2006 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2006 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "ompi_config.h" #include "mpi.h" #ifdef HAVE_STRING_H # include #endif #include "ompi/peruse/peruse.h" #include "ompi/peruse/peruse-internal.h" #include "opal/class/opal_hash_table.h" #include "ompi/communicator/communicator.h" #include "ompi/file/file.h" OMPI_DECLSPEC extern bool ompi_mpi_param_check; /* * Data */ /* * This array has to match the array in peruse.h * and the PERUSE_events -array below. */ const char * PERUSE_event_names[] = { /* Point-to-point request events */ "PERUSE_COMM_REQ_ACTIVATE", "PERUSE_COMM_REQ_MATCH_UNEX", "PERUSE_COMM_REQ_INSERT_IN_POSTED_Q", "PERUSE_COMM_REQ_REMOVE_FROM_POSTED_Q", "PERUSE_COMM_REQ_XFER_BEGIN", "PERUSE_COMM_REQ_XFER_CONTINUE", "PERUSE_COMM_REQ_XFER_END", "PERUSE_COMM_REQ_COMPLETE", "PERUSE_COMM_REQ_NOTIFY", "PERUSE_COMM_MSG_ARRIVED", "PERUSE_COMM_MSG_INSERT_IN_UNEX_Q", "PERUSE_COMM_MSG_REMOVE_FROM_UNEX_Q", "PERUSE_COMM_MSG_MATCH_POSTED_REQ", /* Queue events*/ "PERUSE_COMM_SEARCH_POSTED_Q_BEGIN", "PERUSE_COMM_SEARCH_POSTED_Q_END", "PERUSE_COMM_SEARCH_UNEX_Q_BEGIN", /* XXX Devation from 1.11 */ "PERUSE_COMM_SEARCH_UNEX_Q_END" }; const int PERUSE_events[] = { /* Point-to-point request events */ PERUSE_COMM_REQ_ACTIVATE, PERUSE_COMM_REQ_MATCH_UNEX, PERUSE_COMM_REQ_INSERT_IN_POSTED_Q, PERUSE_COMM_REQ_REMOVE_FROM_POSTED_Q, PERUSE_COMM_REQ_XFER_BEGIN, PERUSE_COMM_REQ_XFER_CONTINUE, PERUSE_COMM_REQ_XFER_END, PERUSE_COMM_REQ_COMPLETE, PERUSE_COMM_REQ_NOTIFY, PERUSE_COMM_MSG_ARRIVED, PERUSE_COMM_MSG_INSERT_IN_UNEX_Q, PERUSE_COMM_MSG_REMOVE_FROM_UNEX_Q, PERUSE_COMM_MSG_MATCH_POSTED_REQ, /* Queue events*/ PERUSE_COMM_SEARCH_POSTED_Q_BEGIN, PERUSE_COMM_SEARCH_POSTED_Q_END, PERUSE_COMM_SEARCH_UNEX_Q_BEGIN, PERUSE_COMM_SEARCH_UNEX_Q_END }; const int PERUSE_num_events = (sizeof (PERUSE_events) / sizeof (PERUSE_events[0])); /* * PERUSE user-callable function */ int PERUSE_Init (void) { ompi_peruse_init (); return PERUSE_SUCCESS; } /* Query all implemented events */ int PERUSE_Query_supported_events ( int * num_supported, char *** event_names, int ** events) { int i; *num_supported = PERUSE_num_events; /* * Play save and copy all values. */ *event_names = (char**) malloc (PERUSE_num_events * sizeof (char *)); *events = (int*) malloc (PERUSE_num_events * sizeof (int)); for (i = 0; i < PERUSE_num_events; i++) { (*event_names)[i] = strdup (PERUSE_event_names[i]); (*events)[i] = PERUSE_events[i]; } return PERUSE_SUCCESS; } /* Query supported events */ int PERUSE_Query_event (const char * event_name, int *event) { int i; for (i = 0; i < PERUSE_num_events; i++) { if (!strcmp (event_name, PERUSE_event_names[i])) break; } if (i == PERUSE_num_events) return PERUSE_ERR_EVENT; *event = PERUSE_events[i]; return PERUSE_SUCCESS; } /* Query event name */ int PERUSE_Query_event_name (int event, char ** event_name) { if (event < 0 || event > PERUSE_num_events || NULL == PERUSE_event_names[event]) return PERUSE_EVENT_INVALID; *event_name = strdup (PERUSE_event_names[event]); return PERUSE_SUCCESS; } /* Get environment variables that affect MPI library behavior */ int PERUSE_Query_environment (int * env_size, char *** env) { /* XXX tbd */ return PERUSE_SUCCESS; } /* Query the scope of queue metrics - global or per communicator */ int PERUSE_Query_queue_event_scope (int * scope) { *scope = PERUSE_PER_COMM; /* XXX; not yet realized */ return PERUSE_SUCCESS; } /* * II. Events, objects initialization and manipulation */ /* Initialize event associated with an MPI communicator */ int PERUSE_Event_comm_register ( int event, MPI_Comm comm, peruse_comm_callback_f * callback_fn, void * param, peruse_event_h * event_h) { ompi_peruse_handle_t * handle; if (MPI_PARAM_CHECK) { if (event < 0 || event > PERUSE_num_events || NULL == PERUSE_event_names[event]) return PERUSE_ERR_EVENT; if (MPI_COMM_NULL == comm || ompi_comm_invalid (comm)) return PERUSE_ERR_COMM; if (NULL == callback_fn) return PERUSE_ERR_GENERIC; if (NULL == event_h) return PERUSE_ERR_EVENT_HANDLE; } handle = OBJ_NEW (ompi_peruse_handle_t); /* * Initialize the newly created handle to the default inactive state. */ handle->active = 0; handle->event = event; handle->type = PERUSE_TYPE_COMM; handle->comm = comm; handle->fn = (ompi_peruse_callback_f*) callback_fn; handle->param = param; /* * Update the information on the handle on the communicator */ OPAL_THREAD_LOCK (&comm->c_lock); if( NULL == comm->c_peruse_handles ) { comm->c_peruse_handles = malloc( PERUSE_num_events * sizeof(ompi_peruse_handle_t*) ); } OPAL_THREAD_UNLOCK (&comm->c_lock); comm->c_peruse_handles[event] = handle; *event_h = handle; return PERUSE_SUCCESS; } /* Start collecting data (activate event) */ int PERUSE_Event_activate (peruse_event_h event_h) { ompi_peruse_handle_t* handle = (ompi_peruse_handle_t*)event_h; if (MPI_PARAM_CHECK) { if (PERUSE_EVENT_HANDLE_NULL == event_h) return PERUSE_ERR_EVENT_HANDLE; } OPAL_THREAD_LOCK (&handle->lock); handle->active = 1; OPAL_THREAD_UNLOCK (&handle->lock); return PERUSE_SUCCESS; } /* Stop collecting data (deactivate event) */ int PERUSE_Event_deactivate (peruse_event_h event_h) { ompi_peruse_handle_t* handle = (ompi_peruse_handle_t*)event_h; if (MPI_PARAM_CHECK) { if (PERUSE_EVENT_HANDLE_NULL == event_h) return PERUSE_ERR_EVENT_HANDLE; } OPAL_THREAD_LOCK (&handle->lock); handle->active = 0; OPAL_THREAD_UNLOCK (&handle->lock); return PERUSE_SUCCESS; } /* Free event handle */ int PERUSE_Event_release (peruse_event_h * event_h) { if (MPI_PARAM_CHECK) { if (PERUSE_EVENT_HANDLE_NULL == event_h) return PERUSE_ERR_EVENT_HANDLE; } /* * XXX */ *event_h = PERUSE_EVENT_HANDLE_NULL; return PERUSE_SUCCESS; } #undef PERUSE_MPI_PARAM_CHECK #define PERUSE_MPI_PARAM_CHECK(obj_upper,obj_lower ) \ if (MPI_PARAM_CHECK) { \ if (PERUSE_EVENT_HANDLE_NULL == event_h || \ ((ompi_peruse_handle_t*)event_h)->active || \ ((ompi_peruse_handle_t*)event_h)->type != \ PERUSE_TYPE_ ## obj_upper) \ return PERUSE_ERR_EVENT_HANDLE; \ \ if (NULL == callback_fn) \ return PERUSE_ERR_PARAMETER; \ /* \ * XXX whethter the underlying MPI-object has been freed!?? \ if (ompi_ ## obj_lower ## _invalid ( \ ((ompi_peruse_handle_t*)event_h)->obj_lower)) \ return PERUSE_ERR_MPI_OBJECT; \ */ \ } \ /* Set a new comm callback */ int PERUSE_Event_comm_callback_set ( peruse_event_h event_h, peruse_comm_callback_f * callback_fn, void * param) { ompi_peruse_handle_t* handle = (ompi_peruse_handle_t*)event_h; PERUSE_MPI_PARAM_CHECK (COMM, comm); OPAL_THREAD_LOCK (&handle->lock); handle->fn = (ompi_peruse_callback_f*) callback_fn; handle->param = param; OPAL_THREAD_UNLOCK (&handle->lock); return PERUSE_SUCCESS; } /* Set a new file callback */ int PERUSE_Event_file_callback_set ( peruse_event_h event_h, peruse_file_callback_f * callback_fn, void * param) { ompi_peruse_handle_t* handle = (ompi_peruse_handle_t*)event_h; PERUSE_MPI_PARAM_CHECK (FILE, file); OPAL_THREAD_LOCK (&handle->lock); handle->fn = (ompi_peruse_callback_f*) callback_fn; handle->param = param; OPAL_THREAD_UNLOCK (&handle->lock); return PERUSE_SUCCESS; } /* Set a new win callback */ int PERUSE_Event_win_callback_set ( peruse_event_h event_h, peruse_win_callback_f * callback_fn, void * param) { ompi_peruse_handle_t* handle = (ompi_peruse_handle_t*)event_h; PERUSE_MPI_PARAM_CHECK (WIN, win); OPAL_THREAD_LOCK (&handle->lock); handle->fn = (ompi_peruse_callback_f*) callback_fn; handle->param = param; OPAL_THREAD_UNLOCK (&handle->lock); return PERUSE_SUCCESS; } #undef PERUSE_MPI_PARAM_CHECK #define PERUSE_MPI_PARAM_CHECK(obj_upper,obj_lower ) \ if (MPI_PARAM_CHECK) { \ if (PERUSE_EVENT_HANDLE_NULL == event_h || \ ((ompi_peruse_handle_t*)event_h)->active || \ ((ompi_peruse_handle_t*)event_h)->type != \ PERUSE_TYPE_ ## obj_upper) \ return PERUSE_ERR_EVENT_HANDLE; \ \ if (NULL == callback_fn || NULL == param) \ return PERUSE_ERR_PARAMETER; \ /* \ * XXX whethter the underlying MPI-object has been freed!?? \ if (ompi_ ## obj_lower ## _invalid ( \ ((ompi_peruse_handle_t*)event_h)->obj_lower)) \ return PERUSE_ERR_MPI_OBJECT; \ */ \ } \ /* Get the current comm callback */ int PERUSE_Event_comm_callback_get ( peruse_event_h event_h, peruse_comm_callback_f ** callback_fn, void ** param) { ompi_peruse_handle_t* handle = (ompi_peruse_handle_t*)event_h; PERUSE_MPI_PARAM_CHECK (COMM, comm); OPAL_THREAD_LOCK (&handle->lock); *callback_fn = (peruse_comm_callback_f*) handle->fn; *param = handle->param; OPAL_THREAD_UNLOCK (&handle->lock); return PERUSE_SUCCESS; } /* Get the current ile callback */ int PERUSE_Event_file_callback_get ( peruse_event_h event_h, peruse_file_callback_f ** callback_fn, void ** param) { ompi_peruse_handle_t* handle = (ompi_peruse_handle_t*)event_h; PERUSE_MPI_PARAM_CHECK (FILE, file); OPAL_THREAD_LOCK (&handle->lock); *callback_fn = (peruse_file_callback_f*) handle->fn; *param = handle->param; OPAL_THREAD_UNLOCK (&handle->lock); return PERUSE_SUCCESS; } /* Get the current win callback */ int PERUSE_Event_win_callback_get ( peruse_event_h event_h, peruse_win_callback_f ** callback_fn, void ** param) { ompi_peruse_handle_t* handle = (ompi_peruse_handle_t*)event_h; PERUSE_MPI_PARAM_CHECK (WIN, win); OPAL_THREAD_LOCK (&handle->lock); *callback_fn = (peruse_win_callback_f*) handle->fn; *param = handle->param; OPAL_THREAD_UNLOCK (&handle->lock); return PERUSE_SUCCESS; } /* Obtain event descriptor from an event handle (reverse lookup) */ int PERUSE_Event_get (peruse_event_h event_h, int * event) { if (MPI_PARAM_CHECK) { if (NULL == event_h) return PERUSE_ERR_EVENT_HANDLE; if (NULL == event) return PERUSE_ERR_PARAMETER; } *event = ((ompi_peruse_handle_t*)event_h)->event; return PERUSE_SUCCESS; } /* Obtain MPI object associated with event handle */ /* XXX Shouldn't we have 3 different functions to obtain a specific object Comm/File/Win */ int PERUSE_Event_object_get (peruse_event_h event_h, void ** mpi_object) { ompi_peruse_handle_t * p = event_h; if (MPI_PARAM_CHECK) { if (NULL == event_h) return PERUSE_ERR_EVENT_HANDLE; if (NULL == mpi_object) return PERUSE_ERR_PARAMETER; } switch (p->type) { case PERUSE_TYPE_INVALID: return PERUSE_ERR_GENERIC; case PERUSE_TYPE_COMM: *mpi_object = p->comm; break; case PERUSE_TYPE_FILE: *mpi_object = p->file; break; case PERUSE_TYPE_WIN: *mpi_object = p->win; break; } return PERUSE_SUCCESS; } /* Propagaiont mode */ int PERUSE_Event_propagate (peruse_event_h event_h, int mode) { return PERUSE_SUCCESS; }