void ObjectTable_dumpAddresses (FILE *fd, unsigned eventstart)
{
    unsigned _ptask, _task, _address;

    /* Temporary, just dump information for ptask 1.task 1 */
    /* Emitting the rest of ptask/task requires some changes in mpimpi2prv */

    for (_ptask = 1; _ptask <= 1 /* ApplicationTable.nptasks */; _ptask++)
        for (_task = 1; _task <= 1 /* ApplicationTable.ptasks[_ptask].ntasks */; _task++)
        {
            task_t *task_info = GET_TASK_INFO(_ptask, _task);

            fprintf (fd, "EVENT_TYPE\n");
            fprintf (fd, "0 %u Object addresses for task %u.%u\n", eventstart++, _ptask, _task);
            fprintf (fd, "VALUES\n");

            /* For now, emit only data symbols for binary object 0 */
            for (_address = 0; _address < task_info->binary_objects[0].nDataSymbols; _address++)
            {
                data_symbol_t *d = &task_info->binary_objects[0].dataSymbols[_address];

                fprintf (fd, "%u %s [0x%08llx-0x%08llx]\n",
                         _address+1,
                         d->name,
                         (unsigned long long) d->address,
                         ((unsigned long long) d->address)+d->size-1);
            }
            fprintf (fd, "\n");
        }
}
char * ObjectTable_GetBinaryObjectName (unsigned ptask, unsigned task)
{
    task_t *task_info = GET_TASK_INFO(ptask, task);

    if (task_info->num_binary_objects > 0)
        return task_info->binary_objects[0].module;
    else
        return NULL;
}
binary_object_t* ObjectTable_GetBinaryObjectAt (unsigned ptask, unsigned task, UINT64 address)
{
    task_t *task_info = GET_TASK_INFO(ptask, task);
    unsigned u;

    for (u = 0; u < task_info->num_binary_objects; u++)
        if (address >= task_info->binary_objects[u].start_address &&
                address <= task_info->binary_objects[u].end_address)
            return &(task_info->binary_objects[u]);

    return NULL;
}
static void AddBinaryObjectInto (unsigned ptask, unsigned task,
                                 unsigned long long start, unsigned long long end, unsigned long long offset,
                                 char *binary)
{
    task_t *task_info = GET_TASK_INFO(ptask, task);
    unsigned found = FALSE, u;

    if (!file_exists(binary))
        return;

    for (u = 0; u < task_info->num_binary_objects && !found; u++)
        found = strcmp (task_info->binary_objects[u].module, binary) == 0;

    if (!found)
    {
        unsigned last_index = task_info->num_binary_objects;
        task_info->binary_objects = (binary_object_t*) realloc (
                                        task_info->binary_objects,
                                        (last_index+1) * sizeof(binary_object_t));
        if (task_info->binary_objects == NULL)
        {
            fprintf (stderr, "Fatal error! Cannot allocate memory for binary object!\n");
            exit (-1);
        }
        task_info->binary_objects[last_index].module = strdup (binary);
        task_info->binary_objects[last_index].start_address = start;
        task_info->binary_objects[last_index].end_address = end;
        task_info->binary_objects[last_index].offset = offset;
        task_info->binary_objects[last_index].index = last_index+1;

#if defined(HAVE_BFD)
        BFDmanager_loadBinary (binary,
                               &(task_info->binary_objects[last_index].bfdImage),
                               &(task_info->binary_objects[last_index].bfdSymbols),
                               &(task_info->binary_objects[last_index].nDataSymbols),
                               &(task_info->binary_objects[last_index].dataSymbols));
#endif

        task_info->num_binary_objects++;
    }
}
/******************************************************************************
 ***  InitializeObjectTable
 ******************************************************************************/
