Browse Source

2011-06-14 Antoniu Pop <antoniu.pop@gmail.com>

libgomp/
gcc/
	Revert and correct some of the changes from last commit.




git-svn-id: svn://gcc.gnu.org/svn/gcc/branches/omp-stream@175027 138bc75d-0d04-0410-961f-82ee72b054a4
ompstream
apop 11 years ago
parent
commit
2a002cb87f
  1. 11
      gcc/builtin-types.def
  2. 4
      gcc/c-parser.c
  3. 1
      gcc/c-typeck.c
  4. 137
      gcc/gimplify.c
  5. 48
      gcc/omp-builtins.def
  6. 7320
      gcc/omp-low.c
  7. 4
      gcc/tree.c
  8. 18
      gcc/tree.h
  9. 12
      libgomp/libgomp.map
  10. 30
      libgomp/libgomp_g.h
  11. 15
      libgomp/omp.h.in
  12. 460
      libgomp/stream.c
  13. 69
      libgomp/stream.h

11
gcc/builtin-types.def

@ -219,6 +219,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32)
DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64)
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_INT, BT_PTR, BT_INT)
DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_PTR, BT_BOOL, BT_PTR)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
@ -318,6 +319,9 @@ DEF_FUNCTION_TYPE_2 (BT_FN_ULL_PTR_ULL,
BT_ULONGLONG, BT_PTR, BT_ULONGLONG)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_ULL,
BT_VOID, BT_PTR, BT_ULONGLONG)
DEF_FUNCTION_TYPE_2 (BT_FN_PTR_PTR_PTR,
BT_PTR, BT_PTR, BT_PTR)
DEF_FUNCTION_TYPE_2 (BT_FN_PTR_PTR_ULL, BT_PTR, BT_PTR, BT_ULONGLONG)
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
@ -388,6 +392,10 @@ DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_INT_SIZE, BT_PTR,
BT_CONST_PTR, BT_INT, BT_SIZE)
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_SIZE_ULL_PTR,
BT_PTR, BT_SIZE, BT_ULONGLONG, BT_PTR)
DEF_FUNCTION_TYPE_3 (BT_FN_ULL_PTR_ULL_ULL,
BT_ULONGLONG, BT_PTR, BT_ULONGLONG, BT_ULONGLONG)
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_ULL_ULL,
BT_PTR, BT_PTR, BT_ULONGLONG, BT_ULONGLONG)
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
@ -441,6 +449,9 @@ DEF_FUNCTION_TYPE_7 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
BT_ULONGLONG, BT_ULONGLONG,
BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_LONG_BOOL,
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR,
BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, BT_LONG, BT_BOOL)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_INT_VAR, BT_INT)

4
gcc/c-parser.c

