예제 #1
0
/*
	指导语句:	#pragma omp for
	结构功能:	for开始函数(无parallel时)
	函数功能:	创建一个任务共享结构
*/
int GOMP_loop_dynamic_start (long p1, long p2, long p3, long p4, long *p5, long *p6)
{
	int res = 0;
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_loop_dynamic_start";
	Event.eid = 220;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	GOMP_loop_dynamic_start_real = (int(*)(long,long,long,long,long*,long*)) dlsym (RTLD_NEXT, "GOMP_loop_dynamic_start");
	if (GOMP_loop_dynamic_start_real != NULL)
	{

		Event.starttime = gettime ();
		res = GOMP_loop_dynamic_start_real (p1, p2, p3, p4, p5, p6);
		Event.endtime = gettime ();
		Record (&Event, OMPI_TRACE);
	}
	else
	{
		printf_d("GOMP_loop_dynamic_start is not hooked! exiting!!\n");
	}
	return res;
}
예제 #2
0
/*
	指导语句:	#pragma omp sections
	结构功能:	section调度函数
	函数功能:	当一个线程结束其执行的任务时,调用该函数分配下一个任务
*/
unsigned GOMP_sections_next (void)
{
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_sections_next";
	Event.eid = 224;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);
	unsigned res = 0;

	GOMP_sections_next_real=(unsigned(*)(void)) dlsym (RTLD_NEXT, "GOMP_sections_next");
	if (GOMP_sections_next_real != NULL)
	{
		Event.starttime=gettime();
		res = GOMP_sections_next_real();
		Event.endtime=gettime();
		Record(&Event, OMPI_TRACE);
	}
	else
	{
		printf_d("GOMP_sections_next is not hooked! exiting!!\n");
	}
	return res;
}
예제 #3
0
int main ( int argc, char **argv )
{
   int result = 0;
   int i;
   nanos_wd_props_t props = {
     .mandatory_creation = true,
     .tied = false
   };

   int level = omp_get_level();
   int ancestor_num = omp_get_ancestor_thread_num( level );
   int team_size = omp_get_team_size(level);
   int active_level = omp_get_active_level();
   int in_final = omp_in_final();


   printf ( " OpenMP API calls simple test:\n" );
   printf ( "\tomp_get_level() = %d\n", level );
   printf ( "\tomp_get_ancestor_thread_num(%d) = %d\n", level, ancestor_num );
   printf ( "\tomp_get_team_size(%d) = %d\n", level, team_size );
   printf ( "\tomp_get_active_level() = %d\n", active_level );
   printf ( "\tomp_in_final() = %d\n", in_final );

   if ( in_final != 0 )
      result = 1;
   if ( active_level != 0 )
      result = 2;
   if ( level != 0 )
      result = 3;
   if ( ancestor_num != 0 )
      result = 4;

   return result;
}
예제 #4
0
/*
	指导语句:	#pragma omp for
	结构功能:	for预初始化函数(有parallel时)
	函数功能:	预初始化一个任务共享结构
*/
void GOMP_parallel_loop_guided_start(void *p1, void *p2, unsigned p3, long p4, long p5, long p6, long p7)
{
	TaskInfo old_task;
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_parallel_loop_guided_start";
	Event.eid = 212;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);
	
	old_task = current_task;

	//If current task is not exist, create a new task
	if (current_task.flag == 0)
	{
		current_task = create_itask ();
		Event.task_state_start = TASK_CREATE;
	}
	else
		Event.task_state_start = TASK_SUSPEND;

	create_team (current_task);
	
	Event.p_task_id_start = current_task.task_parent_id;
	Event.task_id_start = current_task.task_id;

	GOMP_parallel_loop_guided_start_real=(void(*)(void*,void*,unsigned, long, long, long, long)) dlsym (RTLD_NEXT, "GOMP_parallel_loop_guided_start");
	if (GOMP_parallel_loop_guided_start_real != NULL)
	{
		pardo_uf = (void(*)(void*))p1;
		pardo_uf_id++;

		/*if (PAPI == PAPI_ON)
			retVal = PAPI_thread_init(get_thread_num());
		if (retVal != PAPI_OK)
			ERROR_RETURN(retVal);*/
		
		Event.starttime=gettime();
		GOMP_parallel_loop_guided_start_real (callme_pardo, p2, p3, p4, p5, p6, p7);
		Event.endtime=gettime();
	}
	else
	{
		printf_d("GOMP_parallel_loop_guided_start is not hooked! exiting!!\n");
	}

	Event.p_task_id_end = current_task.task_parent_id;
	Event.task_id_end = current_task.task_id;
	
	if (old_task.flag == 0)
		Event.task_state_end = TASK_START;
	else
		Event.task_state_end = TASK_RESUME;

	Record(&Event, OMPI_TRACE);
}
예제 #5
0
/*
	指导语句:	#pragma omp task
	结构功能:	task用户子函数
	函数功能:	task中调用的用户子函数
*/
static void callme_task (void *p1)
{
	TaskInfo old_task;
	struct eTask *task;
	char fun_name[30] = "Task_User_do_fun_";
	char id [10];

	Record_Event Event = Event_init ();

	old_task = current_task;
	task = etask_schedule ();
	current_task = task.task_info;
	current_task.thread_id = get_thread_id (get_level ());
//	current_etask = task;

	itoa (task_uf_id, id);
	strcat (fun_name, id);
	Event.event_name = fun_name;
	Event.eid = 235;
	Event.type = NONE;

	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	Event.p_task_id_start = current_task.task_parent_id;
	Event.task_id_start = current_task.task_id;
	Event.task_state_start = TASK_START;
	if (task_uf == NULL)	
	{
		printf_d("Error! Invalid initialization of 'task_uf'\n");
		return ;
	}
	if (PAPI == PAPI_ON)
	{
		PAPI_get_info (fun_name, 0, PAPI_THREAD);
		Event.starttime = gettime ();
		task_uf (p1);
		Event.endtime = gettime ();
		PAPI_get_info (fun_name, 1, PAPI_THREAD);
	}
	else 
	{
		Event.starttime = gettime ();
		task_uf (p1);
		Event.endtime = gettime ();
	}

	Event.p_task_id_end = current_task.task_parent_id;
	Event.task_id_end = current_task.task_id;
	Event.task_state_end = TASK_END;
	remove_etask (task);
	current_task = old_task;

	Record (&Event, OMPI_TRACE);
}
예제 #6
0
/*
	指导语句:	#pragma omp parallel
	结构功能:	parallel用户子函数
	函数功能:	parallel中调用的用户子函数
*/
static void callme_par (void *p1)
{
	TaskInfo old_task;

	char fun_name[30] = "Parallel_User_fun_";
	char id [10];
	Record_Event Event = Event_init ();

	old_task = current_task;
	current_task = create_itask ();
	//Is it necessary to add this task to the thread team ?
	add_itask (current_task);
	
	itoa (par_uf_id, id);
	strcat (fun_name, id);
	Event.event_name = fun_name;
	Event.eid = 234;
	Event.type = NONE;

	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	Event.p_task_id_start = current_task.task_parent_id;
	Event.task_id_start = current_task.task_id;
	Event.task_state_start = TASK_CREATE;

	if (par_uf == NULL)
	{
		printf_d("Error! Invalid initialization of 'par_uf'\n");
		return ;
	}

	if (PAPI == PAPI_ON)
	{
		PAPI_get_info (fun_name, 0, PAPI_THREAD);
		Event.starttime = gettime ();
		par_uf (p1);
		Event.endtime = gettime ();
		PAPI_get_info (fun_name, 1, PAPI_THREAD);
	}
	else 
	{
		Event.starttime = gettime ();
		par_uf (p1);
		Event.endtime = gettime ();
	}

	Event.p_task_id_end = current_task.task_parent_id;
	Event.task_id_end = current_task.task_id;
	Event.task_state_end = TASK_END;
	remove_itask (current_task);
	current_task = old_task;
	
	Record (&Event, OMPI_TRACE);
}
예제 #7
0
void GOMP_task (void *p1, void *p2, void *p3,long p4, long p5, _Bool p6, unsigned p7)
{
	struct eTask *task;
	int old_block = block_statue;
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_task";
	Event.eid = 229;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	if (current_task.flag == 1)
	{
		Event.p_task_id_start = current_task.task_parent_id;
		Event.task_id_start = current_task.task_id;
		Event.task_state_start = TASK_CREATE;
	}

	if (p6)
	{
		/*Create a task that will be executed immediately*/
		block_statue = RUN_AT_ONCE_BLOCK;
	}
	else
	{
		task = create_etask ();
		add_etask (task);
	}
	

	GOMP_task_real = (void(*)(void *,void *,void *,long,long,_Bool,unsigned))dlsym(RTLD_NEXT,"GOMP_task");

	if(GOMP_task_real != NULL)
	{
		task_uf = (void(*)(void*))p1;
		task_uf_id++;

		Event.starttime = gettime();
		GOMP_task_real (callme_task, p2, p3, p4, p5, p6, p7);
		Event.endtime = gettime();
	}

	block_statue = old_block;

	if (current_task.flag == 1)
	{
		Event.p_task_id_end = current_task.task_parent_id;
		Event.task_id_end = current_task.task_id;
		Event.task_state_end = TASK_RESUME;
	}

	Record(&Event, OMPI_TRACE);
}
예제 #8
0
/*
	指导语句:	#pragma omp parallel
	结构功能:	parallel开始函数
	函数功能:	初始化一个parallel并行结构
*/
void GOMP_parallel_start (void *p1, void *p2, unsigned p3)
{
	TaskInfo old_task;

	Record_Event Event = Event_init ();										//初始化
	Event.event_name = "GOMP_parallel_start";								//获取函数名
	Event.eid = 200;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();										//获取线程编号
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	old_task = current_task;

	//If current task is not exist, create a new task
	if (current_task.flag == 0)
	{
		current_task = create_itask ();
		Event.task_state_start = TASK_CREATE;
	}
	else
		Event.task_state_start = TASK_SUSPEND;

	create_team (current_task);
	
	Event.p_task_id_start = current_task.task_parent_id;
	Event.task_id_start = current_task.task_id;

	/*dlsym函数返回 GOMP_parallel_start 在动态链接库中的下一个地址,供调用使用*/
	GOMP_parallel_start_real = (void(*)(void*,void*,unsigned))dlsym (RTLD_NEXT, "GOMP_parallel_start");
	if (GOMP_parallel_start_real != NULL)
	{	
		par_uf = (void(*)(void*))p1;										//调用子函数的包装函数
		par_uf_id++;
		
		Event.starttime = gettime();										//获取开始时间
		GOMP_parallel_start_real (callme_par, p2, p3);						//调用OpenMP库中的GOMP_parallel_start()实现功能
		Event.endtime = gettime ();											//获取结束时间
	}
	else
	{
		printf_d ("GOMP_parallel_start is not hooked! exiting!!\n");
	}

	Event.p_task_id_end = current_task.task_parent_id;
	Event.task_id_end = current_task.task_id;
	
	if (old_task.flag == 0)
		Event.task_state_end = TASK_START;
	else
		Event.task_state_end = TASK_RESUME;
	Record (&Event, OMPI_TRACE);
}
예제 #9
0
int get_thread_id (int level)
{
	int thread_id = 0;

	if (level < 0)
		return -1;
	
	while (level > 0)
		thread_id = thread_id * MAX_THREAD_NUM + omp_get_ancestor_thread_num (level--);

	return thread_id;
}
예제 #10
0
/*
	指导语句:	#pragma omp parallel for
	结构功能:	for调度函数
	函数功能:	当一个线程完成指定给它的任务时,调用该函数分配下个任务
*/
int GOMP_loop_guided_next(long *p1, long *p2)
{
	int res = 0;
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_loop_guided_next";
	Event.eid = 216;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	Event.p_task_id_start = current_task.task_parent_id;
	Event.task_id_start = current_task.task_id;
	Event.task_state_start= TASK_END;

	GOMP_loop_guided_next_real=(int(*)(long*,long*)) dlsym (RTLD_NEXT, "GOMP_loop_guided_next");

	if (GOMP_loop_guided_next_real != NULL)
	{
		Event.starttime=gettime();
		res = GOMP_loop_guided_next_real (p1, p2);
		Event.endtime=gettime();
		Record(&Event, OMPI_TRACE);
	}
	else
	{
		printf_d("GOMP_loop_guided_next is not hooked! exiting!!\n");
	}

	if (res == 1)																//Create a new task for this thread
	{
		current_task = create_itask ();
		Event.p_task_id_end = current_task.task_parent_id;
		Event.task_id_end= current_task.task_id;
		Event.task_state_end = TASK_CREATE;
	}
	else
	{
		current_task = get_current_task ();
		if (current_task.flag == 1)
		{
			Event.p_task_id_end = current_task.task_parent_id;
			Event.task_id_end= current_task.task_id;
			Event.task_state_end = TASK_RESUME;
		}
	}

	Record (&Event, OMPI_TRACE);
	return res;
}
예제 #11
0
void mergesortstat(I b, I e, I bb)
{
	if(!mergesortstat_debug(-1))
		return;
	char buf[128];
	sprintf(buf,"Start-End %08d-%08d Team %02d Thread/Max %02d/%02d Level %02d Parent %02d\n",
		(int)(b-bb),(int)(e-bb),
		omp_get_team_num(),
		omp_get_thread_num(),
		omp_get_num_threads(),
		omp_get_level(),
		omp_get_ancestor_thread_num (omp_get_level())
		);
	#pragma omp critical (io)
	{
		std::cout << buf << std::flush;
	}
}
예제 #12
0
void GOMP_barrier (void)
{
	TaskInfo old_task;
	int old_block = block_statue;
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_barrier";
	Event.eid = 202;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	old_task = current_task;
	if (current_task.flag == 1)
	{
		Event.p_task_id_start = current_task.task_parent_id;
		Event.task_id_start = current_task.task_id;
		Event.task_state_start = TASK_SUSPEND;
	}
	
	GOMP_barrier_real = (void(*)(void)) dlsym (RTLD_NEXT, "GOMP_barrier");

	block_statue = BARRIER_BLOCK;
	if (GOMP_barrier_real != NULL)
	{
		Event.starttime = gettime();
		GOMP_barrier_real ();
		Event.endtime = gettime ();
	}
	else
		printf_d ("GOMP_barrier is not hooked! exiting!!\n");

	block_statue = old_block;
	current_task = old_task;

	if (current_task.flag == 1)
	{
		Event.p_task_id_end = current_task.task_parent_id;
		Event.task_id_end = current_task.task_id;
		Event.task_state_end = TASK_RESUME;
	}

	Record (&Event, OMPI_TRACE);
}
예제 #13
0
/*
	指导语句:	#pragma omp parallel for
	结构功能:	for结束函数
	函数功能:	结束一个任务共享结构,不同步所有线程
*/
void GOMP_loop_end_nowait (void)
{
	TaskInfo old_task;
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_loop_end_nowait";
	Event.eid = 222;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	old_task = current_task;
	if (current_task.flag == 1)
	{
		Event.p_task_id_start = current_task.task_parent_id;
		Event.task_id_start = current_task.task_id;
		Event.task_state_start = TASK_WAIT;
	}

	GOMP_loop_end_nowait_real=(void(*)(void)) dlsym (RTLD_NEXT, "GOMP_loop_end_nowait");
	if (GOMP_loop_end_nowait_real != NULL)
	{
		Event.starttime=gettime();
		GOMP_loop_end_nowait_real();
		Event.endtime=gettime();
	}
	else
	{
		printf_d("GOMP_loop_end_nowait is not hooked! exiting!!\n");
	}

	current_task = old_task;
	Event.p_task_id_end = current_task.task_parent_id;
	Event.task_id_end = current_task.task_id;
	Event.task_state_end = TASK_END;

	remove_team ();
	current_task = get_current_task ();

	Record(&Event, OMPI_TRACE);
}
예제 #14
0
void GOMP_taskwait (void)
{
	TaskInfo old_task;
	int old_block = block_statue;
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_taskwait";
	Event.eid = 228;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	old_task = current_task;
	if (current_task.flag == 1)
	{
		Event.p_task_id_start = current_task.task_parent_id;
		Event.task_id_start = current_task.task_id;
		Event.task_state_start = TASK_SUSPEND;
	}

	GOMP_taskwait_real = (void(*)(void))dlsym(RTLD_NEXT,"GOMP_taskwait");

	block_statue = TASKWAIT_BLOCK;
	if(GOMP_taskwait_real != NULL)
	{
		Event.starttime = gettime();
		GOMP_taskwait_real ();
		Event.endtime = gettime ();
	}
	block_statue = old_block;
	current_task = old_task;
	if (current_task.flag == 1)
	{
		Event.p_task_id_end = current_task.task_parent_id;
		Event.task_id_end = current_task.task_id;
		Event.task_state_end = TASK_RESUME;
	}

	Record (&Event, OMPI_TRACE);
}
예제 #15
0
void GOMP_critical_name_end(void **p1)
{
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_critical_name_end";
	Event.eid = 204;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	GOMP_critical_name_end_real=(void(*)(void**)) dlsym (RTLD_NEXT, "GOMP_critical_name_end");
	if (GOMP_critical_name_end_real != NULL)
	{
		Event.starttime=gettime();
		GOMP_critical_name_end_real (p1);
		Event.endtime=gettime();
		Record(&Event, OMPI_TRACE);
	}
	else
	{
		printf_d("GOMP_critical_name_end is not hooked! exiting!!\n");
	}
}
예제 #16
0
void omp_unset_lock (int *p1)
{
	Record_Event Event = Event_init ();
	Event.event_name = "omp_unset_lock";
	Event.eid = 231;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	omp_unset_lock_real = (void(*)(int*)) dlsym (RTLD_NEXT, "omp_unset_lock");
	if(omp_unset_lock_real!= NULL)
	{
		Event.starttime = gettime ();
		omp_unset_lock_real (p1);
		Event.endtime = gettime ();
		Record (&Event, OMPI_TRACE);
	}
	else
	{
		printf_d ("omp_unset_lock is not hooked! exiting!!\n");
	}
}
예제 #17
0
void GOMP_parallel_sections_start(void *p1, void *p2, unsigned p3, unsigned p4)
{
	Record_Event Event = Event_init ();
	Event.event_name = "GOMP_parallel_sections_start";
	Event.eid = 227;
	Event.type = NONE;
	Event.omp_rank = get_thread_num ();
	Event.omp_level = get_level ();
	Event.p_rank = omp_get_ancestor_thread_num (get_level () - 1);

	GOMP_parallel_sections_start_real=(void(*)(void*,void*,unsigned,unsigned)) dlsym (RTLD_NEXT, "GOMP_parallel_sections_start");
	if (GOMP_parallel_sections_start_real != NULL)
	{
		Event.starttime=gettime();
		GOMP_parallel_sections_start_real (p1, p2, p3, p4);
		Event.endtime=gettime();
		Record(&Event, OMPI_TRACE);
	}
	else
	{
		printf_d("GOMP_parallel_sections_start is not hooked! exiting!!\n");
	}
}
예제 #18
0
파일: fortran.c 프로젝트: chinabin/gcc-tiny
int32_t
omp_get_ancestor_thread_num_8_ (const int64_t *level)
{
  return omp_get_ancestor_thread_num (TO_INT (*level));
}
예제 #19
0
파일: fortran.c 프로젝트: chinabin/gcc-tiny
int32_t
omp_get_ancestor_thread_num_ (const int32_t *level)
{
  return omp_get_ancestor_thread_num (*level);
}
예제 #20
0
파일: target-6.c 프로젝트: 0day-ci/gcc
int
main ()
{
  omp_set_dynamic (0);
  omp_set_nested (1);
  if (omp_in_parallel ())
    abort ();
  #pragma omp parallel num_threads (3)
    if (omp_get_thread_num () == 2)
      {
	if (!omp_in_parallel ())
	  abort ();
	#pragma omp parallel num_threads (3)
	  if (omp_get_thread_num () == 1)
	    {
	      if (!omp_in_parallel ()
		  || omp_get_level () != 2
		  || omp_get_ancestor_thread_num (0) != 0
		  || omp_get_ancestor_thread_num (1) != 2
		  || omp_get_ancestor_thread_num (2) != 1
		  || omp_get_ancestor_thread_num (3) != -1)
		abort ();
	      #pragma omp target if (0)
		{
		  if (omp_in_parallel ()
		      || omp_get_level () != 0
		      || omp_get_ancestor_thread_num (0) != 0
		      || omp_get_ancestor_thread_num (1) != -1)
		    abort ();
		  #pragma omp parallel num_threads (2)
		  {
		    if (!omp_in_parallel ()
			|| omp_get_level () != 1
			|| omp_get_ancestor_thread_num (0) != 0
			|| omp_get_ancestor_thread_num (1)
			   != omp_get_thread_num ()
			|| omp_get_ancestor_thread_num (2) != -1)
		      abort ();
		  }
		}
	      #pragma omp target if (0)
		{
		  #pragma omp teams thread_limit (2)
		    {
		      if (omp_in_parallel ()
			  || omp_get_level () != 0
			  || omp_get_ancestor_thread_num (0) != 0
			  || omp_get_ancestor_thread_num (1) != -1)
			abort ();
		      #pragma omp parallel num_threads (2)
		      {
			if (!omp_in_parallel ()
			    || omp_get_level () != 1
			    || omp_get_ancestor_thread_num (0) != 0
			    || omp_get_ancestor_thread_num (1)
			       != omp_get_thread_num ()
			    || omp_get_ancestor_thread_num (2) != -1)
			  abort ();
		      }
		    }
		}
	    }
      }
  return 0;
}
예제 #21
0
파일: nested-3.c 프로젝트: 0day-ci/gcc
int
main (void)
{
  int e[3];

  memset (e, '\0', sizeof (e));
  omp_set_nested (1);
  omp_set_dynamic (0);
  if (omp_in_parallel ()
      || omp_get_level () != 0
      || omp_get_ancestor_thread_num (0) != 0
      || omp_get_ancestor_thread_num (-1) != -1
      || omp_get_ancestor_thread_num (1) != -1
      || omp_get_team_size (0) != 1
      || omp_get_team_size (-1) != -1
      || omp_get_team_size (1) != -1
      || omp_get_active_level () != 0)
    abort ();
#pragma omp parallel num_threads (4)
  {
    int tn1 = omp_get_thread_num ();
    if (omp_in_parallel () != 1
	|| omp_get_num_threads () != 4
	|| tn1 >= 4 || tn1 < 0
	|| omp_get_level () != 1
	|| omp_get_ancestor_thread_num (0) != 0
	|| omp_get_ancestor_thread_num (1) != tn1
	|| omp_get_ancestor_thread_num (-1) != -1
	|| omp_get_ancestor_thread_num (2) != -1
	|| omp_get_team_size (0) != 1
	|| omp_get_team_size (1) != omp_get_num_threads ()
	|| omp_get_team_size (-1) != -1
	|| omp_get_team_size (2) != -1
	|| omp_get_active_level () != 1)
      #pragma omp atomic
	e[0] += 1;
    #pragma omp parallel if (0) num_threads(5) firstprivate(tn1)
    {
      int tn2 = omp_get_thread_num ();
      if (omp_in_parallel () != 1
	  || omp_get_num_threads () != 1
	  || tn2 != 0
	  || omp_get_level () != 2
	  || omp_get_ancestor_thread_num (0) != 0
	  || omp_get_ancestor_thread_num (1) != tn1
	  || omp_get_ancestor_thread_num (2) != tn2
	  || omp_get_ancestor_thread_num (-1) != -1
	  || omp_get_ancestor_thread_num (3) != -1
	  || omp_get_team_size (0) != 1
	  || omp_get_team_size (1) != 4
	  || omp_get_team_size (2) != 1
	  || omp_get_team_size (-1) != -1
	  || omp_get_team_size (3) != -1
	  || omp_get_active_level () != 1)
	#pragma omp atomic
	  e[1] += 1;
      #pragma omp parallel num_threads(2) firstprivate(tn1, tn2)
      {
	int tn3 = omp_get_thread_num ();
	if (omp_in_parallel () != 1
	    || omp_get_num_threads () != 2
	    || tn3 > 1 || tn3 < 0
	    || omp_get_level () != 3
	    || omp_get_ancestor_thread_num (0) != 0
	    || omp_get_ancestor_thread_num (1) != tn1
	    || omp_get_ancestor_thread_num (2) != tn2
	    || omp_get_ancestor_thread_num (3) != tn3
	    || omp_get_ancestor_thread_num (-1) != -1
	    || omp_get_ancestor_thread_num (4) != -1
	    || omp_get_team_size (0) != 1
	    || omp_get_team_size (1) != 4
	    || omp_get_team_size (2) != 1
	    || omp_get_team_size (3) != 2
	    || omp_get_team_size (-1) != -1
	    || omp_get_team_size (4) != -1
	    || omp_get_active_level () != 2)
	  #pragma omp atomic
	    e[2] += 1;
      }
    }
  }
  if (e[0] || e[1] || e[2])
    abort ();
  return 0;
}