void InitializeObjectTable (unsigned num_appl, struct input_t * files,
                            unsigned long nfiles)
{
    unsigned int ptask, task, thread, i, j;
    unsigned int ntasks[num_appl], **nthreads = NULL;

    /* First step, collect number of applications, number of tasks per application and
       number of threads per task within an app */
    for (i = 0; i < num_appl; i++)
        ntasks[i] = 0;

    for (i = 0; i < nfiles; i++)
        ntasks[files[i].ptask-1] = MAX(files[i].task, ntasks[files[i].ptask-1]);

    nthreads = (unsigned**) malloc (num_appl*sizeof(unsigned*));
    ASSERT(nthreads!=NULL, "Cannot allocate memory to store nthreads for whole applications");

    for (i = 0; i < num_appl; i++)
    {
        nthreads[i] = (unsigned*) malloc (ntasks[i]*sizeof(unsigned));
        ASSERT(nthreads[i]!=NULL, "Cannot allocate memory to store nthreads for application");

        for (j = 0; j < ntasks[i]; j++)
            nthreads[i][j] = 0;
    }

    for (i = 0; i < nfiles; i++)
        nthreads[files[i].ptask-1][files[i].task-1] = MAX(files[i].thread, nthreads[files[i].ptask-1][files[i].task-1]);

    /* Second step, allocate structures respecting the number of apps, tasks and threads found */
    ApplicationTable.nptasks = num_appl;
    ApplicationTable.ptasks = (ptask_t*) malloc (sizeof(ptask_t)*num_appl);
    ASSERT(ApplicationTable.ptasks!=NULL, "Unable to allocate memory for ptasks");

    for (i = 0; i < ApplicationTable.nptasks; i++)
    {
        /* Allocate per task information within each ptask */
        ApplicationTable.ptasks[i].ntasks = ntasks[i];
        ApplicationTable.ptasks[i].tasks = (task_t*) malloc (sizeof(task_t)*ntasks[i]);
        ASSERT(ApplicationTable.ptasks[i].tasks!=NULL, "Unable to allocate memory for tasks");

        for (j = 0; j < ApplicationTable.ptasks[i].ntasks; j++)
        {
            /* Initialize pending communication queues for each task */
            CommunicationQueues_Init (
                &(ApplicationTable.ptasks[i].tasks[j].send_queue),
                &(ApplicationTable.ptasks[i].tasks[j].recv_queue));

            /* Allocate per thread information within each task */
            ApplicationTable.ptasks[i].tasks[j].threads = (thread_t*) malloc (sizeof(thread_t)*nthreads[i][j]);
            ASSERT(ApplicationTable.ptasks[i].tasks[j].threads!=NULL,"Unable to allocate memory for threads");
        }
    }

#if USE_HARDWARE_COUNTERS || defined(HETEROGENEOUS_SUPPORT)
    INIT_QUEUE (&CountersTraced);
#endif

    /* 3rd step, Initialize the object table structure */
    for (ptask = 0; ptask < ApplicationTable.nptasks; ptask++)
        for (task = 0; task < ApplicationTable.ptasks[ptask].ntasks; task++)
        {
            task_t *task_info = GET_TASK_INFO(ptask+1,task+1);
            task_info->tracing_disabled = FALSE;
            task_info->nthreads = nthreads[ptask][task];
            task_info->num_virtual_threads = nthreads[ptask][task];

            task_info->num_binary_objects = 0;
            task_info->binary_objects = NULL;

            for (thread = 0; thread < nthreads[ptask][task]; thread++)
            {
                thread_t *thread_info = GET_THREAD_INFO(ptask+1,task+1,thread+1);

                /* Look for the appropriate CPU for this ptask, task, thread */
                for (i = 0; i < nfiles; i++)
                    if (files[i].ptask == ptask+1 &&
                            files[i].task == task+1 &&
                            files[i].thread == thread+1)
                    {
                        thread_info->cpu = files[i].cpu;
                        break;
                    }

                thread_info->dimemas_size = 0;
                thread_info->virtual_thread = thread+1;
                thread_info->nStates = 0;
                thread_info->First_Event = TRUE;
                thread_info->HWCChange_count = 0;
                thread_info->MatchingComms = TRUE;
#if USE_HARDWARE_COUNTERS || defined(HETEROGENEOUS_SUPPORT)
                thread_info->HWCSets = NULL;
                thread_info->HWCSets_types = NULL;
                thread_info->num_HWCSets = 0;
                thread_info->current_HWCSet = 0;
#endif
            }
        }

    /* 4th step Assign the node ID */
    for (i = 0; i < nfiles; i++)
    {
        task_t *task_info = GET_TASK_INFO(files[i].ptask, files[i].task);
        task_info->nodeid = files[i].nodeid;
    }

    /* This is needed for get_option_merge_NanosTaskView() == FALSE */
    for (ptask = 0; ptask < ApplicationTable.nptasks; ptask++)
        for (task = 0; task < ApplicationTable.ptasks[ptask].ntasks; task++)
        {
            task_t *task_info = GET_TASK_INFO(ptask+1, task+1);
            task_info->num_active_task_threads = 0;
            task_info->active_task_threads = NULL;
        }

    /* Clean up */
    if (nthreads != NULL)
    {
        for (i = 0; i < num_appl; i++)
            if (nthreads[i] != NULL)
                free (nthreads[i]);
        free (nthreads);
    }
}
int MPI_PersistentRequest_Event (event_t * current_event,
	unsigned long long current_time, unsigned int cpu, unsigned int ptask,
	unsigned int task, unsigned int thread, FileSet_t *fset)
{
	thread_t *thread_info;
	task_t *task_info, *task_info_partner;
	event_t *recv_begin, *recv_end;
	event_t *send_begin, *send_end;
	off_t send_position;
	unsigned recv_thread, send_thread, recv_vthread, send_vthread;
	int EvComm; 

	EvComm = Get_EvComm( current_event );

	thread_info = GET_THREAD_INFO(ptask, task, thread);
	task_info = GET_TASK_INFO(ptask, task);
	trace_paraver_state (cpu, ptask, task, thread, current_time);

	/* If this is a send, look for the receive */
	if (Get_EvValue (current_event) == MPI_ISEND_EV)
	{
		thread_info->Send_Rec = current_event;

		if (MatchComms_Enabled(ptask, task))
		{
			if (MPI_PROC_NULL != Get_EvTarget (current_event))
			{
				int target_ptask = intercommunicators_get_target_ptask( ptask, task, EvComm );

				if (isTaskInMyGroup (fset, target_ptask-1, Get_EvTarget(current_event)))
				{
#if defined(DEBUG)
					fprintf (stderr, "PERS_REQ_ISEND_CMD(%u): TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d\n", Get_EvValue (current_event), current_time, Get_EvTime(current_event), task-1, Get_EvTarget(current_event), Get_EvTag(current_event));
#endif

					task_info_partner = GET_TASK_INFO(target_ptask, Get_EvTarget(current_event)+1);

					CommunicationQueues_ExtractRecv (task_info_partner->recv_queue, task-1, Get_EvTag (current_event), &recv_begin, &recv_end, &recv_thread, &recv_vthread, 0);

					if (recv_begin == NULL || recv_end == NULL)
					{
						off_t position;
#if defined(DEBUG)
						fprintf (stderr, "PER_REQ_ISEND_CMD DID NOT find a partner\n");
#endif
						position = WriteFileBuffer_getPosition (thread_info->file->wfb);
						CommunicationQueues_QueueSend (task_info->send_queue, current_event, current_event, position, thread, thread_info->virtual_thread, Get_EvTarget(current_event), Get_EvTag(current_event), 0);
						trace_paraver_unmatched_communication (1, ptask, task, thread, thread_info->virtual_thread, current_time, Get_EvTime(current_event), 1, target_ptask, Get_EvTarget(current_event)+1, 1, Get_EvSize(current_event), Get_EvTag(current_event));
					}
					else
					{
#if defined(DEBUG)
						fprintf (stderr, "PER_REQ_ISEND_CMD DID NOT find a partner\n");
#endif
						trace_communicationAt (ptask, task, thread, thread_info->virtual_thread, target_ptask, 1+Get_EvTarget(current_event), recv_thread, recv_vthread, current_event, current_event, recv_begin, recv_end, FALSE, 0);
					}

				}
#if defined(PARALLEL_MERGE)
				else
				{
#if defined(DEBUG)
					fprintf (stdout, "SEND_CMD(%u): TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d >> PENDING\n", Get_EvEvent(current_event), current_time, Get_EvTime(current_event), task-1, Get_EvTarget(current_event), Get_EvTag(current_event));
#endif
					trace_pending_communication (ptask, task, thread, thread_info->virtual_thread, thread_info->Send_Rec, current_event, target_ptask, Get_EvTarget (current_event));
				}
#endif
			}
		}
	}

	/* If this is a receive, look for the send */
	if (Get_EvValue(current_event) == MPI_IRECV_EV)
	{
		thread_info->Recv_Rec = current_event;

		if (MatchComms_Enabled(ptask, task))
		{
			event_t *receive = Search_MPI_IRECVED (current_event, Get_EvAux (current_event), thread_info->file);
			if (NULL != receive)
			{
				int target_ptask = intercommunicators_get_target_ptask( ptask, task, EvComm );

				if (MPI_PROC_NULL != Get_EvTarget(receive))
				{
					if (isTaskInMyGroup (fset, target_ptask-1, Get_EvTarget(receive)))
					{
#if defined(DEBUG)
						fprintf (stderr, "PERS_REQ_IRECV_CMD(%u): TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d\n", Get_EvValue (current_event), current_time, Get_EvTime(current_event), task-1, Get_EvTarget(receive), Get_EvTag(receive));
#endif

						task_info_partner = GET_TASK_INFO(ptask, Get_EvTarget(receive)+1);

						CommunicationQueues_ExtractSend (task_info_partner->send_queue, task-1, Get_EvTag (receive), &send_begin, &send_end, &send_position, &send_thread, &send_vthread, 0);

						if (NULL == send_begin || NULL == send_end)
						{
#if defined(DEBUG)
							fprintf (stderr, "PER_REQ_IRECV_CMD DID NOT find a partner\n");
#endif
							CommunicationQueues_QueueRecv (task_info->recv_queue, current_event, receive, thread, thread_info->virtual_thread, Get_EvTarget(current_event), Get_EvTag(current_event), 0);
						}
						else if (NULL != send_begin && NULL != send_end)
						{
#if defined(DEBUG)
							fprintf (stderr, "PERS_REQ_IRECV_CMD find partner (send position = %llu)\n", (unsigned long long) send_position);
#endif
							trace_communicationAt (target_ptask, 1+Get_EvTarget(receive), send_thread, send_vthread, ptask, task, thread, thread_info->virtual_thread, send_begin, send_end, current_event, receive, TRUE, send_position);
						}
						else
							fprintf (stderr, "mpi2prv: Attention CommunicationQueues_ExtractSend returned send_begin = %p and send_end = %p\n", send_begin, send_end);
					}
#if defined(PARALLEL_MERGE)
					else
					{
						UINT64 log_r, phy_r;

						log_r = TIMESYNC (ptask-1, task-1, Get_EvTime(current_event));
						phy_r = TIMESYNC (ptask-1, task-1, Get_EvTime(receive));
						AddForeignRecv (phy_r, log_r, Get_EvTag(receive), ptask-1, task-1, thread-1,
							thread_info->virtual_thread-1, target_ptask-1, Get_EvTarget(receive), fset, MatchComms_GetZone(ptask, task));
					}
#endif
				}
			}
		}
	}

	return 0;
}
static int IRecv_Event (event_t * current_event,
	unsigned long long current_time, unsigned int cpu, unsigned int ptask,
	unsigned int task, unsigned int thread, FileSet_t *fset)
{
	event_t *send_begin, *send_end;
	off_t send_position;
	unsigned EvType, EvValue, send_thread, send_vthread;
	thread_t *thread_info;
	task_t *task_info, *task_info_partner;
	int EvComm;

	thread_info = GET_THREAD_INFO(ptask, task, thread);
	task_info = GET_TASK_INFO(ptask, task);

	EvType  = Get_EvEvent (current_event);
	EvValue = Get_EvValue (current_event);
	EvComm  = Get_EvComm  (current_event);

	Switch_State (STATE_IWAITMESS, (EvValue == EVT_BEGIN), ptask, task, thread);

	if (EvValue == EVT_END)
	{
		if (MatchComms_Enabled(ptask, task))
		{
			event_t *receive = Search_MPI_IRECVED (current_event, Get_EvAux (current_event), thread_info->file);
			if (NULL != receive)
			{
				if (MPI_PROC_NULL != Get_EvTarget(receive))
				{
					int target_ptask = intercommunicators_get_target_ptask( ptask, task, EvComm );

					if (isTaskInMyGroup (fset, target_ptask-1, Get_EvTarget(receive)))
					{
#if defined(DEBUG)
						fprintf (stderr, "IRECV_CMD: TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d\n", current_time, Get_EvTime(current_event), task-1, Get_EvTarget(receive), Get_EvTag(receive));
#endif
						task_info_partner = GET_TASK_INFO(target_ptask, Get_EvTarget(receive)+1);

						CommunicationQueues_ExtractSend (task_info_partner->send_queue, task-1, Get_EvTag (receive), &send_begin, &send_end, &send_position, &send_thread, &send_vthread, 0);

						if (NULL == send_begin || NULL == send_end)
						{
#if defined(DEBUG)
							fprintf (stderr, "IRECV_CMD DID NOT find COMM\n");
#endif
							CommunicationQueues_QueueRecv (task_info->recv_queue, current_event, receive, thread, thread_info->virtual_thread, Get_EvTarget(receive), Get_EvTag(receive), 0);
						}
						else if (NULL != send_begin && NULL != send_end)
						{
#if defined(DEBUG)
							fprintf (stderr, "IRECV_CMD find COMM (partner times = %lld/%lld)\n", Get_EvTime(send_begin), Get_EvTime(send_end));
#endif
							trace_communicationAt (target_ptask, 1+Get_EvTarget(receive), send_thread, send_vthread, ptask, task, thread, thread_info->virtual_thread, send_begin, send_end, current_event, receive, TRUE, send_position);
						}
						else
							fprintf (stderr, "mpi2prv: Attention CommunicationQueues_ExtractSend returned send_begin = %p and send_end = %p\n", send_begin, send_end);
					}
#if defined(PARALLEL_MERGE)
					else
					{
						UINT64 log_r, phy_r;

						log_r = TIMESYNC (ptask-1, task-1, Get_EvTime(current_event));
						phy_r = TIMESYNC (ptask-1, task-1, Get_EvTime(receive));
						AddForeignRecv (phy_r, log_r, Get_EvTag(receive), ptask-1, task-1, thread-1,
							thread_info->virtual_thread-1, target_ptask-1, Get_EvTarget(receive), fset, MatchComms_GetZone(ptask, task));
					}
#endif
				}
			}
		}
	}

	trace_paraver_state (cpu, ptask, task, thread, current_time);
	trace_paraver_event (cpu, ptask, task, thread, current_time, EvType, EvValue);

	return 0;
}
static int SendRecv_Event (event_t * current_event, 
	unsigned long long current_time, unsigned int cpu, unsigned int ptask, 
	unsigned int task, unsigned int thread, FileSet_t *fset)
{
	thread_t *thread_info;
	task_t *task_info, *task_info_partner;
#if !defined(AVOID_SENDRECV)
	unsigned recv_thread, send_thread, recv_vthread, send_vthread;
	event_t *recv_begin, *recv_end, *send_begin, *send_end;
	off_t send_position;
#endif
	int EvComm = Get_EvComm (current_event);

	Switch_State (STATE_SENDRECVOP, (Get_EvValue(current_event) == EVT_BEGIN), ptask, task, thread);

	trace_paraver_state (cpu, ptask, task, thread, current_time);
	trace_paraver_event (cpu, ptask, task, thread, current_time, Get_EvEvent(current_event), Get_EvValue(current_event));

	thread_info = GET_THREAD_INFO(ptask, task, thread);
	task_info = GET_TASK_INFO(ptask, task);

	if (!get_option_merge_SkipSendRecvComms())
	{
		if (Get_EvValue (current_event) == EVT_BEGIN)
		{
			thread_info->Send_Rec = current_event;

			/* Treat the send part */
			if (MatchComms_Enabled(ptask, task))
				if (MPI_PROC_NULL != Get_EvTarget (thread_info->Send_Rec))
				{
					int target_ptask = intercommunicators_get_target_ptask( ptask, task, EvComm );

					if (isTaskInMyGroup (fset, target_ptask-1, Get_EvTarget(thread_info->Send_Rec)))
					{
#if defined(DEBUG)
						fprintf (stderr, "SENDRECV/SEND: TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d\n", current_time, Get_EvTime(thread_info->Send_Rec), task-1, Get_EvTarget(thread_info->Send_Rec), Get_EvTag(thread_info->Send_Rec));
#endif
						task_info_partner = GET_TASK_INFO(target_ptask, Get_EvTarget(thread_info->Send_Rec)+1);

						CommunicationQueues_ExtractRecv (task_info_partner->recv_queue, task-1, Get_EvTag (thread_info->Send_Rec), &recv_begin, &recv_end, &recv_thread, &recv_vthread, 0);

						if (recv_begin == NULL || recv_end == NULL)
						{
							off_t position;

#if defined(DEBUG)
							fprintf (stderr, "SENDRECV/SEND DID NOT find partner\n");
#endif
							position = WriteFileBuffer_getPosition (thread_info->file->wfb);
							CommunicationQueues_QueueSend (task_info->send_queue, thread_info->Send_Rec, current_event, position, thread, thread_info->virtual_thread, Get_EvTarget(thread_info->Send_Rec), Get_EvTag(thread_info->Send_Rec), 0);
							trace_paraver_unmatched_communication (1, ptask, task, thread, thread_info->virtual_thread, current_time, Get_EvTime(current_event), 1, target_ptask, Get_EvTarget(current_event)+1, 1, Get_EvSize(current_event), Get_EvTag(current_event));
						}
						else if (recv_begin != NULL && recv_end != NULL)
						{
#if defined(DEBUG)
							fprintf (stderr, "SENDRECV/SEND found partner\n");
#endif
							trace_communicationAt (ptask, task, thread, thread_info->virtual_thread, target_ptask, 1+Get_EvTarget(thread_info->Send_Rec), recv_thread, recv_vthread, thread_info->Send_Rec, current_event, recv_begin, recv_end, FALSE, 0);
						}
						else
							fprintf (stderr, "mpi2prv: Attention CommunicationQueues_ExtractRecv returned recv_begin = %p and recv_end = %p\n", recv_begin, recv_end);
					}
#if defined(PARALLEL_MERGE)
					else
					{
#if defined(DEBUG)
						fprintf (stdout, "SEND_CMD(%u): TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d >> PENDING\n", Get_EvEvent(current_event), current_time, Get_EvTime(current_event), task-1, Get_EvTarget(current_event), Get_EvTag(current_event));
#endif
						trace_pending_communication (ptask, task, thread, thread_info->virtual_thread, thread_info->Send_Rec, current_event, target_ptask, Get_EvTarget (thread_info->Send_Rec));
					}
#endif /* PARALLEL_MERGE */
					}

		}
		else if (Get_EvValue (current_event) == EVT_END)
		{
			thread_info->Recv_Rec = current_event;

			/* Treat the receive part */
			if (MatchComms_Enabled(ptask, task))
				if (MPI_PROC_NULL != Get_EvTarget (thread_info->Recv_Rec))
				{
					int target_ptask = intercommunicators_get_target_ptask( ptask, task, EvComm );

					if (isTaskInMyGroup (fset, target_ptask-1, Get_EvTarget(thread_info->Recv_Rec)))
					{
#if defined(DEBUG)
						fprintf (stderr, "SENDRECV/RECV: TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d\n", current_time, Get_EvTime(thread_info->Recv_Rec), task-1, Get_EvTarget(thread_info->Recv_Rec), Get_EvTag(thread_info->Recv_Rec));
#endif

						task_info_partner = GET_TASK_INFO(target_ptask, Get_EvTarget(thread_info->Recv_Rec)+1);

						CommunicationQueues_ExtractSend (task_info_partner->send_queue, task-1, Get_EvTag (thread_info->Recv_Rec), &send_begin, &send_end, &send_position, &send_thread, &send_vthread, 0);

						if (NULL == send_begin && NULL == send_end)
						{
#if defined(DEBUG)
							fprintf (stderr, "SENDRECV/RECV DID NOT find partner\n");
#endif
							CommunicationQueues_QueueRecv (task_info->recv_queue, thread_info->Send_Rec, current_event, thread, thread_info->virtual_thread, Get_EvTarget(thread_info->Recv_Rec), Get_EvTag(thread_info->Recv_Rec), 0);
						}
						else if (NULL != send_begin && NULL != send_end)
						{
#if defined(DEBUG)
							fprintf (stderr, "SENDRECV/RECV found partner\n");
#endif
							trace_communicationAt (target_ptask, 1+Get_EvTarget(thread_info->Recv_Rec), send_thread, send_vthread, ptask, task, thread, thread_info->virtual_thread, send_begin, send_end, thread_info->Send_Rec, thread_info->Recv_Rec, TRUE, send_position);
						}
						else
							fprintf (stderr, "mpi2prv: Attention CommunicationQueues_ExtractSend returned send_begin = %p and send_end = %p\n", send_begin, send_end);
					}
#if defined(PARALLEL_MERGE)
					else
					{
						UINT64 log_r, phy_r;

						log_r = TIMESYNC (ptask-1, task-1, Get_EvTime(thread_info->Send_Rec));
						phy_r = TIMESYNC (ptask-1, task-1, Get_EvTime(current_event));
						AddForeignRecv (phy_r, log_r, Get_EvTag(current_event), ptask-1, task-1, thread-1,
							thread_info->virtual_thread-1, target_ptask-1, Get_EvTarget(current_event), fset, MatchComms_GetZone(ptask, task));
					}
#endif /* PARALLEL_MERGE */
				}
		}
	}

	return 0;
}
static int Any_Send_Event (event_t * current_event,
	unsigned long long current_time, unsigned int cpu, unsigned int ptask,
	unsigned int task, unsigned int thread, FileSet_t *fset)
{
	unsigned recv_thread, recv_vthread, EvType, EvValue;
	thread_t *thread_info;
	task_t *task_info, *task_info_partner;
	event_t * recv_begin, * recv_end;
	int EvComm;

	EvType  = Get_EvEvent(current_event);
	EvValue = Get_EvValue(current_event);
	EvComm  = Get_EvComm (current_event);

	Switch_State (Get_State(EvType), (EvValue == EVT_BEGIN), ptask, task, thread);

	trace_paraver_state (cpu, ptask, task, thread, current_time);
	trace_paraver_event (cpu, ptask, task, thread, current_time, EvType, EvValue);

	thread_info = GET_THREAD_INFO(ptask, task, thread);
	task_info = GET_TASK_INFO(ptask, task);

	switch (EvValue)
	{
		case EVT_BEGIN:
			thread_info->Send_Rec = current_event;
		break;
		case EVT_END:
			if (MatchComms_Enabled(ptask, task))
			{
				if (MPI_PROC_NULL != Get_EvTarget (current_event))
				{
					int target_ptask = intercommunicators_get_target_ptask( ptask, task, EvComm );

					if (isTaskInMyGroup (fset, target_ptask-1, Get_EvTarget(current_event)))
					{
#if defined(DEBUG)
						fprintf (stderr, "SEND_CMD(%u): TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d\n", EvType, current_time, Get_EvTime(current_event), task-1, Get_EvTarget(current_event), Get_EvTag(current_event));
#endif
						task_info_partner = GET_TASK_INFO(target_ptask, Get_EvTarget(current_event)+1);
						CommunicationQueues_ExtractRecv (task_info_partner->recv_queue, task-1, Get_EvTag (current_event), &recv_begin, &recv_end, &recv_thread, &recv_vthread, 0);

						if (recv_begin == NULL || recv_end == NULL)
						{
							off_t position;

#if defined(DEBUG)
							fprintf (stderr, "SEND_CMD(%u) DID NOT find receiver\n", EvType);
#endif
							position = WriteFileBuffer_getPosition (thread_info->file->wfb);
							CommunicationQueues_QueueSend (task_info->send_queue, thread_info->Send_Rec, current_event, position, thread, thread_info->virtual_thread, Get_EvTarget(current_event), Get_EvTag(current_event), 0);
							trace_paraver_unmatched_communication (1, ptask, task, thread, thread_info->virtual_thread, current_time, Get_EvTime(current_event), 1, target_ptask, Get_EvTarget(current_event)+1, 1, Get_EvSize(current_event), Get_EvTag(current_event));
						}
						else
						{
#if defined(DEBUG)
							fprintf (stderr, "SEND_CMD(%u) find receiver\n", EvType);
#endif
							trace_communicationAt (ptask, task, thread, thread_info->virtual_thread, target_ptask, 1+Get_EvTarget(current_event), recv_thread, recv_vthread, thread_info->Send_Rec, current_event, recv_begin, recv_end, FALSE, 0);
						}
					}
#if defined(PARALLEL_MERGE)
					else
					{
#if defined(DEBUG)
						fprintf (stdout, "SEND_CMD(%u): TIME/TIMESTAMP %lld/%lld IAM %d PARTNER %d tag %d >> PENDING\n", Get_EvEvent(current_event), current_time, Get_EvTime(current_event), task-1, Get_EvTarget(current_event), Get_EvTag(current_event));
#endif
						trace_pending_communication (ptask, task, thread, thread_info->virtual_thread, thread_info->Send_Rec, current_event, target_ptask, Get_EvTarget (current_event));
					}
#endif
				}
			}
		break;
	}
	return 0;
}
/******************************************************************************
 *** Paraver_WriteHeader
 ******************************************************************************/