@ -7364,7 +7364,6 @@ c_parser_omp_stream_clause (c_parser *parser,
OMP_CLAUSE_STREAM_ID (omp_clause) = stream_id;
OMP_CLAUSE_STREAM_SUB (omp_clause) = stream_idx;
if (c_parser_next_token_is (parser, CPP_LSHIFT)
|| c_parser_next_token_is (parser, CPP_RSHIFT))
{
@ -8768,7 +8767,8 @@ c_parser_omp_single (location_t loc, c_parser *parser)
| (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (1u << PRAGMA_OMP_CLAUSE_SHARED)) \
| (1u << PRAGMA_OMP_CLAUSE_INPUT) \
| (1u << PRAGMA_OMP_CLAUSE_OUTPUT)
| (1u << PRAGMA_OMP_CLAUSE_OUTPUT) \
| (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS)
static tree
c_parser_omp_task (location_t loc, c_parser *parser)

1
gcc/c-typeck.c

@ -10231,6 +10231,7 @@ c_finish_omp_clauses (tree clauses)
case OMP_CLAUSE_FIRSTPRIVATE:
name = "firstprivate";
t = OMP_CLAUSE_DECL (c);
OMP_CLAUSE_VIEW_VAR_KIND (c) = OMP_CLAUSE_VIEW_VAR_UNSPECIFIED;
need_complete = true;
need_implicitly_determined = true;
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)

137
gcc/gimplify.c

@ -5724,6 +5724,9 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
goto do_add;
case OMP_CLAUSE_FIRSTPRIVATE:
flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
if (OMP_CLAUSE_VIEW_VAR_KIND (c) != OMP_CLAUSE_VIEW_VAR_UNSPECIFIED)
flags |= GOVD_SEEN;
check_non_private = "firstprivate";
goto do_add;
case OMP_CLAUSE_LASTPRIVATE:
@ -5737,9 +5740,38 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_INPUT:
case OMP_CLAUSE_OUTPUT:
{
#if 0
tree view = OMP_CLAUSE_VIEW_ID (c);
if(view != NULL_TREE)
omp_add_variable (ctx, view, GOVD_LOCAL | GOVD_SEEN);
{
//omp_add_variable (ctx, view, GOVD_LOCAL | GOVD_SEEN);
if (DECL_HAS_VALUE_EXPR_P (view))
{
tree new_decl = DECL_VALUE_EXPR (view);
gcc_assert (TREE_CODE (new_decl) == INDIRECT_REF);
/* if (TREE_CODE (new_decl) == INDIRECT_REF)*/
new_decl = TREE_OPERAND (new_decl, 0);
OMP_CLAUSE_VIEW_ID (c) = new_decl;
}
}
tree burst = OMP_CLAUSE_BURST_SIZE (c);
if (burst != NULL_TREE && DECL_P (burst))
{
omp_add_variable (ctx, burst, GOVD_FIRSTPRIVATE | GOVD_EXPLICIT | GOVD_SEEN);
if (outer_ctx)
omp_notice_variable (outer_ctx, decl, true);
gcc_assert (!DECL_HAS_VALUE_EXPR_P (burst));
if (0)
{
tree new_decl = DECL_VALUE_EXPR (burst);
gcc_assert (TREE_CODE (new_decl) == INDIRECT_REF);
/* if (TREE_CODE (new_decl) == INDIRECT_REF)*/
new_decl = TREE_OPERAND (new_decl, 0);
OMP_CLAUSE_BURST_SIZE (c) = new_decl;
}
}
#endif
}
flags = GOVD_PRIVATE | GOVD_EXPLICIT;
goto do_add;
@ -6046,9 +6078,112 @@ static void
gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
{
tree expr = *expr_p;
tree clauses = OMP_TASK_CLAUSES (expr);
gimple g;
gimple_seq body = NULL;
struct gimplify_ctx gctx;
bool is_streaming = false;
for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_INPUT ||
OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_OUTPUT)
{
is_streaming = true;
break;
}
/* We promote firstprivate clauses on streaming tasks to streams
from the enclosing context. */
if (is_streaming)
{
tree *clauses_p = &OMP_TASK_CLAUSES (expr);
for (; *clauses_p ; clauses_p = &OMP_CLAUSE_CHAIN (*clauses_p))
if (OMP_CLAUSE_CODE (*clauses_p) == OMP_CLAUSE_FIRSTPRIVATE)
{
tree c = build_omp_clause (input_location, OMP_CLAUSE_INPUT);
OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*clauses_p);
/* Store the original decl, but this will be replaced by
the firstprivate view's decl. */
OMP_CLAUSE_FIRSTPRIVATE_INPUT (c) = OMP_CLAUSE_DECL (*clauses_p);
OMP_CLAUSE_CHAIN (c) = OMP_CLAUSE_CHAIN (*clauses_p);
*clauses_p = c;
lang_hooks.decls.omp_finish_clause (c);
}
else if (OMP_CLAUSE_CODE (*clauses_p) == OMP_CLAUSE_INPUT
|| OMP_CLAUSE_CODE (*clauses_p) == OMP_CLAUSE_OUTPUT)
{
tree view = OMP_CLAUSE_VIEW_ID (*clauses_p);
tree burst = OMP_CLAUSE_BURST_SIZE (*clauses_p);
tree *size = &OMP_CLAUSE_VIEW_SIZE (*clauses_p);
/* We need to add firstprivate clauses for the burst
variables used in these clauses to ensure we don't
loose track of them. */
if (view != NULL_TREE)
{
tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
OMP_CLAUSE_DECL (c) = view;
OMP_CLAUSE_CHAIN (c) = OMP_CLAUSE_CHAIN (*clauses_p);
OMP_CLAUSE_CHAIN (*clauses_p) = c;
/* Store the replacement pointer's decl, if there is
one, instead of the original view id. */
if (DECL_HAS_VALUE_EXPR_P (view))
{
tree new_decl = DECL_VALUE_EXPR (view);
gcc_assert (TREE_CODE (new_decl) == INDIRECT_REF);
new_decl = TREE_OPERAND (new_decl, 0);
OMP_CLAUSE_VIEW_ID (*clauses_p) = new_decl;
}
clauses_p = &OMP_CLAUSE_CHAIN (*clauses_p);
OMP_CLAUSE_VIEW_VAR_KIND (c) = OMP_CLAUSE_VIEW_VAR_DISCARD;
lang_hooks.decls.omp_finish_clause (c);
*size = TYPE_SIZE_UNIT (TREE_TYPE (view));
}
else
continue;
if (burst != NULL_TREE && DECL_P (burst))
{
/* Check if there already is a clause for this burst. */
tree c_iter = OMP_TASK_CLAUSES (expr);
bool add_firstprivate = true;
for (; c_iter; c_iter = OMP_CLAUSE_CHAIN (c_iter))
if (OMP_CLAUSE_DECL (c_iter) == burst)
{
/* FIXME: check clause type, upgrade private to firstprivate. */
add_firstprivate = false;
break;
}
if (add_firstprivate)
{
tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
OMP_CLAUSE_DECL (c) = burst;
OMP_CLAUSE_CHAIN (c) = OMP_CLAUSE_CHAIN (*clauses_p);
OMP_CLAUSE_CHAIN (*clauses_p) = c;
clauses_p = &OMP_CLAUSE_CHAIN (*clauses_p);
OMP_CLAUSE_VIEW_VAR_KIND (c) = OMP_CLAUSE_VIEW_VAR_KEEP;
lang_hooks.decls.omp_finish_clause (c);
}
}
#if 0
if (*size && DECL_P (*size))
{
tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
OMP_CLAUSE_DECL (c) = *size;
OMP_CLAUSE_CHAIN (c) = OMP_CLAUSE_CHAIN (*clauses_p);
OMP_CLAUSE_CHAIN (*clauses_p) = c;
clauses_p = &OMP_CLAUSE_CHAIN (*clauses_p);
lang_hooks.decls.omp_finish_clause (c);
}
#endif
}
}
gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p, ORT_TASK);

48
gcc/omp-builtins.def

