If there is at least one 'copyprivate' clause is associated with the single directive, the following code is generated:
i32 did_it = 0; \\ for 'copyprivate' clause if(__kmpc_single(ident_t *, gtid)) { SingleOpGen(); __kmpc_end_single(ident_t *, gtid); did_it = 1; \\ for 'copyprivate' clause } <copyprivate_list>[0] = &var0; ... <copyprivate_list>[n] = &varn; call __kmpc_copyprivate(ident_t *, gtid, <copyprivate_list_size>, <copyprivate_list>, <copy_func>, did_it); ... void <copy_func>(void* LHSArg, void *RHSArg) { Dst = (void*[n])(LHSArg); Src = (void*[n])(RHSArg); Dst[0] = Src[0]; ... Dst[n] = Src[n]; }
All list items from all 'copyprivate' clauses are gathered into single <copyprivate list> (<copyprivate_list_size> is a size in bytes of this list) and <copy_func> is used to propagate values of private or threadprivate variables from the 'single' region to other implicit threads from outer 'parallel' region.