static int Paraver_WriteHeader (FileSet_t *fset, int numtasks, int taskid,
	unsigned num_appl, unsigned long long Ftime, struct fdz_fitxer prv_fd,
	struct Pair_NodeCPU *info)
{
	int NumNodes;
	char Header[1024];
	unsigned threads, task, ptask, node;
	TipusComunicador com;
	int final;

	UNREFERENCED_PARAMETER(numtasks);
#if !defined(PARALLEL_MERGE)
	UNREFERENCED_PARAMETER(fset);
#endif

	if (taskid == 0)
	{
		char Date[80];
		time_t h;

		time (&h);
		strftime (Date, 80, "%d/%m/%Y at %H:%M", localtime (&h));

		/* Write the Paraver header */
#if SIZEOF_LONG == 8
		sprintf (Header, "#Paraver (%s):%lu_ns:", Date, Ftime);
#elif SIZEOF_LONG == 4
		sprintf (Header, "#Paraver (%s):%llu_ns:", Date, Ftime);
#endif
		PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));

		NumNodes = 0;
		while (info[NumNodes].files != NULL)
			NumNodes++;

		sprintf (Header, "%d(", NumNodes);
		PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));

		if (NumNodes > 0)
		{
			sprintf (Header, "%d", info[0].CPUs);
			PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));

			NumNodes = 1;
			while (info[NumNodes].CPUs > 0)
			{
				sprintf (Header,",%d", info[NumNodes].CPUs);
				PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));
				NumNodes++;
			}
		}
		sprintf (Header, "):%d:", num_appl);
		PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));
	}

	/* For every application, write down its resources */
	for (ptask = 0; ptask < num_appl; ptask++)
	{
#if defined(PARALLEL_MERGE)
		unsigned *vthreads_count = Gather_Paraver_VirtualThreads (taskid, ptask,
			fset);
#endif

		if (taskid == 0)
		{
			ptask_t *ptask_info = GET_PTASK_INFO(ptask+1);
			task_t *last_task_info = GET_TASK_INFO(ptask+1,ptask_info->ntasks);

			sprintf (Header, "%d(", ptask_info->ntasks);
			PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));

			for (task = 0; task < ptask_info->ntasks-1; task++)
			{
				task_t *task_info = GET_TASK_INFO(ptask+1,task+1);

#if defined(PARALLEL_MERGE)
				threads = vthreads_count[task];
#else
				threads = task_info->num_virtual_threads; /*nthreads;*/
#endif
				node = task_info->nodeid;

				sprintf (Header, "%d:%d,", threads, node);
				PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));
			}