@ -209,16 +209,25 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_END, "GOMP_single_copy_end",
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CREATE_STREAM,
"GOMP_stream_create_stream",
BT_FN_PTR_SIZE_ULL_PTR, ATTR_NOTHROW_LIST)
BT_FN_PTR_SIZE_SIZE, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CREATE_READ_VIEW,
"GOMP_stream_create_read_view",
BT_FN_PTR, ATTR_NOTHROW_LIST)
BT_FN_PTR_SIZE_SIZE, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CREATE_WRITE_VIEW,
"GOMP_stream_create_write_view",
BT_FN_PTR, ATTR_NOTHROW_LIST)
BT_FN_PTR_SIZE_SIZE, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CREATE_TASK,
"GOMP_stream_create_task",
BT_FN_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_GET_TASK_ACTIVATION_COUNTER,
"GOMP_stream_get_task_activation_counter",
BT_FN_PTR_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_SET_TASK_TERMINATION_FLAG,
"GOMP_stream_set_task_termination_flag",
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_TASK_ADD_INSTANCE,
"GOMP_stream_task_add_instance",
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_ADD_EXPECTED_VIEWS,
"GOMP_stream_add_expected_views",
BT_FN_VOID_PTR_INT_INT_INT, ATTR_NOTHROW_LIST)
@ -228,10 +237,13 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CONNECT_VIEW,
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_WAIT_UNTIL_CONNECTED,
"GOMP_stream_wait_until_connected",
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_UPDATE, "GOMP_stream_update",
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_GET_AVAILABLE_WORK,
"GOMP_stream_get_available_work",
BT_FN_ULL_PTR_ULL, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_UPDATE, "GOMP_stream_update",
BT_FN_PTR_PTR_ULL_ULL, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_STALL, "GOMP_stream_stall",
BT_FN_VOID_PTR_ULL, ATTR_NOTHROW_LIST)
BT_FN_PTR_PTR_ULL_ULL, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_RELEASE, "GOMP_stream_release",
BT_FN_VOID_PTR_ULL, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_COMMIT, "GOMP_stream_commit",
@ -239,6 +251,32 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_COMMIT, "GOMP_stream_commit",
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_TASK_EXIT, "GOMP_stream_task_exit",
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CREATE_CONTROL_STREAM,
"GOMP_stream_create_control_stream",
BT_FN_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CONTROL_STREAM_ENABLE_ACTIVATION,
"GOMP_stream_control_stream_enable_activation",
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CONTROL_STREAM_SET_EOS,
"GOMP_stream_control_stream_set_eos",
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CONTROL_STREAM_EOS,
"GOMP_stream_control_stream_eos",
BT_FN_BOOL_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_DESTROY_CONTROL_STREAM,
"GOMP_stream_destroy_control_stream",
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_TASK, "GOMP_stream_task",
BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_LONG_BOOL,
ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_INIT, "GOMP_stream_init",
BT_FN_VOID, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_EXIT, "GOMP_stream_exit",
BT_FN_VOID, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_PRE, "GOMP_stream_pre",
BT_FN_PTR_PTR_ULL, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_PUSH_STUB, "GOMP_stream_push_stub",
BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_POP_STUB, "GOMP_stream_pop_stub",

7320
gcc/omp-low.c

File diff suppressed because it is too large

4
gcc/tree.c

@ -233,8 +233,8 @@ unsigned const char omp_clause_num_ops[] =
1, /* OMP_CLAUSE_SHARED */
1, /* OMP_CLAUSE_FIRSTPRIVATE */
2, /* OMP_CLAUSE_LASTPRIVATE */
4, /* OMP_CLAUSE_INPUT */
4, /* OMP_CLAUSE_OUTPUT */
6, /* OMP_CLAUSE_INPUT */
5, /* OMP_CLAUSE_OUTPUT */
4, /* OMP_CLAUSE_REDUCTION */
1, /* OMP_CLAUSE_COPYIN */
1, /* OMP_CLAUSE_COPYPRIVATE */

18
gcc/tree.h

