@@ -2285,6 +2285,219 @@ static int __kmp_dispatch_next(ident_t *loc, int gtid, kmp_int32 *p_last,
22852285 return status;
22862286}
22872287
2288+ /* !
2289+ @ingroup WORK_SHARING
2290+ @param loc source location information
2291+ @param global_tid global thread number
2292+ @return Zero if the parallel region is not active and this thread should execute
2293+ all sections, non-zero otherwise.
2294+
2295+ Beginning of sections construct.
2296+ There are no implicit barriers in the "sections" calls, rather the compiler
2297+ should introduce an explicit barrier if it is required.
2298+
2299+ This implementation is based on __kmp_dispatch_init, using same constructs for
2300+ shared data (we can't have sections nested directly in omp for loop, there
2301+ should be a parallel region in between)
2302+ */
2303+ kmp_int32 __kmpc_sections_init (ident_t *loc, kmp_int32 gtid) {
2304+
2305+ int active;
2306+ kmp_info_t *th;
2307+ kmp_team_t *team;
2308+ kmp_uint32 my_buffer_index;
2309+ dispatch_shared_info_template<kmp_int32> volatile *sh;
2310+
2311+ KMP_DEBUG_ASSERT (__kmp_init_serial);
2312+
2313+ if (!TCR_4 (__kmp_init_parallel))
2314+ __kmp_parallel_initialize ();
2315+ __kmp_resume_if_soft_paused ();
2316+
2317+ /* setup data */
2318+ th = __kmp_threads[gtid];
2319+ team = th->th .th_team ;
2320+ active = !team->t .t_serialized ;
2321+ th->th .th_ident = loc;
2322+
2323+ KMP_COUNT_BLOCK (OMP_SECTIONS);
2324+ KD_TRACE (10 , (" __kmpc_sections: called by T#%d\n " , gtid));
2325+
2326+ if (active) {
2327+ // Setup sections in the same way as dynamic scheduled loops.
2328+ // We need one shared data: which section is to execute next.
2329+ // (in case parallel is not active, all sections will be executed on the
2330+ // same thread)
2331+ KMP_DEBUG_ASSERT (th->th .th_dispatch ==
2332+ &th->th .th_team ->t .t_dispatch [th->th .th_info .ds .ds_tid ]);
2333+
2334+ my_buffer_index = th->th .th_dispatch ->th_disp_index ++;
2335+
2336+ // reuse shared data structures from dynamic sched loops:
2337+ sh = reinterpret_cast <dispatch_shared_info_template<kmp_int32> volatile *>(
2338+ &team->t .t_disp_buffer [my_buffer_index % __kmp_dispatch_num_buffers]);
2339+ KD_TRACE (10 , (" __kmpc_sections_init: T#%d my_buffer_index:%d\n " , gtid,
2340+ my_buffer_index));
2341+
2342+ th->th .th_dispatch ->th_deo_fcn = __kmp_dispatch_deo_error;
2343+ th->th .th_dispatch ->th_dxo_fcn = __kmp_dispatch_dxo_error;
2344+
2345+ KD_TRACE (100 , (" __kmpc_sections_init: T#%d before wait: my_buffer_index:%d "
2346+ " sh->buffer_index:%d\n " ,
2347+ gtid, my_buffer_index, sh->buffer_index ));
2348+ __kmp_wait<kmp_uint32>(&sh->buffer_index , my_buffer_index,
2349+ __kmp_eq<kmp_uint32> USE_ITT_BUILD_ARG (NULL ));
2350+ // Note: KMP_WAIT() cannot be used there: buffer index and
2351+ // my_buffer_index are *always* 32-bit integers.
2352+ KMP_MB ();
2353+ KD_TRACE (100 , (" __kmpc_sections_init: T#%d after wait: my_buffer_index:%d "
2354+ " sh->buffer_index:%d\n " ,
2355+ gtid, my_buffer_index, sh->buffer_index ));
2356+
2357+ th->th .th_dispatch ->th_dispatch_pr_current =
2358+ nullptr ; // sections construct doesn't need private data
2359+ th->th .th_dispatch ->th_dispatch_sh_current =
2360+ CCAST (dispatch_shared_info_t *, (volatile dispatch_shared_info_t *)sh);
2361+ }
2362+
2363+ #if OMPT_SUPPORT && OMPT_OPTIONAL
2364+ if (ompt_enabled.ompt_callback_work ) {
2365+ ompt_team_info_t *team_info = __ompt_get_teaminfo (0 , NULL );
2366+ ompt_task_info_t *task_info = __ompt_get_task_info_object (0 );
2367+ ompt_callbacks.ompt_callback (ompt_callback_work)(
2368+ ompt_work_sections, ompt_scope_begin, &(team_info->parallel_data ),
2369+ &(task_info->task_data ), 0 , OMPT_GET_RETURN_ADDRESS (0 ));
2370+ }
2371+ #endif
2372+ KMP_PUSH_PARTITIONED_TIMER (OMP_sections);
2373+
2374+ return active;
2375+ }
2376+
2377+ /* !
2378+ @ingroup WORK_SHARING
2379+ @param loc source location information
2380+ @param global_tid global thread number
2381+ @param numberOfSections number of sections in the 'sections' construct
2382+ @return unsigned [from 0 to n) - number (id) of the section to execute next on
2383+ this thread. n (or any other number not in range) - nothing to execute on this
2384+ thread
2385+ */
2386+
2387+ kmp_int32 __kmpc_next_section (ident_t *loc, kmp_int32 gtid,
2388+ kmp_int32 numberOfSections) {
2389+
2390+ KMP_TIME_PARTITIONED_BLOCK (OMP_sections);
2391+
2392+ kmp_info_t *th = __kmp_threads[gtid];
2393+ #ifdef KMP_DEBUG
2394+ kmp_team_t *team = th->th .th_team ;
2395+ #endif
2396+
2397+ KD_TRACE (1000 , (" __kmp_dispatch_next: T#%d; number of sections:%d\n " , gtid,
2398+ numberOfSections));
2399+
2400+ // For serialized case we should not call this function:
2401+ KMP_DEBUG_ASSERT (!team->t .t_serialized );
2402+
2403+ dispatch_shared_info_template<kmp_int32> volatile *sh;
2404+
2405+ KMP_DEBUG_ASSERT (th->th .th_dispatch ==
2406+ &th->th .th_team ->t .t_dispatch [th->th .th_info .ds .ds_tid ]);
2407+
2408+ KMP_DEBUG_ASSERT (!(th->th .th_dispatch ->th_dispatch_pr_current ));
2409+ sh = reinterpret_cast <dispatch_shared_info_template<kmp_int32> volatile *>(
2410+ th->th .th_dispatch ->th_dispatch_sh_current );
2411+ KMP_DEBUG_ASSERT (sh);
2412+
2413+ kmp_int32 sectionIndex = 0 ;
2414+ bool moreSectionsToExecute = true ;
2415+
2416+ // Find section to execute:
2417+ sectionIndex = test_then_inc<kmp_int32>((kmp_int32 *)&sh->u .s .iteration );
2418+ if (sectionIndex >= numberOfSections) {
2419+ moreSectionsToExecute = false ;
2420+ }
2421+
2422+ // status == 0: no more sections to execute;
2423+ // OMPTODO: __kmpc_end_sections could be bypassed?
2424+ if (!moreSectionsToExecute) {
2425+ kmp_int32 num_done;
2426+
2427+ num_done = test_then_inc<kmp_int32>((kmp_int32 *)(&sh->u .s .num_done ));
2428+
2429+ if (num_done == th->th .th_team_nproc - 1 ) {
2430+ /* NOTE: release this buffer to be reused */
2431+
2432+ KMP_MB (); /* Flush all pending memory write invalidates. */
2433+
2434+ sh->u .s .num_done = 0 ;
2435+ sh->u .s .iteration = 0 ;
2436+
2437+ KMP_MB (); /* Flush all pending memory write invalidates. */
2438+
2439+ sh->buffer_index += __kmp_dispatch_num_buffers;
2440+ KD_TRACE (100 , (" __kmpc_next_section: T#%d change buffer_index:%d\n " , gtid,
2441+ sh->buffer_index ));
2442+
2443+ KMP_MB (); /* Flush all pending memory write invalidates. */
2444+
2445+ } // if
2446+
2447+ th->th .th_dispatch ->th_deo_fcn = NULL ;
2448+ th->th .th_dispatch ->th_dxo_fcn = NULL ;
2449+ th->th .th_dispatch ->th_dispatch_sh_current = NULL ;
2450+ th->th .th_dispatch ->th_dispatch_pr_current = NULL ;
2451+
2452+ #if OMPT_SUPPORT && OMPT_OPTIONAL
2453+ if (ompt_enabled.ompt_callback_dispatch ) {
2454+ ompt_team_info_t *team_info = __ompt_get_teaminfo (0 , NULL );
2455+ ompt_task_info_t *task_info = __ompt_get_task_info_object (0 );
2456+ ompt_data_t instance = ompt_data_none;
2457+ instance.ptr = OMPT_GET_RETURN_ADDRESS (0 );
2458+ ompt_callbacks.ompt_callback (ompt_callback_dispatch)(
2459+ &(team_info->parallel_data ), &(task_info->task_data ),
2460+ ompt_dispatch_section, instance);
2461+ }
2462+ #endif
2463+ KMP_POP_PARTITIONED_TIMER ();
2464+ }
2465+
2466+ return sectionIndex;
2467+ }
2468+
2469+ /* !
2470+ @ingroup WORK_SHARING
2471+ @param loc source location information
2472+ @param global_tid global thread number
2473+
2474+ End of "sections" construct.
2475+ Don't need to wait here: barrier is added separately when needed.
2476+ */
2477+ void __kmpc_end_sections (ident_t *loc, kmp_int32 gtid) {
2478+
2479+ kmp_info_t *th = __kmp_threads[gtid];
2480+ int active = !th->th .th_team ->t .t_serialized ;
2481+
2482+ KD_TRACE (100 , (" __kmpc_end_sections: T#%d called\n " , gtid));
2483+
2484+ if (!active) {
2485+ // In active case call finalization is done in __kmpc_next_section
2486+ #if OMPT_SUPPORT && OMPT_OPTIONAL
2487+ if (ompt_enabled.ompt_callback_work ) {
2488+ ompt_team_info_t *team_info = __ompt_get_teaminfo (0 , NULL );
2489+ ompt_task_info_t *task_info = __ompt_get_task_info_object (0 );
2490+ ompt_callbacks.ompt_callback (ompt_callback_work)(
2491+ ompt_work_sections, ompt_scope_end, &(team_info->parallel_data ),
2492+ &(task_info->task_data ), 0 , OMPT_GET_RETURN_ADDRESS (0 ));
2493+ }
2494+ #endif
2495+ KMP_POP_PARTITIONED_TIMER ();
2496+ }
2497+
2498+ KD_TRACE (100 , (" __kmpc_end_sections: T#%d returned\n " , gtid));
2499+ }
2500+
22882501template <typename T>
22892502static void __kmp_dist_get_bounds (ident_t *loc, kmp_int32 gtid,
22902503 kmp_int32 *plastiter, T *plower, T *pupper,
0 commit comments