#if defined(PARALLEL_MERGE)
			threads = vthreads_count[ptask_info->ntasks-1];
#else
			threads = last_task_info->num_virtual_threads; /* nthreads */
#endif
			node = last_task_info->nodeid;

			/* Add the communicators info at the last application / ptask */
			if (ptask == num_appl-1)
				sprintf (Header, "%d:%d),%d", threads, node, numero_comunicadors());
			else
				sprintf (Header, "%d:%d),", threads, node);
			PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));

#if defined(PARALLEL_MERGE)
			free (vthreads_count);			
#endif
		}
	}

	if (taskid == 0)
	{
		sprintf (Header, "\n");
		PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));

		/* Write the communicator definition for every application */
		for (ptask = 1; ptask <= num_appl; ptask++)
		{
			/* Write the communicators created manually by the application */
			final = (primer_comunicador (&com) < 0);
			while (!final)
			{
				unsigned u;

				/* Write this communicator */
				sprintf (Header, "c:%d:%lu:%d", ptask, com.id, com.num_tasks);
				PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));
				for (u = 0; u < com.num_tasks; u++)
				{
					sprintf (Header, ":%d", com.tasks[u] + 1);
					PRVWRITECNTL (FDZ_WRITE (prv_fd, Header));
				}
				PRVWRITECNTL (FDZ_WRITE (prv_fd, "\n"));

				/* Get the next communicator */
				final = (seguent_comunicador (&com) < 0);
			}