@ -1783,6 +1783,13 @@ extern void protected_set_expr_location (tree, location_t);
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
OMP_CLAUSE_INPUT, \
OMP_CLAUSE_OUTPUT), 3)
#define OMP_CLAUSE_VIEW_SIZE(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
OMP_CLAUSE_INPUT, \
OMP_CLAUSE_OUTPUT), 4)
#define OMP_CLAUSE_FIRSTPRIVATE_INPUT(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, \
OMP_CLAUSE_INPUT), 5)
#define OMP_CLAUSE_HAS_LOCATION(NODE) \
((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
@ -1871,6 +1878,16 @@ enum omp_clause_default_kind
#define OMP_CLAUSE_DEFAULT_KIND(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEFAULT)->omp_clause.subcode.default_kind)
enum omp_clause_view_var_kind
{
OMP_CLAUSE_VIEW_VAR_UNSPECIFIED,
OMP_CLAUSE_VIEW_VAR_DISCARD,
OMP_CLAUSE_VIEW_VAR_KEEP
};
#define OMP_CLAUSE_VIEW_VAR_KIND(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FIRSTPRIVATE)->omp_clause.subcode.view_var_kind)
struct GTY(()) tree_exp {
struct tree_common common;
location_t locus;
@ -1987,6 +2004,7 @@ struct GTY(()) tree_omp_clause {
union omp_clause_subcode {
enum omp_clause_default_kind default_kind;
enum omp_clause_schedule_kind schedule_kind;
enum omp_clause_view_var_kind view_var_kind;
enum tree_code reduction_code;
} GTY ((skip)) subcode;

12
libgomp/libgomp.map

@ -171,13 +171,25 @@ GOMP_2.0 {
GOMP_stream_create_read_view;
GOMP_stream_create_write_view;
GOMP_stream_create_task;
GOMP_stream_get_task_activation_counter;
GOMP_stream_set_task_termination_flag;
GOMP_stream_task_add_instance;
GOMP_stream_add_expected_views;
GOMP_stream_connect_view;
GOMP_stream_wait_until_connected;
GOMP_stream_get_available_work;
GOMP_stream_update;
GOMP_stream_stall;
GOMP_stream_release;
GOMP_stream_commit;
GOMP_stream_task_exit;
GOMP_stream_create_control_stream;
GOMP_stream_control_stream_set_eos;
GOMP_stream_control_stream_eos;
GOMP_stream_destroy_control_stream;
GOMP_stream_task;
GOMP_stream_init;
GOMP_stream_exit;
GOMP_stream_pre;
} GOMP_1.0;

30
libgomp/libgomp_g.h

@ -180,20 +180,36 @@ extern void *GOMP_single_copy_start (void);
extern void GOMP_single_copy_end (void *);
/* stream.c */
extern void *GOMP_stream_create_stream (size_t, unsigned long long, char *);
extern void *GOMP_stream_create_read_view (void);
extern void *GOMP_stream_create_write_view (void);
extern void *GOMP_stream_create_stream (size_t, size_t);
extern void *GOMP_stream_create_read_view (size_t, size_t);
extern void *GOMP_stream_create_write_view (size_t, size_t);
extern void *GOMP_stream_create_task (void);
extern volatile void *GOMP_stream_get_task_activation_counter (void *);
extern void GOMP_stream_set_task_termination_flag (void *);
extern void GOMP_stream_task_add_instance (void *);
extern void GOMP_stream_add_expected_views (void *, int, int, int);
extern void GOMP_stream_connect_view (void *, void *, void *);
extern void GOMP_stream_wait_until_connected (void *);
extern unsigned long long GOMP_stream_update (void *,
const unsigned long long);
extern void GOMP_stream_stall (void *, const unsigned long long);
extern unsigned long long GOMP_stream_get_available_work (void *,
unsigned long long *);
extern void *GOMP_stream_update (void *,
const unsigned long long,
const unsigned long long);
extern void *GOMP_stream_stall (void *, const unsigned long long,
const unsigned long long);
extern void GOMP_stream_release (void *, const unsigned long long);
extern void GOMP_stream_commit (void *, const unsigned long long);
extern void GOMP_stream_task_exit (void *);
extern void *GOMP_stream_create_control_stream (void);
extern void GOMP_stream_control_stream_set_eos (void *);
extern bool GOMP_stream_control_stream_eos (void *);
extern void GOMP_stream_destroy_control_stream (void *);
extern void GOMP_stream_task (void (*) (void *), void *,
void (*) (void *, void *),
long, long, long, bool);
extern void GOMP_stream_init (void);
extern void GOMP_stream_exit (void);
extern void *GOMP_stream_pre (void *, const unsigned long long);
#endif /* LIBGOMP_G_H */

15
libgomp/omp.h.in

@ -107,19 +107,24 @@ int omp_get_active_level (void) __GOMP_NOTHROW;
[(unsigned long long)(INDEX) & \
(*((unsigned long long *)((*((char ***) (VIEW))) + 1)))]
extern void *GOMP_stream_create_stream (size_t, unsigned long long, char *)
extern void *GOMP_stream_create_stream (size_t, size_t)
__GOMP_NOTHROW;
extern void *GOMP_stream_create_read_view (void) __GOMP_NOTHROW;
extern void *GOMP_stream_create_write_view (void) __GOMP_NOTHROW;
extern void *GOMP_stream_create_read_view (size_t, size_t) __GOMP_NOTHROW;
extern void *GOMP_stream_create_write_view (size_t, size_t) __GOMP_NOTHROW;
extern void *GOMP_stream_create_task (void) __GOMP_NOTHROW;
extern void GOMP_stream_add_expected_views (void *, int, int, int)
__GOMP_NOTHROW;
extern void GOMP_stream_connect_view (void *, void *, void *) __GOMP_NOTHROW;
extern void GOMP_stream_wait_until_connected (void *) __GOMP_NOTHROW;
extern unsigned long long GOMP_stream_update (void *,
extern unsigned long long GOMP_stream_get_available_work (void *,
unsigned long long *)
__GOMP_NOTHROW;
extern void *GOMP_stream_update (void *,
const unsigned long long,
const unsigned long long)
__GOMP_NOTHROW;
extern void GOMP_stream_stall (void *, const unsigned long long)
extern void *GOMP_stream_stall (void *, const unsigned long long,
const unsigned long long)
__GOMP_NOTHROW;
extern void GOMP_stream_release (void *, const unsigned long long)
__GOMP_NOTHROW;

460
libgomp/stream.c

@ -36,6 +36,30 @@
#include "mutex.h"
#include "libgomp.h"
#define AGGREGATION_FACTOR 32
//#define debug_log_init(S, V1, V2) printf (S, V1, V2); fflush (stdout)
#define debug_log_init(S, V1, V2)
//#define debug_log_init3(S, V1, V2, V3) printf (S, V1, V2, V3); fflush (stdout)
#define debug_log_init3(S, V1, V2, V3)
//#define debug_log(S, V1, V2) printf (S, V1, V2); fflush (stdout)
#define debug_log(S, V1, V2)
gomp_barrier_t gomp_stream_tasks_wait_until_connected_barrier;
gomp_barrier_t gomp_stream_tasks_exit_barrier;
unsigned gomp_stream_tasks_count;
/* This structure is used to communicate across pthread_create. */
struct gomp_stream_thread_start_data
{
void (*fn) (void *);
void *fn_data;
int id;
};
/* Data structures creation and pipeline initialization. */
@ -46,39 +70,32 @@
BUFFER for the stream. */
void *
GOMP_stream_create_stream (size_t element_size,
unsigned long long stream_buffer_size,
char *buffer)
GOMP_stream_create_stream (size_t element_size, size_t buffer_size)
{
gomp_stream_p stream = (gomp_stream_p) gomp_malloc (sizeof (gomp_stream_t));
debug_log_init ("GOMP_stream_create_stream %zu %zu\n", element_size, buffer_size);
if (buffer_size < 2)
gomp_fatal ("GOMP_stream: insufficient stream buffer size.");
/* Initialize and allocate the data buffer. We force the
buffer_size to be a power of 2 for efficient modulo computation
of the indices in the circular buffer. */
stream->element_size = element_size;
/* To avoid excessive multiplication operations, we convert the
accounting from elements to bytes. */
buffer_size *= element_size;
stream->buffer_size = 1;
while(stream->buffer_size < stream_buffer_size)
while(stream->buffer_size < buffer_size)
stream->buffer_size <<= 1;
stream->buffer_mask = stream->buffer_size - 1;
/* In case the user provided a pre-allocated buffer, we need to
ensure it is properly sized. */
if (buffer != NULL)
{
if (stream->buffer_size != stream_buffer_size)
gomp_fatal ("GOMP_stream: provided buffer size is not power of 2.");
stream->buffer = buffer;
}
else
{
stream->buffer =
(void *) gomp_malloc (stream->element_size * stream->buffer_size);
}
stream->buffer =
(void *) gomp_malloc (stream->buffer_size * 2);
stream->expected_ready_p = false;
stream->connected_p = false;
stream->eos_p = false;
stream->pre_shift = 0;
/* Initialize the view_handles. */
stream->read_views.current_min = stream->buffer_size;
@ -89,7 +106,7 @@ GOMP_stream_create_stream (size_t element_size,
stream->read_views.nr_expected_views = 0;
stream->read_views.nr_registered_views = 0;
stream->read_views.nr_unregistered_views = 0;
gomp_mutex_init (&stream->read_views.connect_view_mutex);
gomp_mutex_init (&stream->read_views.view_list.connect_view_mutex);
stream->write_views.current_min = 0;
stream->write_views.current_max = stream->buffer_size;
@ -99,7 +116,7 @@ GOMP_stream_create_stream (size_t element_size,
stream->write_views.nr_expected_views = 0;
stream->write_views.nr_registered_views = 0;
stream->write_views.nr_unregistered_views = 0;
gomp_mutex_init (&stream->write_views.connect_view_mutex);
gomp_mutex_init (&stream->write_views.view_list.connect_view_mutex);
#ifndef HAVE_SYNC_BUILTINS
gomp_mutex_init (&stream->stream_mutex);
@ -111,10 +128,11 @@ GOMP_stream_create_stream (size_t element_size,
/* Allocate and initialize a generic GOMP_STREAM_VIEW that can be
connected to any stream to give either read or write access
depending on its TYPE. Returns a pointer to the newly allocated
view. */
view. This view accesses VIEW_SIZE bytes in the stream and
commits/releases BURST_SIZE bytes per activation. */
static inline void *
gomp_stream_create_view (int type)
gomp_stream_create_view (int type, size_t view_size, size_t burst_size)
{
gomp_stream_view_p view =
(gomp_stream_view_p) gomp_malloc (sizeof(gomp_stream_view_t));
@ -125,45 +143,86 @@ gomp_stream_create_view (int type)
view->end_p = false;
view->type = type;
view->local_min_value = 0;
view->view_size = view_size;
view->burst_size = burst_size;
view->pxxk_size = view_size - burst_size;
return view;
}
/* Wrapper for creating a READ view. */
/* Wrapper for creating a READ view . */
void *
GOMP_stream_create_read_view (void)
GOMP_stream_create_read_view (size_t view_size, size_t burst_size)
{
return gomp_stream_create_view (READ_VIEW);
debug_log_init ("GOMP_stream_create_read_view %zu %zu\n", view_size, burst_size);
return gomp_stream_create_view (READ_VIEW, view_size, burst_size);
}
/* Wrapper for creating a WRITE view. */
void *
GOMP_stream_create_write_view (void)
GOMP_stream_create_write_view (size_t view_size, size_t burst_size)
{
return gomp_stream_create_view (WRITE_VIEW);
debug_log_init ("GOMP_stream_create_write_view %zu %zu\n", view_size, burst_size);
return gomp_stream_create_view (WRITE_VIEW, view_size, burst_size);
}
/* Allocate and initialize a GOMP_STREAM_TASK data structure. */
void *
GOMP_stream_create_task (void)
GOMP_stream_create_task ()
{
gomp_stream_task_p task =
gomp_stream_task_p task =
(gomp_stream_task_p) gomp_malloc (sizeof(gomp_stream_task_t));
debug_log_init3 ("GOMP_stream_create_task %d %d \t %15zu\n", 0, 0, (size_t) task);
task->read_view_list.views = NULL;
task->read_view_list.nr_views = 0;
task->read_view_list.size = 0;
gomp_mutex_init (&task->read_view_list.connect_view_mutex);
task->write_view_list.views = NULL;
task->write_view_list.nr_views = 0;
task->write_view_list.size = 0;
gomp_mutex_init (&task->write_view_list.connect_view_mutex);
task->activation_counter = 0;
task->termination_flag = false;
task->first_unassigned_activation_counter = 0;
task->num_instances = 0;
__sync_synchronize ();
return task;
}
volatile void *
GOMP_stream_get_task_activation_counter (void *t)
{
gomp_stream_task_p task = (gomp_stream_task_p) t;
return &(task->activation_counter);
}
void
GOMP_stream_set_task_termination_flag (void *t)
{
gomp_stream_task_p task = (gomp_stream_task_p) t;
task->termination_flag = true;
}
void
GOMP_stream_task_add_instance (void *t)
{
gomp_stream_task_p task = (gomp_stream_task_p) t;
__sync_fetch_and_add (&task->num_instances, 1);
__sync_synchronize ();
}
/* Declare additional READ_VIEWS and WRITE_VIEWS expected views on
stream S. When possible, the thread that creates the streaming
tasks should declare, for each stream, the number of read/write
@ -177,6 +236,7 @@ GOMP_stream_add_expected_views (void *s, int read_views, int write_views,
int final)
{
gomp_stream_p stream = (gomp_stream_p) s;
debug_log_init ("GOMP_stream_add_expected_views %d %d\n", read_views, write_views);
if (stream->expected_ready_p)
gomp_fatal
@ -249,14 +309,16 @@ GOMP_stream_connect_view (void *t, void *s, void *v)
/* Register the view with the TASK to which it belongs. This
operation is local to the task, so there is no need to
synchronize. */
gomp_mutex_lock (&task_list->connect_view_mutex);
gomp_stream_add_view_to_list (view, task_list);
gomp_mutex_unlock (&task_list->connect_view_mutex);
/* Connect the view to the stream. This must be done atomically as
this data structure is shared with the other producer/consumer
tasks. */
gomp_mutex_lock (&vh->connect_view_mutex);
gomp_mutex_lock (&vh->view_list.connect_view_mutex);
gomp_stream_add_view_to_list (view, stream_list);
gomp_mutex_unlock (&vh->connect_view_mutex);
gomp_mutex_unlock (&vh->view_list.connect_view_mutex);
__sync_fetch_and_add (&vh->nr_registered_views, 1);
}
@ -290,24 +352,27 @@ void
GOMP_stream_wait_until_connected (void *t)
{
gomp_stream_task_p task = (gomp_stream_task_p) t;
int num_read_views = task->read_view_list.nr_views;
int num_write_views = task->write_view_list.nr_views;
int i;
bool done;
int i;
do
{
done = true;
for (i = 0; i < num_read_views; ++i)
gomp_mutex_lock (&task->read_view_list.connect_view_mutex);
for (i = 0; i < task->read_view_list.nr_views; ++i)
if (!gomp_stream_check_connected (task->read_view_list.views[i]->stream))
done = false;
gomp_mutex_unlock (&task->read_view_list.connect_view_mutex);
for (i = 0; i < num_write_views; ++i)
gomp_mutex_lock (&task->write_view_list.connect_view_mutex);
for (i = 0; i < task->write_view_list.nr_views; ++i)
if (!gomp_stream_check_connected (task->write_view_list.views[i]->stream))
done = false;
gomp_mutex_unlock (&task->write_view_list.connect_view_mutex);
}
while (!done);
debug_log_init ("GOMP_stream_wait_until_connected %zu %zu\n", (size_t) task, (size_t) task);
}
/* Stream communication/synchronization. */
@ -409,76 +474,151 @@ gomp_stream_wait_release (gomp_stream_view_p view,
}
}
/* Request read access for the view V to the stream up to INDEX. In
case the producers have finished and there is not enough data, the
returned value is the highest index to which the view is allowed to
access the stream. */
unsigned long long
GOMP_stream_update (void *v, const unsigned long long index)
void *
GOMP_stream_update (void *v, const unsigned long long act_start,
const unsigned long long act_end)
{
unsigned long long low_idx, up_idx;
size_t low_idx_loc, up_idx_loc;
gomp_stream_view_p view = (gomp_stream_view_p) v;
view->upper_index = index;
gomp_stream_p stream = view->stream;
void *buffer_pointer;
debug_log ("GOMP_stream_update [in] %llu %llu\n", act_start, act_end);
/* This update requests access to the buffer in [low_idx,up_idx[.
We will release up to low_idx-1 and acquire up to up_idx-1. */
low_idx = act_start * view->burst_size;
up_idx = act_end * view->burst_size + view->pxxk_size - 1;
if (up_idx - low_idx > stream->buffer_size)
gomp_fatal ("GOMP_stream: update requested access to more than buffer_size data.");
view->lower_index = low_idx + view->stream->buffer_size;
view->upper_index = up_idx;
/* In case another consumer has received permission to read up to a
yet higher index, then there is no need to check for this one. */
if (index > view->stream->read_views.current_max)
if (up_idx > view->stream->read_views.current_max)
{
gomp_stream_wait_release (view, &view->stream->write_views, index);
gomp_stream_wait_release (view, &view->stream->write_views, up_idx);
view->stream->read_views.current_max = up_idx;
}
/* If the producers have finished producing for this stream, we
need to ensure we do not give read permission to the view
past the highest fully committed index (committed by all
producers). */
if (view->stream->eos_p)
{
view->stream->write_views.current_min =
gomp_stream_compute_lower_min (&view->stream->write_views.view_list);
low_idx_loc = low_idx & stream->buffer_mask;
up_idx_loc = up_idx & stream->buffer_mask;
if (index > view->stream->write_views.current_min)
{
return view->stream->write_views.current_min;
}
}
view->stream->read_views.current_max = index;
/* Once we know enough data is available for reading, we need to
check whether the data between the lower and upper buonds is
contiguous or if the buffer wrap-around occurs in the middle. */
if (low_idx_loc > up_idx_loc)
{
/* FIXME: does this require synchronization or is concurrent
overwriting acceptable as long as enough data has been copied
at the end? */
memcpy (stream->buffer + stream->buffer_size, stream->buffer,
up_idx_loc + 1);
//printf ("Update copy: (%llu,%llu) %llu - %llu | %zu - %zu (size: %zu)\n ", act_start, act_end, low_idx, up_idx, low_idx_loc, up_idx_loc, up_idx_loc + 1);
}
return index;
/* We return a pointer to a contiguous array where this view is
guaranteed access to all the requested data. */
buffer_pointer = stream->buffer + low_idx_loc;
debug_log ("GOMP_stream_update [out] %llu %llu\n", act_start, act_end);
return buffer_pointer;
}
/* Request write access for the view V to the stream up to INDEX. */
void
GOMP_stream_stall (void *v, const unsigned long long index)
void *
GOMP_stream_stall (void *v, const unsigned long long act_start,
const unsigned long long act_end)
{
unsigned long long low_idx, up_idx;
gomp_stream_view_p view = (gomp_stream_view_p) v;
view->upper_index = index;
gomp_stream_p stream = view->stream;
void *buffer_pointer;
debug_log ("GOMP_stream_stall [in] %llu %llu\n", act_start, act_end);
/* This update requests access to the buffer in [low_idx,up_idx[.
We will release up to low_idx-1 and acquire up to up_idx-1. */
low_idx = act_start * view->burst_size + stream->pre_shift;
up_idx = act_end * view->burst_size + view->pxxk_size + stream->pre_shift - 1;
if (index > view->stream->write_views.current_max)
if (up_idx - low_idx > stream->buffer_size)
{
gomp_stream_wait_release (view, &view->stream->read_views, index);
view->stream->write_views.current_max = index;
fprintf (stderr, "Requesting data from low: %llu to up: %llu act [%llu,%llu] for burst:%zu size: %zu\n", low_idx, up_idx, act_start, act_end, view->burst_size, view->view_size);
gomp_fatal ("GOMP_stream: stall requested access to more than buffer_size data.");
}
/* We do not need to worry about wrap-around copying as this
"commit" only means that we do not want to write to those
indices below low_idx. */
view->lower_index = low_idx;
view->upper_index = up_idx;
if (up_idx > stream->write_views.current_max)
{
gomp_stream_wait_release (view, &stream->read_views, up_idx);
stream->write_views.current_max = up_idx;
}
buffer_pointer = stream->buffer + (low_idx & stream->buffer_mask);
debug_log ("GOMP_stream_stall [out] %llu %llu\n", act_start, act_end);
return buffer_pointer;
}
/* Relinquish read access for the view V to the stream up to
INDEX. */
void
GOMP_stream_release (void *v, const unsigned long long index)
GOMP_stream_release (void *v, const unsigned long long act_idx)
{
gomp_stream_view_p view = (gomp_stream_view_p) v;
view->lower_index = index + view->stream->buffer_size;
view->lower_index = act_idx * view->burst_size + view->stream->buffer_size - 1;
debug_log ("GOMP_stream_release %llu %llu\n", act_idx, act_idx);
}
/* Relinquish write access for the view V to the stream up to
INDEX. */
void
GOMP_stream_commit (void *v, const unsigned long long index)
GOMP_stream_commit (void *v, const unsigned long long act_idx)
{
gomp_stream_view_p view = (gomp_stream_view_p) v;
view->lower_index = index;
gomp_stream_p stream = view->stream;
unsigned long long up_idx = act_idx * view->burst_size + stream->pre_shift - 1;
size_t low_idx_loc, up_idx_loc;
low_idx_loc = view->lower_index & stream->buffer_mask;
up_idx_loc = up_idx & stream->buffer_mask;
/* Once we know enough data is available for reading, we need to
check whether the data between the lower and upper buonds is
contiguous or if the buffer wrap-around occurs in the middle. */
if (low_idx_loc > up_idx_loc)
{
/* FIXME: does this require synchronization or is concurrent
overwriting acceptable as long as enough data has been copied
at the end? */
memcpy (stream->buffer, stream->buffer + stream->buffer_size,
up_idx_loc + 1);
//printf ("Commit copy: (%llu) %llu - %llu | %zu - %zu (size: %zu)\n ", act_idx, view->lower_index, up_idx, low_idx_loc, up_idx_loc, up_idx_loc + 1);
}
view->lower_index = up_idx;
debug_log ("GOMP_stream_commit %llu %llu\n", act_idx, act_idx);
}
/* Finalization and destruction of the streaming data structures. */
@ -543,20 +683,186 @@ GOMP_stream_task_exit (void *t)
gomp_stream_task_p task = (gomp_stream_task_p) t;
int num_read_views = task->read_view_list.nr_views;
int num_write_views = task->write_view_list.nr_views;
int i;
int i, res;
debug_log_init ("GOMP_stream_task_exit %zu %zu\n", (size_t) t, (size_t) t);
res = __sync_sub_and_fetch (&task->num_instances, 1);
if (res == 0)
{
for (i = 0; i < num_read_views; ++i)
gomp_stream_unregister_view (task->read_view_list.views[i]);
for (i = 0; i < num_write_views; ++i)
gomp_stream_unregister_view (task->write_view_list.views[i]);
free (task->read_view_list.views);
free (task->write_view_list.views);
free (task);
}
}
/* Get info on the amount of work/data available in the stream
starting from INDEX and considering a constant burst of size BURST.
This function does not wait, except in case there is no work yet,
but the EOS flag has not yet been set. The function only returns 0
on termination. */
unsigned long long
GOMP_stream_get_available_work (void *t, unsigned long long *start_idx)
{
gomp_stream_task_p task = (gomp_stream_task_p) t;
long result = 0;
unsigned long long start;
/* Atomically acquire a range, then wait until the range is either
fully available or termination occurs. */
start = __sync_fetch_and_add (&task->first_unassigned_activation_counter,
AGGREGATION_FACTOR);
result = task->activation_counter - start;
debug_log_init3 ("GOMP_stream_get_available_work [entry] %llu %llu \t %15zu\n", start, task->activation_counter, (size_t) task);
if (result >= AGGREGATION_FACTOR)
{
*start_idx = start;
return AGGREGATION_FACTOR;
}
while (result < AGGREGATION_FACTOR)
{
if (task->termination_flag)
{
__sync_synchronize ();
result = task->activation_counter - start;
debug_log ("GOMP_stream_get_available_work [final] %llu %ld\n", start, result);
*start_idx = start;
if (result > AGGREGATION_FACTOR)
return AGGREGATION_FACTOR;
return (result > 0) ? result : 0;
}
result = task->activation_counter - start;
}
debug_log ("GOMP_stream_get_available_work %llu %ld\n", start, result);
*start_idx = start;
return AGGREGATION_FACTOR;
}
for (i = 0; i < num_read_views; ++i)
gomp_stream_unregister_view (task->read_view_list.views[i]);
for (i = 0; i < num_write_views; ++i)
gomp_stream_unregister_view (task->write_view_list.views[i]);
/* Initialize streaming in this region. */
free (task->read_view_list.views);
free (task->write_view_list.views);
free (task);
void
GOMP_stream_init ()
{
/* Add self to ensure at least one member of the team barrier will
be waiting for the streaming tasks. */
gomp_stream_tasks_count = 1;
gomp_barrier_init (&gomp_stream_tasks_exit_barrier, gomp_stream_tasks_count);
}
/* Wait until all streaming threads complete. */
void
GOMP_stream_exit ()
{
gomp_barrier_wait (&gomp_stream_tasks_exit_barrier);
}
/* Request SIZE bytes for a PRE operator on stream S. Return a
pointer where data should be stored. */
void *
GOMP_stream_pre (void *s, const unsigned long long size)
{
gomp_stream_p stream = (gomp_stream_p) s;
debug_log_init ("GOMP_stream_pre %zu \t %llu\n", (size_t) s, size);
stream->pre_shift = size;
stream->write_views.current_min = size;
return stream->buffer;
}
/* This function is a pthread_create entry point for streaming
tasks. */
static void *
gomp_stream_thread_start (void *xdata)
{
struct gomp_stream_thread_start_data *data = xdata;
void (*local_fn) (void *);
void *local_data;
local_fn = data->fn;
local_data = data->fn_data;
local_fn (local_data);
gomp_barrier_wait_last (&gomp_stream_tasks_exit_barrier);
debug_log_init ("** exiting task: %d (%u)\n", data->id, gomp_stream_tasks_count);
return NULL;
}
/* Called for starting a streaming task. These tasks do not partake
in existing thread teams and are not subject to scheduling
points. */
void
GOMP_stream_task (void (*fn) (void *), void *data,
void (*cpyfn) (void *, void *),
long arg_size, long arg_align,
long num_instances, bool auto_replicable)
{
pthread_attr_t thread_attr, *attr;
pthread_t pt;
int err, i, base_id;
char *arg, *buf;
base_id = __sync_fetch_and_add (&gomp_stream_tasks_count, num_instances);
gomp_barrier_reinit (&gomp_stream_tasks_exit_barrier,
gomp_stream_tasks_count);
debug_log_init ("** adding tasks: %ld (%u)\n", num_instances, gomp_stream_tasks_count);
attr = &gomp_thread_attr;
if (__builtin_expect (gomp_cpu_affinity != NULL, 0))
{
size_t stacksize;
pthread_attr_init (&thread_attr);
pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
if (! pthread_attr_getstacksize (&gomp_thread_attr, &stacksize))
pthread_attr_setstacksize (&thread_attr, stacksize);
attr = &thread_attr;
#if 0 /* This should be handled separately ... we will have to build a
stream mapping and prevent other OMP threads from touching
the cores running streaming tasks. */
gomp_init_thread_affinity (attr);
#endif
}
for (i = 0; i < num_instances; ++i)
{
struct gomp_stream_thread_start_data *start_data;
buf = (char *) gomp_malloc (arg_size + arg_align - 1);
arg = (char *) (((uintptr_t) (buf) + arg_align - 1)
& ~(uintptr_t) (arg_align - 1));
if (cpyfn)
cpyfn (arg, data);
else
memcpy (arg, data, arg_size);
start_data = gomp_malloc (sizeof (struct gomp_stream_thread_start_data));
start_data->fn = fn;
start_data->fn_data = arg;
start_data->id = base_id + i;
err = pthread_create (&pt, attr, gomp_stream_thread_start, start_data);
if (err != 0)
gomp_fatal ("Thread creation failed: %s", strerror (err));
}
if (__builtin_expect (gomp_cpu_affinity != NULL, 0))
pthread_attr_destroy (&thread_attr);
}

69
libgomp/stream.h

@ -73,6 +73,12 @@ typedef struct gomp_stream_view
to be first. */
struct gomp_stream *stream;
/* Size in bytes of the burst associated to this view. Later this
may become a stream. */
size_t view_size;
size_t burst_size;
size_t pxxk_size;
/* The alignment directives are needed to ensure these
high-potential false-sharing fields are on their own cache
lines. */
@ -109,6 +115,10 @@ typedef struct gomp_stream_view_list
gomp_stream_view_p *views;
int nr_views;
int size;
/* Enforce atomic connection of the views in this list. */
gomp_mutex_t connect_view_mutex;
} gomp_stream_view_list_t, *gomp_stream_view_list_p;
@ -133,9 +143,6 @@ typedef struct gomp_stream_view_handle
int nr_registered_views;
int nr_unregistered_views;
/* Enforce atomic connection of the views to the stream. */
gomp_mutex_t connect_view_mutex;
} gomp_stream_view_handle_t, *gomp_stream_view_handle_p;
@ -158,9 +165,9 @@ typedef struct gomp_stream
for the wrap-around. The size is expressed in basic elements for
this stream. The size in bytes of the buffer is
BUFFER_SIZE * ELEMENT_SIZE. */
unsigned long long buffer_mask;
unsigned long long buffer_size;
unsigned long long element_size;
unsigned long long buffer_mask;
unsigned long long pre_shift;
/* True once all the tasks that should be expected to connect to
this stream been declared. */
@ -205,6 +212,58 @@ typedef struct gomp_stream_task
gomp_stream_view_list_t read_view_list;
gomp_stream_view_list_t write_view_list;
/* The following are used directly in the generated code and should
only be read here. A memory fence is guaranteed before the
termination flag is set to true. */
/* Number of activations allowed for the task. */
volatile unsigned long long activation_counter;
volatile unsigned long long first_unassigned_activation_counter;
int num_instances;
/* True only when the activation counter has reached the maximum
number of activations allowed for this task. */
volatile bool termination_flag;
} gomp_stream_task_t, *gomp_stream_task_p;
#if 0
/* GOMP_STREAM_CONTROL_STREAM data structure. Implements a simple
if-conversion analog that allows a non data-driven task to conform
to its original control dependences. */
typedef struct gomp_stream_control_stream
{
/* In all cases where the streams bypass control (i.e., for
sequential control flow only), an activation counter is
sufficient to carry the control flow. */
/* Local counter of the number of times a task has been activated. */
unsigned long long activation_counter __attribute__((aligned (64)));
unsigned long long local_enabled_activations;
/* Number of times this task is allowed to activate. */
unsigned long long enabled_activations __attribute__((aligned (64)));
/* When a task's inputs or outputs cross a parallel control flow
boundary (i.e., worksharing construct), their activation pattern
can be sparse wrt. the actual stream of data that they share with
their sibling tasks. We use activation ranges as an optimization
to streaming the activation indexes themselves, but the two
options are equivalent. These streams are inherently 1-to-1, so
a simpler implementation of the synchronization should be used in
this case.*/
/* gomp_stream_p activation_range_stream; */
/* End of stream: true when all producers have finished committing
all the data and are terminating. */
bool eos_p;
} gomp_stream_control_stream_t, *gomp_stream_control_stream_p;
#endif
#endif /* GOMP_STREAM_H */

Loading…
Cancel
Save