2010-10-05 Antoniu Pop <antoniu.pop@gmail.com>
Merge diffs r32779:34430 from INRIA local svn to omp-stream branch base r159266. libgomp/ This merge introduces a stream-communication layer to the GOMP runtime. gcc/ Code generation for an OpenMP streaming extension. git-svn-id: svn://gcc.gnu.org/svn/gcc/branches/omp-stream@164990 138bc75d-0d04-0410-961f-82ee72b054a4
This commit is contained in:
parent
5c1fb0cf09
commit
48de164d08
|
@ -0,0 +1,206 @@
|
||||||
|
2010-10-04 Cupertino Miranda <cupertinomiranda@gmail.com>
|
||||||
|
|
||||||
|
* omp-low.c: Debugging
|
||||||
|
(convert_view_var_array): Perform a type cast for the case where an
|
||||||
|
address of ARRAY_REF is performed. Cast is done for the expected type
|
||||||
|
of the current node.
|
||||||
|
(expand_view_traverser_callback): Corrected code for cases where an
|
||||||
|
assign statement that has two memory operands.
|
||||||
|
|
||||||
|
2010-10-04 Cupertino Miranda <cupertinomiranda@gmail.com>
|
||||||
|
|
||||||
|
* omp-low.c: Debugging and cleanup
|
||||||
|
(_lookup_stream): Removed stream type checking to start treat every
|
||||||
|
stream var in the same fashion.
|
||||||
|
(TRAVERSE_VIEWS_IN_REGION): Check htab before doing the traversal.
|
||||||
|
(traverse_views_in_region_and_subs): Check region->view_pointers before
|
||||||
|
traverse it.
|
||||||
|
(compute_data_position): Rename variables. Enabled to pass NULL index
|
||||||
|
to make it further reusable.
|
||||||
|
(convert_view_var_array_struct): Added assign_to_var_if_has_parent.
|
||||||
|
(convert_view_var_array): Updated way to perform convertion. Convertion
|
||||||
|
is only executed for ARRAY elements. Created checks to validate if
|
||||||
|
recursive callers should do the convertion or simply ignore. The
|
||||||
|
remaining expansions are performed by the caller function.
|
||||||
|
(expand_view_traverser_callback_data): Removed unused nr_elements.
|
||||||
|
(expand_view_traverser_callback): Moved sync_index increment to after
|
||||||
|
commit / release. Created condition to either call
|
||||||
|
convert_view_var_array (for an ARRAY element, substituting it by direct
|
||||||
|
buffer accesses) or perform the expansion in this function by adding
|
||||||
|
either and read / write to the buffer after / before an update / commit
|
||||||
|
respectively.
|
||||||
|
(register_views_traverser_callback): Change initial assign to
|
||||||
|
sync_index to view_horizon instead of 0.
|
||||||
|
(expand_task_streaming_extensions): Removed assign to nr_elements
|
||||||
|
remove from the structure. Added gsi_inserts for write_stmts and
|
||||||
|
read_stmts elements.
|
||||||
|
(stream_create_calls): Changed created variables from size_type_node to
|
||||||
|
long_long_unsigned_type_node.
|
||||||
|
(expand_push_and_pop_stubs): Removed un-used nr_elements local
|
||||||
|
variable.
|
||||||
|
(expand_omp_single): Removed a condition that was miss protecting some
|
||||||
|
code that was producing bad builtin calls when master had no shared
|
||||||
|
stream with child tasks.
|
||||||
|
(retrieve_streams_info): Changed var from size_type_node to
|
||||||
|
long_long_unsigned_type_node.
|
||||||
|
|
||||||
|
2010-09-28 Antoniu Pop <antoniu.pop@gmail.com>
|
||||||
|
|
||||||
|
* omp-low.c: Debugging and cleanup.
|
||||||
|
(retrieve_streams_info): Removed unguarded call to
|
||||||
|
OMP_CLAUSE_STREAM_ID. This macro can only be called on
|
||||||
|
OMP_CLAUSE_INPUT and OMP_CLAUSE_OUTPUT.
|
||||||
|
(list_bbs_in_sese): Renamed variable NEW to avoid compilation
|
||||||
|
warnings and potential surprises.
|
||||||
|
(lookup_stream, compute_data_position): Changed type of
|
||||||
|
BUFFER_MASK to be consistent. As we use unsigned_long_long for
|
||||||
|
indexes and horizons, this should be used everywhere we interact
|
||||||
|
with stream indexes.
|
||||||
|
(convert_view_var_array): Handle cases where the use of a
|
||||||
|
dereference is not acceptable in gimple. This includes among
|
||||||
|
others, binary RHS in assignment, non-register LHS, statements
|
||||||
|
with no memory operands.
|
||||||
|
|
||||||
|
2010-07-27 Cupertino Miranda <cupertinomiranda@gmail.com>
|
||||||
|
|
||||||
|
* omp-low.c: Updated code to new streaming syntax.
|
||||||
|
(regions_streamization_info): Added outer_check, outer_first,
|
||||||
|
sese_entry, sese_exit;
|
||||||
|
(stream, _lookup_stream): Added buffer_type, buffer_mask,
|
||||||
|
element_number. Removed element_size and data. Initializations within
|
||||||
|
_lookup_stream. Added logic to identify type of elements in stream
|
||||||
|
depending if stream var is simple type or an array. Should be changed
|
||||||
|
later.
|
||||||
|
(view): Added sync_index, buffer_pointer, view_var, burst, view_horizon,
|
||||||
|
expanded_push_pop and info.
|
||||||
|
(prepare_inner_context_for_streaming): Adapted to supported newly
|
||||||
|
expansion correctly updateing elements in regions_streamization_info.
|
||||||
|
(compute_data_position): Added function to simplify expansion to buffer
|
||||||
|
positions by index.
|
||||||
|
(create_data_pointer): Removed
|
||||||
|
(is_same_expression): Added function to identify similar tree node
|
||||||
|
expressions. Used to compare with operands used in code to substitute
|
||||||
|
the view_var by a direct buffer access.
|
||||||
|
(convert_view_var_array_struct, convert_view_var_array): Strucutre and
|
||||||
|
function traverser callback to convert the view_vars in direct buffer
|
||||||
|
accesses. Uses is_same_expression function to compare tree expressions.
|
||||||
|
(list_bbs_in_sese): Function to create a list of BBS inside of a SESE
|
||||||
|
region. We use it to identify which BBS we should traverse to
|
||||||
|
substitute all view_var references by buffer acceses.
|
||||||
|
(convert_view_var_array_traverser): Function to traverse SESE
|
||||||
|
and substitute all the references of view_var by the respective buffer
|
||||||
|
pointer. It is a callback function but is not used as such.
|
||||||
|
(expand_view_traverser_callback): Changed how the expansion is
|
||||||
|
performed. Mainly, created different index variables, view_vars are
|
||||||
|
converted here by calls to convert_view_var_array_traverser instead of
|
||||||
|
the previous copy or memcpy that was done before.
|
||||||
|
(register_views_traverser_callback): Initialize newly introduced index
|
||||||
|
vars.
|
||||||
|
(expand_task_streaming_extensions): Adapted to reflect new syntax /
|
||||||
|
expansion.
|
||||||
|
(expand_push_and_pop_stubs): Updated to reflect new expansion. More
|
||||||
|
respectively, create stall / release statements before single regions.
|
||||||
|
(expand_omp_single): Setup SESE BBS nodes in stramization_info, both
|
||||||
|
task and single regions.
|
||||||
|
(retrieve_streams_info): Initialize new view structure elements.
|
||||||
|
|
||||||
|
* gimplify.c: Updated set default cluase for view var.
|
||||||
|
(gimplify_scan_omp_clauses): Added view var as local when omp a new
|
||||||
|
syntax input / output clause is used.
|
||||||
|
|
||||||
|
* c-parser.c: Added support for new input / output clause clauses.
|
||||||
|
(c_parser_omp_stream_identifier, (c_parser_omp_stream_clause): New
|
||||||
|
parsing function.
|
||||||
|
(c_parser_omp_clause_input, c_parser_omp_clause_output): Updated.
|
||||||
|
|
||||||
|
2010-07-22 Cupertino Miranda <cupertinomiranda@gmail.com>
|
||||||
|
|
||||||
|
* omp-low.c: Clearly commented code.
|
||||||
|
Renamed stream_task to regions_streamization_info
|
||||||
|
Renamed create_synchronization to expand_view_traverser_callback
|
||||||
|
(stream, _lookup_stream): Added access_type, element_size, element_type
|
||||||
|
to stream structure. Initialized those in _lookup_stream.
|
||||||
|
(prepare_inner_context_for_streaming): Updated comments. Removed
|
||||||
|
repeated split_edge call for outer_latch. Removed call to remove edge.
|
||||||
|
(create_data_pointer): Changed way to obtain stream elements size.
|
||||||
|
(expand_view_traverser_callback): In case elements being accessed in
|
||||||
|
view are typed ARRAY_DECL then the data in it is fully copied to and
|
||||||
|
from the buffer with a MEMCPY built in.
|
||||||
|
(lower_copyprivate_clauses): Removed call to build_fold_addr_expr_loc.
|
||||||
|
Removed a couple of redundant calls to cleanup_tree_cfg.
|
||||||
|
|
||||||
|
2010-07-20 Antoniu Pop <antoniu.pop@gmail.com>
|
||||||
|
|
||||||
|
* omp-low.c (create_task_copyfn): Added cases for OMP_CLAUSE_INPUT
|
||||||
|
and OMP_CLAUSE_OUTPUT to create the proper copy-in code for the
|
||||||
|
marshalling function.
|
||||||
|
|
||||||
|
2010-07-09 Cupertino Miranda <cupertinomiranda@gmail.com>
|
||||||
|
|
||||||
|
* omp-low.c (clause_to_var_struct, hash_clause_to_var,
|
||||||
|
eq_clause_to_var, lookup_var_for_clause): New structure,
|
||||||
|
hash table and the accessor functions.
|
||||||
|
|
||||||
|
2010-07-06 Cupertino Miranda <cupertinomiranda@gmail.com>
|
||||||
|
|
||||||
|
* omp-low.c (stream_task, get_streamization_info_for_region):
|
||||||
|
Structure and creator/accessor functions streamization
|
||||||
|
information used through code expnsion.
|
||||||
|
(stream, htab_stream, hash_stream, eq_stream, lookup_stream,
|
||||||
|
_lookup_stream): New structure, hash table and the accessor
|
||||||
|
functions.
|
||||||
|
(view, hash_view, eq_view, alloc_view, _lookup_view,
|
||||||
|
lookup_view, maybe_lookup_view): New structure, hash table
|
||||||
|
and the accessor functions.
|
||||||
|
(stmt_location, stmt_loc, htab_stmt_loc, hash_stmt_loc,
|
||||||
|
eq_stmt_loc, get_stmt_loc, lookup_stmt_loc, set_stmt_loc,
|
||||||
|
set_stmt_loc_if_none): New structure, hash table and the
|
||||||
|
accessor functions.
|
||||||
|
(TRAVERSE_VIEWS_IN_REGION_AND_SUBS, TRAVERSE_VIEWS_IN_REGION,
|
||||||
|
GET_VIEW_FOR_STREAM_WITH_POINTER): New macros
|
||||||
|
(scan_sharing_clauses, lower_rec_input_clauses, expand_omp_taskreg,
|
||||||
|
lower_send_clauses, expand_omp_single, execute_expand_omp,
|
||||||
|
lower_omp_taskreg, execute_lower_omp):
|
||||||
|
Implement streamization of INPUT/OUTPUT clauses.
|
||||||
|
|
||||||
|
* c-parser.c (c_parser_omp_clause_name, c_parser_omp_all_clauses,
|
||||||
|
OMP_TASK_CLAUSE_MASK): Added OMP_CLAUSE_INPUT and
|
||||||
|
OMP_CLAUSE_OUTPUT cases.
|
||||||
|
(c_parser_omp_clause_input, c_parser_omp_clause_output): New.
|
||||||
|
|
||||||
|
* tree-flow.h (omp_region): Added streamization_init_bb and
|
||||||
|
streamization_exit_bb fields.
|
||||||
|
* c-pragma.h (pragma_omp_clause): Add OMP_CLAUSE_INPUT
|
||||||
|
OMP_CLAUSE_OUTPUT clauses.
|
||||||
|
* c-typeck.c (c_finish_omp_clauses): Added OMP_CLAUSE_INPUT and
|
||||||
|
OMP_CLAUSE_OUTPUT cases.
|
||||||
|
* gimplify.c (gimplify_scan_omp_clauses,
|
||||||
|
gimplify_adjust_omp_clauses): Added OMP_CLAUSE_INPUT and
|
||||||
|
OMP_CLAUSE_OUTPUT cases.
|
||||||
|
* tree.c (omp_clause_num_ops, omp_clause_code_name, walk_tree_1):
|
||||||
|
Add and handle OMP_CLAUSE_INPUT and OMP_CLAUSE_OUTPUT cases.
|
||||||
|
* tree.h (omp_clause_code): Add OMP_CLAUSE_INPUT
|
||||||
|
OMP_CLAUSE_OUTPUT clauses.
|
||||||
|
* tree-pretty-print.c (dump_omp_clause): Added OMP_CLAUSE_INPUT
|
||||||
|
and OMP_CLAUSE_OUTPUT cases.
|
||||||
|
|
||||||
|
2010-07-01 Antoniu Pop <antoniu.pop@gmail.com>
|
||||||
|
|
||||||
|
* builtin-types.def (BT_FN_ULL_PTR_ULL, BT_FN_VOID_PTR_ULL)
|
||||||
|
(BT_FN_PTR_SIZE_ULL_PTR, BT_FN_VOID_PTR_INT_INT_INT): New builtin
|
||||||
|
types for the GOMP stream runtime.
|
||||||
|
* omp-builtins.def (BUILT_IN_GOMP_STREAM_CREATE_STREAM)
|
||||||
|
(BUILT_IN_GOMP_STREAM_CREATE_READ_VIEW)
|
||||||
|
(BUILT_IN_GOMP_STREAM_CREATE_WRITE_VIEW)
|
||||||
|
(BUILT_IN_GOMP_STREAM_CREATE_TASK)
|
||||||
|
(BUILT_IN_GOMP_STREAM_ADD_EXPECTED_VIEWS)
|
||||||
|
(BUILT_IN_GOMP_STREAM_CONNECT_VIEW)
|
||||||
|
(BUILT_IN_GOMP_STREAM_WAIT_UNTIL_CONNECTED)
|
||||||
|
(BUILT_IN_GOMP_STREAM_UPDATE, BUILT_IN_GOMP_STREAM_STALL)
|
||||||
|
(BUILT_IN_GOMP_STREAM_RELEASE, BUILT_IN_GOMP_STREAM_COMMIT)
|
||||||
|
(BUILT_IN_GOMP_STREAM_TASK_EXIT): New builtin functions of the
|
||||||
|
GOMP stream runtime.
|
||||||
|
|
||||||
|
2010-06-30 Cupertino Miranda <cupertinomiranda@gmail.com>
|
||||||
|
|
||||||
|
* Branch from mainline (r158338).
|
|
@ -218,6 +218,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG)
|
||||||
DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
|
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_UINT32_UINT32, BT_UINT32, BT_UINT32)
|
||||||
DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64)
|
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_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
|
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
|
||||||
|
|
||||||
|
@ -313,6 +314,10 @@ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_LONGPTR_LONGPTR,
|
||||||
BT_BOOL, BT_PTR_LONG, BT_PTR_LONG)
|
BT_BOOL, BT_PTR_LONG, BT_PTR_LONG)
|
||||||
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR,
|
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR,
|
||||||
BT_BOOL, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
|
BT_BOOL, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
|
||||||
|
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_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
|
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
|
||||||
|
|
||||||
|
@ -381,6 +386,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
|
||||||
BT_PTR, BT_UINT)
|
BT_PTR, BT_UINT)
|
||||||
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_INT_SIZE, BT_PTR,
|
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_INT_SIZE, BT_PTR,
|
||||||
BT_CONST_PTR, BT_INT, BT_SIZE)
|
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_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
|
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
|
||||||
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
|
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
|
||||||
|
@ -400,6 +407,8 @@ DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
|
||||||
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
|
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
|
||||||
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
|
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
|
||||||
BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
|
BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
|
||||||
|
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_INT_INT_INT,
|
||||||
|
BT_VOID, BT_PTR, BT_INT, BT_INT, BT_INT)
|
||||||
|
|
||||||
DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
|
DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
|
||||||
BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
|
BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
|
||||||
|
|
187
gcc/c-parser.c
187
gcc/c-parser.c
|
@ -7156,6 +7156,10 @@ c_parser_omp_clause_name (c_parser *parser)
|
||||||
if (!strcmp ("firstprivate", p))
|
if (!strcmp ("firstprivate", p))
|
||||||
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
|
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
if (!strcmp ("input", p))
|
||||||
|
result = PRAGMA_OMP_CLAUSE_INPUT;
|
||||||
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
if (!strcmp ("lastprivate", p))
|
if (!strcmp ("lastprivate", p))
|
||||||
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
|
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
|
||||||
|
@ -7169,6 +7173,8 @@ c_parser_omp_clause_name (c_parser *parser)
|
||||||
case 'o':
|
case 'o':
|
||||||
if (!strcmp ("ordered", p))
|
if (!strcmp ("ordered", p))
|
||||||
result = PRAGMA_OMP_CLAUSE_ORDERED;
|
result = PRAGMA_OMP_CLAUSE_ORDERED;
|
||||||
|
else if (!strcmp ("output", p))
|
||||||
|
result = PRAGMA_OMP_CLAUSE_OUTPUT;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
if (!strcmp ("private", p))
|
if (!strcmp ("private", p))
|
||||||
|
@ -7267,6 +7273,157 @@ c_parser_omp_variable_list (c_parser *parser,
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* OpenMP X.X:
|
||||||
|
stream-list:
|
||||||
|
identifier ************************
|
||||||
|
variable-list , identifier
|
||||||
|
|
||||||
|
KIND must be OMP_CLAUSE_INPUT or OMP_CLAUSE_OUTPUT. */
|
||||||
|
static bool
|
||||||
|
c_parser_omp_stream_identifier (c_parser *parser, location_t loc,
|
||||||
|
tree *id, tree *sub)
|
||||||
|
{
|
||||||
|
if (c_parser_next_token_is_not (parser, CPP_NAME)
|
||||||
|
|| c_parser_peek_token (parser)->id_kind != C_ID_ID)
|
||||||
|
c_parser_error (parser, "expected stream or view identifier");
|
||||||
|
|
||||||
|
*id = lookup_name (c_parser_peek_token (parser)->value);
|
||||||
|
if (*id == NULL_TREE)
|
||||||
|
{
|
||||||
|
inform (loc, "OpenMP stream and view identifiers must"
|
||||||
|
" be declared before use in streaming clauses.");
|
||||||
|
undeclared_variable (c_parser_peek_token (parser)->location,
|
||||||
|
c_parser_peek_token (parser)->value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*id == error_mark_node)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
c_parser_consume_token (parser);
|
||||||
|
|
||||||
|
/* If this is an array reference. */
|
||||||
|
if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
|
||||||
|
{
|
||||||
|
c_parser_consume_token (parser);
|
||||||
|
*sub = c_parser_expression (parser).value;
|
||||||
|
c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
|
||||||
|
"expected %<]%>");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*sub = NULL_TREE;
|
||||||
|
|
||||||
|
if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
|
||||||
|
{
|
||||||
|
c_parser_error (parser, "single dimension arrays"
|
||||||
|
" supported only in streaming clauses");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next, we must either connect a view or have another stream use
|
||||||
|
separated by a comma, or the closing parenthesis. This test
|
||||||
|
prevents all other syntaxes that will be supported later (like
|
||||||
|
dot or deref ...) */
|
||||||
|
if (c_parser_next_token_is_not (parser, CPP_LSHIFT)
|
||||||
|
&& c_parser_next_token_is_not (parser, CPP_RSHIFT)
|
||||||
|
&& c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)
|
||||||
|
&& c_parser_next_token_is_not (parser, CPP_COMMA))
|
||||||
|
{
|
||||||
|
c_parser_error (parser, "wrong syntax on streaming clause");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tree
|
||||||
|
c_parser_omp_stream_clause (c_parser *parser,
|
||||||
|
enum omp_clause_code kind,
|
||||||
|
tree list)
|
||||||
|
{
|
||||||
|
/* The clause's location. */
|
||||||
|
location_t clause_loc = c_parser_peek_token (parser)->location;
|
||||||
|
|
||||||
|
gcc_assert (kind == OMP_CLAUSE_INPUT || kind == OMP_CLAUSE_OUTPUT);
|
||||||
|
|
||||||
|
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
|
||||||
|
return list;
|
||||||
|
|
||||||
|
/* Every stream clause must start with either a stream identifier or
|
||||||
|
a view identifier. */
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
tree stream_id, stream_idx, view_id, view_idx;
|
||||||
|
tree omp_clause;
|
||||||
|
|
||||||
|
if (!c_parser_omp_stream_identifier (parser, clause_loc,
|
||||||
|
&stream_id, &stream_idx))
|
||||||
|
break;
|
||||||
|
|
||||||
|
omp_clause = build_omp_clause (clause_loc, kind);
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
bool lshift_stream_operator_p =
|
||||||
|
c_parser_next_token_is (parser, CPP_LSHIFT);
|
||||||
|
|
||||||
|
c_parser_consume_token (parser);
|
||||||
|
|
||||||
|
if (!c_parser_omp_stream_identifier (parser, clause_loc,
|
||||||
|
&view_id, &view_idx))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* If the clause is reversed ("view << >> stream" instead of
|
||||||
|
"stream << >> view"), swap the roles. */
|
||||||
|
if ((kind == OMP_CLAUSE_INPUT && lshift_stream_operator_p)
|
||||||
|
|| (kind == OMP_CLAUSE_OUTPUT && !lshift_stream_operator_p))
|
||||||
|
{
|
||||||
|
OMP_CLAUSE_STREAM_ID (omp_clause) = view_id;
|
||||||
|
view_id = stream_id;
|
||||||
|
OMP_CLAUSE_STREAM_SUB (omp_clause) = view_idx;
|
||||||
|
view_idx = stream_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
OMP_CLAUSE_VIEW_ID (omp_clause) = view_id;
|
||||||
|
OMP_CLAUSE_BURST_SIZE (omp_clause) = view_idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OMP_CLAUSE_VIEW_ID (omp_clause) = NULL_TREE;
|
||||||
|
OMP_CLAUSE_BURST_SIZE (omp_clause) = NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
OMP_CLAUSE_CHAIN (omp_clause) = list;
|
||||||
|
list = omp_clause;
|
||||||
|
|
||||||
|
// TODO: TINO Check this
|
||||||
|
//if(OMP_CLAUSE_VIEW_ID (omp_clause) != NULL_TREE)
|
||||||
|
//{
|
||||||
|
// tree new_omp_clause = build_omp_clause (clause_loc, OMP_CLAUSE_PRIVATE);
|
||||||
|
// OMP_CLAUSE_DECL (new_omp_clause) = OMP_CLAUSE_VIEW_ID (omp_clause);
|
||||||
|
// OMP_CLAUSE_CHAIN (new_omp_clause) = list;
|
||||||
|
// list = new_omp_clause;
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (c_parser_next_token_is (parser, CPP_COMMA))
|
||||||
|
c_parser_consume_token (parser);
|
||||||
|
else if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c_parser_error (parser, "expected %<,%> or %<)%>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/* Similarly, but expect leading and trailing parenthesis. This is a very
|
/* Similarly, but expect leading and trailing parenthesis. This is a very
|
||||||
common case for omp clauses. */
|
common case for omp clauses. */
|
||||||
|
|
||||||
|
@ -7426,6 +7583,15 @@ c_parser_omp_clause_if (c_parser *parser, tree list)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* OpenMP stream extension:
|
||||||
|
input ( variable-list ) */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
c_parser_omp_clause_input (c_parser *parser, tree list)
|
||||||
|
{
|
||||||
|
return c_parser_omp_stream_clause (parser, OMP_CLAUSE_INPUT, list);
|
||||||
|
}
|
||||||
|
|
||||||
/* OpenMP 2.5:
|
/* OpenMP 2.5:
|
||||||
lastprivate ( variable-list ) */
|
lastprivate ( variable-list ) */
|
||||||
|
|
||||||
|
@ -7512,6 +7678,15 @@ c_parser_omp_clause_ordered (c_parser *parser, tree list)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* OpenMP stream extension:
|
||||||
|
output ( variable-list ) */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
c_parser_omp_clause_output (c_parser *parser, tree list)
|
||||||
|
{
|
||||||
|
return c_parser_omp_stream_clause (parser, OMP_CLAUSE_OUTPUT, list);
|
||||||
|
}
|
||||||
|
|
||||||
/* OpenMP 2.5:
|
/* OpenMP 2.5:
|
||||||
private ( variable-list ) */
|
private ( variable-list ) */
|
||||||
|
|
||||||
|
@ -7756,6 +7931,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
|
||||||
clauses = c_parser_omp_clause_if (parser, clauses);
|
clauses = c_parser_omp_clause_if (parser, clauses);
|
||||||
c_name = "if";
|
c_name = "if";
|
||||||
break;
|
break;
|
||||||
|
case PRAGMA_OMP_CLAUSE_INPUT:
|
||||||
|
clauses = c_parser_omp_clause_input (parser, clauses);
|
||||||
|
c_name = "input";
|
||||||
|
break;
|
||||||
case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
|
case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
|
||||||
clauses = c_parser_omp_clause_lastprivate (parser, clauses);
|
clauses = c_parser_omp_clause_lastprivate (parser, clauses);
|
||||||
c_name = "lastprivate";
|
c_name = "lastprivate";
|
||||||
|
@ -7772,6 +7951,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask,
|
||||||
clauses = c_parser_omp_clause_ordered (parser, clauses);
|
clauses = c_parser_omp_clause_ordered (parser, clauses);
|
||||||
c_name = "ordered";
|
c_name = "ordered";
|
||||||
break;
|
break;
|
||||||
|
case PRAGMA_OMP_CLAUSE_OUTPUT:
|
||||||
|
clauses = c_parser_omp_clause_output (parser, clauses);
|
||||||
|
c_name = "output";
|
||||||
|
break;
|
||||||
case PRAGMA_OMP_CLAUSE_PRIVATE:
|
case PRAGMA_OMP_CLAUSE_PRIVATE:
|
||||||
clauses = c_parser_omp_clause_private (parser, clauses);
|
clauses = c_parser_omp_clause_private (parser, clauses);
|
||||||
c_name = "private";
|
c_name = "private";
|
||||||
|
@ -8583,7 +8766,9 @@ c_parser_omp_single (location_t loc, c_parser *parser)
|
||||||
| (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
|
| (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
|
||||||
| (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
|
| (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
|
||||||
| (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
|
| (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
|
||||||
| (1u << PRAGMA_OMP_CLAUSE_SHARED))
|
| (1u << PRAGMA_OMP_CLAUSE_SHARED)) \
|
||||||
|
| (1u << PRAGMA_OMP_CLAUSE_INPUT) \
|
||||||
|
| (1u << PRAGMA_OMP_CLAUSE_OUTPUT)
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
c_parser_omp_task (location_t loc, c_parser *parser)
|
c_parser_omp_task (location_t loc, c_parser *parser)
|
||||||
|
|
|
@ -62,10 +62,12 @@ typedef enum pragma_omp_clause {
|
||||||
PRAGMA_OMP_CLAUSE_DEFAULT,
|
PRAGMA_OMP_CLAUSE_DEFAULT,
|
||||||
PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
|
PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
|
||||||
PRAGMA_OMP_CLAUSE_IF,
|
PRAGMA_OMP_CLAUSE_IF,
|
||||||
|
PRAGMA_OMP_CLAUSE_INPUT,
|
||||||
PRAGMA_OMP_CLAUSE_LASTPRIVATE,
|
PRAGMA_OMP_CLAUSE_LASTPRIVATE,
|
||||||
PRAGMA_OMP_CLAUSE_NOWAIT,
|
PRAGMA_OMP_CLAUSE_NOWAIT,
|
||||||
PRAGMA_OMP_CLAUSE_NUM_THREADS,
|
PRAGMA_OMP_CLAUSE_NUM_THREADS,
|
||||||
PRAGMA_OMP_CLAUSE_ORDERED,
|
PRAGMA_OMP_CLAUSE_ORDERED,
|
||||||
|
PRAGMA_OMP_CLAUSE_OUTPUT,
|
||||||
PRAGMA_OMP_CLAUSE_PRIVATE,
|
PRAGMA_OMP_CLAUSE_PRIVATE,
|
||||||
PRAGMA_OMP_CLAUSE_REDUCTION,
|
PRAGMA_OMP_CLAUSE_REDUCTION,
|
||||||
PRAGMA_OMP_CLAUSE_SCHEDULE,
|
PRAGMA_OMP_CLAUSE_SCHEDULE,
|
||||||
|
|
|
@ -10272,6 +10272,20 @@ c_finish_omp_clauses (tree clauses)
|
||||||
bitmap_set_bit (&lastprivate_head, DECL_UID (t));
|
bitmap_set_bit (&lastprivate_head, DECL_UID (t));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OMP_CLAUSE_INPUT:
|
||||||
|
name = "input";
|
||||||
|
t = OMP_CLAUSE_DECL (c);
|
||||||
|
need_complete = true;
|
||||||
|
need_implicitly_determined = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OMP_CLAUSE_OUTPUT:
|
||||||
|
name = "output";
|
||||||
|
t = OMP_CLAUSE_DECL (c);
|
||||||
|
need_complete = true;
|
||||||
|
need_implicitly_determined = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case OMP_CLAUSE_IF:
|
case OMP_CLAUSE_IF:
|
||||||
case OMP_CLAUSE_NUM_THREADS:
|
case OMP_CLAUSE_NUM_THREADS:
|
||||||
case OMP_CLAUSE_SCHEDULE:
|
case OMP_CLAUSE_SCHEDULE:
|
||||||
|
|
|
@ -5734,6 +5734,15 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
|
||||||
flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
|
flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
|
||||||
check_non_private = "reduction";
|
check_non_private = "reduction";
|
||||||
goto do_add;
|
goto do_add;
|
||||||
|
case OMP_CLAUSE_INPUT:
|
||||||
|
case OMP_CLAUSE_OUTPUT:
|
||||||
|
{
|
||||||
|
tree view = OMP_CLAUSE_VIEW_ID (c);
|
||||||
|
if(view != NULL_TREE)
|
||||||
|
omp_add_variable (ctx, view, GOVD_LOCAL | GOVD_SEEN);
|
||||||
|
}
|
||||||
|
flags = GOVD_PRIVATE | GOVD_EXPLICIT;
|
||||||
|
goto do_add;
|
||||||
|
|
||||||
do_add:
|
do_add:
|
||||||
decl = OMP_CLAUSE_DECL (c);
|
decl = OMP_CLAUSE_DECL (c);
|
||||||
|
@ -5959,6 +5968,8 @@ gimplify_adjust_omp_clauses (tree *list_p)
|
||||||
= (n->value & GOVD_FIRSTPRIVATE) != 0;
|
= (n->value & GOVD_FIRSTPRIVATE) != 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OMP_CLAUSE_INPUT:
|
||||||
|
case OMP_CLAUSE_OUTPUT:
|
||||||
case OMP_CLAUSE_REDUCTION:
|
case OMP_CLAUSE_REDUCTION:
|
||||||
case OMP_CLAUSE_COPYIN:
|
case OMP_CLAUSE_COPYIN:
|
||||||
case OMP_CLAUSE_COPYPRIVATE:
|
case OMP_CLAUSE_COPYPRIVATE:
|
||||||
|
|
|
@ -206,3 +206,40 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_START, "GOMP_single_copy_start",
|
||||||
BT_FN_PTR, ATTR_NOTHROW_LIST)
|
BT_FN_PTR, ATTR_NOTHROW_LIST)
|
||||||
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_END, "GOMP_single_copy_end",
|
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_END, "GOMP_single_copy_end",
|
||||||
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
|
BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
|
||||||
|
|
||||||
|
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CREATE_STREAM,
|
||||||
|
"GOMP_stream_create_stream",
|
||||||
|
BT_FN_PTR_SIZE_ULL_PTR, ATTR_NOTHROW_LIST)
|
||||||
|
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CREATE_READ_VIEW,
|
||||||
|
"GOMP_stream_create_read_view",
|
||||||
|
BT_FN_PTR, ATTR_NOTHROW_LIST)
|
||||||
|
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CREATE_WRITE_VIEW,
|
||||||
|
"GOMP_stream_create_write_view",
|
||||||
|
BT_FN_PTR, 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_ADD_EXPECTED_VIEWS,
|
||||||
|
"GOMP_stream_add_expected_views",
|
||||||
|
BT_FN_VOID_PTR_INT_INT_INT, ATTR_NOTHROW_LIST)
|
||||||
|
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_CONNECT_VIEW,
|
||||||
|
"GOMP_stream_connect_view",
|
||||||
|
BT_FN_VOID_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
|
||||||
|
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",
|
||||||
|
BT_FN_ULL_PTR_ULL, ATTR_NOTHROW_LIST)
|
||||||
|
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_STREAM_STALL, "GOMP_stream_stall",
|
||||||
|
BT_FN_VOID_PTR_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",
|
||||||
|
BT_FN_VOID_PTR_ULL, ATTR_NOTHROW_LIST)
|
||||||
|
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_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",
|
||||||
|
BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LIST)
|
||||||
|
|
1909
gcc/omp-low.c
1909
gcc/omp-low.c
File diff suppressed because it is too large
Load Diff
|
@ -406,6 +406,12 @@ struct omp_region
|
||||||
|
|
||||||
/* True if this is a combined parallel+workshare region. */
|
/* True if this is a combined parallel+workshare region. */
|
||||||
bool is_combined_parallel;
|
bool is_combined_parallel;
|
||||||
|
|
||||||
|
/* Streams accessed by this region */
|
||||||
|
htab_t view_pointers;
|
||||||
|
|
||||||
|
/* Streamization data */
|
||||||
|
void *streamization_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct omp_region *root_omp_region;
|
extern struct omp_region *root_omp_region;
|
||||||
|
|
|
@ -307,6 +307,12 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
|
||||||
case OMP_CLAUSE_LASTPRIVATE:
|
case OMP_CLAUSE_LASTPRIVATE:
|
||||||
name = "lastprivate";
|
name = "lastprivate";
|
||||||
goto print_remap;
|
goto print_remap;
|
||||||
|
case OMP_CLAUSE_INPUT:
|
||||||
|
name = "input";
|
||||||
|
goto print_remap;
|
||||||
|
case OMP_CLAUSE_OUTPUT:
|
||||||
|
name = "output";
|
||||||
|
goto print_remap;
|
||||||
case OMP_CLAUSE_COPYIN:
|
case OMP_CLAUSE_COPYIN:
|
||||||
name = "copyin";
|
name = "copyin";
|
||||||
goto print_remap;
|
goto print_remap;
|
||||||
|
|
|
@ -233,6 +233,8 @@ unsigned const char omp_clause_num_ops[] =
|
||||||
1, /* OMP_CLAUSE_SHARED */
|
1, /* OMP_CLAUSE_SHARED */
|
||||||
1, /* OMP_CLAUSE_FIRSTPRIVATE */
|
1, /* OMP_CLAUSE_FIRSTPRIVATE */
|
||||||
2, /* OMP_CLAUSE_LASTPRIVATE */
|
2, /* OMP_CLAUSE_LASTPRIVATE */
|
||||||
|
4, /* OMP_CLAUSE_INPUT */
|
||||||
|
4, /* OMP_CLAUSE_OUTPUT */
|
||||||
4, /* OMP_CLAUSE_REDUCTION */
|
4, /* OMP_CLAUSE_REDUCTION */
|
||||||
1, /* OMP_CLAUSE_COPYIN */
|
1, /* OMP_CLAUSE_COPYIN */
|
||||||
1, /* OMP_CLAUSE_COPYPRIVATE */
|
1, /* OMP_CLAUSE_COPYPRIVATE */
|
||||||
|
@ -243,7 +245,7 @@ unsigned const char omp_clause_num_ops[] =
|
||||||
0, /* OMP_CLAUSE_ORDERED */
|
0, /* OMP_CLAUSE_ORDERED */
|
||||||
0, /* OMP_CLAUSE_DEFAULT */
|
0, /* OMP_CLAUSE_DEFAULT */
|
||||||
3, /* OMP_CLAUSE_COLLAPSE */
|
3, /* OMP_CLAUSE_COLLAPSE */
|
||||||
0 /* OMP_CLAUSE_UNTIED */
|
0, /* OMP_CLAUSE_UNTIED */
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * const omp_clause_code_name[] =
|
const char * const omp_clause_code_name[] =
|
||||||
|
@ -253,6 +255,8 @@ const char * const omp_clause_code_name[] =
|
||||||
"shared",
|
"shared",
|
||||||
"firstprivate",
|
"firstprivate",
|
||||||
"lastprivate",
|
"lastprivate",
|
||||||
|
"input",
|
||||||
|
"output",
|
||||||
"reduction",
|
"reduction",
|
||||||
"copyin",
|
"copyin",
|
||||||
"copyprivate",
|
"copyprivate",
|
||||||
|
@ -10215,6 +10219,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
|
||||||
case OMP_CLAUSE_PRIVATE:
|
case OMP_CLAUSE_PRIVATE:
|
||||||
case OMP_CLAUSE_SHARED:
|
case OMP_CLAUSE_SHARED:
|
||||||
case OMP_CLAUSE_FIRSTPRIVATE:
|
case OMP_CLAUSE_FIRSTPRIVATE:
|
||||||
|
case OMP_CLAUSE_INPUT:
|
||||||
|
case OMP_CLAUSE_OUTPUT:
|
||||||
case OMP_CLAUSE_COPYIN:
|
case OMP_CLAUSE_COPYIN:
|
||||||
case OMP_CLAUSE_COPYPRIVATE:
|
case OMP_CLAUSE_COPYPRIVATE:
|
||||||
case OMP_CLAUSE_IF:
|
case OMP_CLAUSE_IF:
|
||||||
|
|
24
gcc/tree.h
24
gcc/tree.h
|
@ -295,6 +295,12 @@ enum omp_clause_code
|
||||||
/* OpenMP clause: lastprivate (variable_list). */
|
/* OpenMP clause: lastprivate (variable_list). */
|
||||||
OMP_CLAUSE_LASTPRIVATE,
|
OMP_CLAUSE_LASTPRIVATE,
|
||||||
|
|
||||||
|
/* OpenMP clause: firstprivate (variable_list). */
|
||||||
|
OMP_CLAUSE_INPUT,
|
||||||
|
|
||||||
|
/* OpenMP clause: lastprivate (variable_list). */
|
||||||
|
OMP_CLAUSE_OUTPUT,
|
||||||
|
|
||||||
/* OpenMP clause: reduction (operator:variable_list).
|
/* OpenMP clause: reduction (operator:variable_list).
|
||||||
OMP_CLAUSE_REDUCTION_CODE: The tree_code of the operator.
|
OMP_CLAUSE_REDUCTION_CODE: The tree_code of the operator.
|
||||||
Operand 1: OMP_CLAUSE_REDUCTION_INIT: Stmt-list to initialize the var.
|
Operand 1: OMP_CLAUSE_REDUCTION_INIT: Stmt-list to initialize the var.
|
||||||
|
@ -1760,6 +1766,24 @@ extern void protected_set_expr_location (tree, location_t);
|
||||||
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
|
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
|
||||||
OMP_CLAUSE_PRIVATE, \
|
OMP_CLAUSE_PRIVATE, \
|
||||||
OMP_CLAUSE_COPYPRIVATE), 0)
|
OMP_CLAUSE_COPYPRIVATE), 0)
|
||||||
|
|
||||||
|
#define OMP_CLAUSE_STREAM_ID(NODE) \
|
||||||
|
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
|
||||||
|
OMP_CLAUSE_INPUT, \
|
||||||
|
OMP_CLAUSE_OUTPUT), 0)
|
||||||
|
#define OMP_CLAUSE_STREAM_SUB(NODE) \
|
||||||
|
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
|
||||||
|
OMP_CLAUSE_INPUT, \
|
||||||
|
OMP_CLAUSE_OUTPUT), 1)
|
||||||
|
#define OMP_CLAUSE_VIEW_ID(NODE) \
|
||||||
|
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
|
||||||
|
OMP_CLAUSE_INPUT, \
|
||||||
|
OMP_CLAUSE_OUTPUT), 2)
|
||||||
|
#define OMP_CLAUSE_BURST_SIZE(NODE) \
|
||||||
|
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
|
||||||
|
OMP_CLAUSE_INPUT, \
|
||||||
|
OMP_CLAUSE_OUTPUT), 3)
|
||||||
|
|
||||||
#define OMP_CLAUSE_HAS_LOCATION(NODE) \
|
#define OMP_CLAUSE_HAS_LOCATION(NODE) \
|
||||||
((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
|
((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
|
||||||
#define OMP_CLAUSE_LOCATION(NODE) (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus
|
#define OMP_CLAUSE_LOCATION(NODE) (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
2010-10-05 Antoniu Pop <antoniu.pop@gmail.com>
|
||||||
|
|
||||||
|
* stream.c (gomp_stream_add_view_to_list): Added missing sizeof
|
||||||
|
call inside gomp_realloc.
|
||||||
|
|
||||||
|
2010-07-10 Antoniu Pop <antoniu.pop@gmail.com>
|
||||||
|
|
||||||
|
* stream.c (GOMP_stream_connect_view): Update the
|
||||||
|
nr_registered_views field in the view_handle when connecting
|
||||||
|
views.
|
||||||
|
|
||||||
|
2010-07-05 Antoniu Pop <antoniu.pop@gmail.com>
|
||||||
|
|
||||||
|
* stream.c (gomp_stream_unregister_view): Set the EOS_P flag when
|
||||||
|
the last producer exits and commit up to the highest committed index.
|
||||||
|
(gomp_stream_compute_lower_max): New.
|
||||||
|
|
||||||
|
2010-07-05 Antoniu Pop <antoniu.pop@gmail.com>
|
||||||
|
|
||||||
|
* stream.c (GOMP_stream_create_stream): corrected initialization
|
||||||
|
values.
|
||||||
|
|
||||||
|
2010-07-01 Antoniu Pop <antoniu.pop@gmail.com>
|
||||||
|
|
||||||
|
* stream.h: New.
|
||||||
|
* stream.c: New.
|
||||||
|
* Makefile.am (libgomp_la_SOURCES): Added stream.c
|
||||||
|
* Makefile.in: Regenerated.
|
||||||
|
* libgomp.h: Include stream.h
|
||||||
|
* libgomp_g.h (GOMP_stream_create_stream)
|
||||||
|
(GOMP_stream_create_read_view, GOMP_stream_create_write_view)
|
||||||
|
(GOMP_stream_create_task, GOMP_stream_add_expected_views)
|
||||||
|
(GOMP_stream_connect_view, GOMP_stream_wait_until_connected)
|
||||||
|
(GOMP_stream_update, GOMP_stream_stall, GOMP_stream_release)
|
||||||
|
(GOMP_stream_commit, GOMP_stream_task_exit): Declared builtins
|
||||||
|
from stream.c
|
||||||
|
* libgomp.map: Export GOMP_stream_*.
|
||||||
|
* omp.h.in: Added GOMP_stream_* to the OpenMP public interface.
|
|
@ -34,7 +34,7 @@ libgomp_la_LINK = $(LINK) $(libgomp_la_LDFLAGS)
|
||||||
libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \
|
libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \
|
||||||
iter_ull.c loop.c loop_ull.c ordered.c parallel.c sections.c single.c \
|
iter_ull.c loop.c loop_ull.c ordered.c parallel.c sections.c single.c \
|
||||||
task.c team.c work.c lock.c mutex.c proc.c sem.c bar.c ptrlock.c \
|
task.c team.c work.c lock.c mutex.c proc.c sem.c bar.c ptrlock.c \
|
||||||
time.c fortran.c affinity.c
|
time.c fortran.c affinity.c stream.c
|
||||||
|
|
||||||
nodist_noinst_HEADERS = libgomp_f.h
|
nodist_noinst_HEADERS = libgomp_f.h
|
||||||
nodist_libsubinclude_HEADERS = omp.h
|
nodist_libsubinclude_HEADERS = omp.h
|
||||||
|
|
|
@ -95,7 +95,7 @@ am_libgomp_la_OBJECTS = alloc.lo barrier.lo critical.lo env.lo \
|
||||||
error.lo iter.lo iter_ull.lo loop.lo loop_ull.lo ordered.lo \
|
error.lo iter.lo iter_ull.lo loop.lo loop_ull.lo ordered.lo \
|
||||||
parallel.lo sections.lo single.lo task.lo team.lo work.lo \
|
parallel.lo sections.lo single.lo task.lo team.lo work.lo \
|
||||||
lock.lo mutex.lo proc.lo sem.lo bar.lo ptrlock.lo time.lo \
|
lock.lo mutex.lo proc.lo sem.lo bar.lo ptrlock.lo time.lo \
|
||||||
fortran.lo affinity.lo
|
fortran.lo affinity.lo stream.lo
|
||||||
libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS)
|
libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS)
|
||||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||||
depcomp = $(SHELL) $(top_srcdir)/../depcomp
|
depcomp = $(SHELL) $(top_srcdir)/../depcomp
|
||||||
|
@ -306,7 +306,7 @@ libgomp_la_LINK = $(LINK) $(libgomp_la_LDFLAGS)
|
||||||
libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \
|
libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \
|
||||||
iter_ull.c loop.c loop_ull.c ordered.c parallel.c sections.c single.c \
|
iter_ull.c loop.c loop_ull.c ordered.c parallel.c sections.c single.c \
|
||||||
task.c team.c work.c lock.c mutex.c proc.c sem.c bar.c ptrlock.c \
|
task.c team.c work.c lock.c mutex.c proc.c sem.c bar.c ptrlock.c \
|
||||||
time.c fortran.c affinity.c
|
time.c fortran.c affinity.c stream.c
|
||||||
|
|
||||||
nodist_noinst_HEADERS = libgomp_f.h
|
nodist_noinst_HEADERS = libgomp_f.h
|
||||||
nodist_libsubinclude_HEADERS = omp.h
|
nodist_libsubinclude_HEADERS = omp.h
|
||||||
|
@ -463,6 +463,7 @@ distclean-compile:
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sections.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sections.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sem.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sem.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/single.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/single.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/team.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/team.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
#include "bar.h"
|
#include "bar.h"
|
||||||
#include "ptrlock.h"
|
#include "ptrlock.h"
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
|
|
||||||
/* This structure contains the data to control one work-sharing construct,
|
/* This structure contains the data to control one work-sharing construct,
|
||||||
|
|
|
@ -167,4 +167,17 @@ GOMP_2.0 {
|
||||||
GOMP_loop_ull_runtime_start;
|
GOMP_loop_ull_runtime_start;
|
||||||
GOMP_loop_ull_static_next;
|
GOMP_loop_ull_static_next;
|
||||||
GOMP_loop_ull_static_start;
|
GOMP_loop_ull_static_start;
|
||||||
|
GOMP_stream_create_stream;
|
||||||
|
GOMP_stream_create_read_view;
|
||||||
|
GOMP_stream_create_write_view;
|
||||||
|
GOMP_stream_create_task;
|
||||||
|
GOMP_stream_add_expected_views;
|
||||||
|
GOMP_stream_connect_view;
|
||||||
|
GOMP_stream_wait_until_connected;
|
||||||
|
GOMP_stream_update;
|
||||||
|
GOMP_stream_stall;
|
||||||
|
GOMP_stream_release;
|
||||||
|
GOMP_stream_commit;
|
||||||
|
GOMP_stream_task_exit;
|
||||||
} GOMP_1.0;
|
} GOMP_1.0;
|
||||||
|
|
||||||
|
|
|
@ -179,4 +179,21 @@ extern bool GOMP_single_start (void);
|
||||||
extern void *GOMP_single_copy_start (void);
|
extern void *GOMP_single_copy_start (void);
|
||||||
extern void GOMP_single_copy_end (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_task (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 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 *);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* LIBGOMP_G_H */
|
#endif /* LIBGOMP_G_H */
|
||||||
|
|
|
@ -102,4 +102,29 @@ int omp_get_active_level (void) __GOMP_NOTHROW;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define GOMP_STREAM_ACCESS(VIEW, INDEX, TYPE) \
|
||||||
|
(**((TYPE ***) (VIEW))) \
|
||||||
|
[(unsigned long long)(INDEX) & \
|
||||||
|
(*((unsigned long long *)((*((char ***) (VIEW))) + 1)))]
|
||||||
|
|
||||||
|
extern void *GOMP_stream_create_stream (size_t, unsigned long long, char *)
|
||||||
|
__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_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 *,
|
||||||
|
const unsigned long long)
|
||||||
|
__GOMP_NOTHROW;
|
||||||
|
extern void GOMP_stream_stall (void *, const unsigned long long)
|
||||||
|
__GOMP_NOTHROW;
|
||||||
|
extern void GOMP_stream_release (void *, const unsigned long long)
|
||||||
|
__GOMP_NOTHROW;
|
||||||
|
extern void GOMP_stream_commit (void *, const unsigned long long)
|
||||||
|
__GOMP_NOTHROW;
|
||||||
|
extern void GOMP_stream_task_exit (void *) __GOMP_NOTHROW;
|
||||||
|
|
||||||
#endif /* OMP_H */
|
#endif /* OMP_H */
|
||||||
|
|
|
@ -0,0 +1,562 @@
|
||||||
|
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
|
Contributed by Antoniu Pop <antoniu.pop@gmail.com>.
|
||||||
|
|
||||||
|
This file is part of the GNU OpenMP Library (libgomp).
|
||||||
|
|
||||||
|
Libgomp is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with libgomp; see the file COPYING.LIB. If not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
/* As a special exception, if you link this library with other files, some
|
||||||
|
of which are compiled with GCC, to produce an executable, this library
|
||||||
|
does not by itself cause the resulting executable to be covered by the
|
||||||
|
GNU General Public License. This exception does not however invalidate
|
||||||
|
any other reasons why the executable file might be covered by the GNU
|
||||||
|
General Public License. */
|
||||||
|
|
||||||
|
/* This implements the stream communication layer for libGOMP. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "wait.h"
|
||||||
|
#include "sem.h"
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "libgomp.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Data structures creation and pipeline initialization. */
|
||||||
|
|
||||||
|
/* Allocate and initialize a GOMP_STREAM for data elements of size
|
||||||
|
ELEMENT_SIZE using a circular buffer of STREAM_BUFFER_SIZE such
|
||||||
|
elements. Returns a pointer to the newly allocated stream. The
|
||||||
|
user may provide a pointer to pre-allocated memory to be used as
|
||||||
|
BUFFER for the stream. */
|
||||||
|
|
||||||
|
void *
|
||||||
|
GOMP_stream_create_stream (size_t element_size,
|
||||||
|
unsigned long long stream_buffer_size,
|
||||||
|
char *buffer)
|
||||||
|
{
|
||||||
|
gomp_stream_p stream = (gomp_stream_p) gomp_malloc (sizeof (gomp_stream_t));
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
stream->buffer_size = 1;
|
||||||
|
while(stream->buffer_size < stream_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->expected_ready_p = false;
|
||||||
|
stream->connected_p = false;
|
||||||
|
stream->eos_p = false;
|
||||||
|
|
||||||
|
/* Initialize the view_handles. */
|
||||||
|
stream->read_views.current_min = stream->buffer_size;
|
||||||
|
stream->read_views.current_max = 0;
|
||||||
|
stream->read_views.view_list.views = NULL;
|
||||||
|
stream->read_views.view_list.nr_views = 0;
|
||||||
|
stream->read_views.view_list.size = 0;
|
||||||
|
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);
|
||||||
|
|
||||||
|
stream->write_views.current_min = 0;
|
||||||
|
stream->write_views.current_max = stream->buffer_size;
|
||||||
|
stream->write_views.view_list.views = NULL;
|
||||||
|
stream->write_views.view_list.nr_views = 0;
|
||||||
|
stream->write_views.view_list.size = 0;
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifndef HAVE_SYNC_BUILTINS
|
||||||
|
gomp_mutex_init (&stream->stream_mutex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
|
||||||
|
static inline void *
|
||||||
|
gomp_stream_create_view (int type)
|
||||||
|
{
|
||||||
|
gomp_stream_view_p view =
|
||||||
|
(gomp_stream_view_p) gomp_malloc (sizeof(gomp_stream_view_t));
|
||||||
|
|
||||||
|
view->lower_index = 0;
|
||||||
|
view->upper_index = 0;
|
||||||
|
view->stream = NULL;
|
||||||
|
view->end_p = false;
|
||||||
|
view->type = type;
|
||||||
|
view->local_min_value = 0;
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrapper for creating a READ view. */
|
||||||
|
|
||||||
|
void *
|
||||||
|
GOMP_stream_create_read_view (void)
|
||||||
|
{
|
||||||
|
return gomp_stream_create_view (READ_VIEW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wrapper for creating a WRITE view. */
|
||||||
|
|
||||||
|
void *
|
||||||
|
GOMP_stream_create_write_view (void)
|
||||||
|
{
|
||||||
|
return gomp_stream_create_view (WRITE_VIEW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate and initialize a GOMP_STREAM_TASK data structure. */
|
||||||
|
|
||||||
|
void *
|
||||||
|
GOMP_stream_create_task (void)
|
||||||
|
{
|
||||||
|
gomp_stream_task_p task =
|
||||||
|
(gomp_stream_task_p) gomp_malloc (sizeof(gomp_stream_task_t));
|
||||||
|
|
||||||
|
task->read_view_list.views = NULL;
|
||||||
|
task->read_view_list.nr_views = 0;
|
||||||
|
task->read_view_list.size = 0;
|
||||||
|
|
||||||
|
task->write_view_list.views = NULL;
|
||||||
|
task->write_view_list.nr_views = 0;
|
||||||
|
task->write_view_list.size = 0;
|
||||||
|
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
views that will connect to a stream before the streaming tasks are
|
||||||
|
started. If this function is called on a stream, there will be no
|
||||||
|
further checks for the number of tasks partaking in the
|
||||||
|
initialization synchronization. */
|
||||||
|
|
||||||
|
void
|
||||||
|
GOMP_stream_add_expected_views (void *s, int read_views, int write_views,
|
||||||
|
int final)
|
||||||
|
{
|
||||||
|
gomp_stream_p stream = (gomp_stream_p) s;
|
||||||
|
|
||||||
|
if (stream->expected_ready_p)
|
||||||
|
gomp_fatal
|
||||||
|
("GOMP_stream: attempting to modify a final number of expected views.");
|
||||||
|
stream->expected_ready_p = final;
|
||||||
|
|
||||||
|
#ifdef HAVE_SYNC_BUILTINS
|
||||||
|
__sync_fetch_and_add (&stream->read_views.nr_expected_views, read_views);
|
||||||
|
__sync_fetch_and_add (&stream->write_views.nr_expected_views, write_views);
|
||||||
|
#else
|
||||||
|
gomp_mutex_lock (&stream->stream_mutex);
|
||||||
|
stream->read_views.nr_expected_views += read_views;
|
||||||
|
stream->write_views.nr_expected_views += write_views;
|
||||||
|
gomp_mutex_unlock (&stream->stream_mutex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add VIEW to the VIEW_LIST. We actually use an array as this list
|
||||||
|
is only modified in the initialization phase and we never remove
|
||||||
|
any items from it. */
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gomp_stream_add_view_to_list (gomp_stream_view_p view,
|
||||||
|
gomp_stream_view_list_p view_list)
|
||||||
|
{
|
||||||
|
/* Allocate memory when needed. */
|
||||||
|
if (view_list->views == NULL || view_list->nr_views == view_list->size)
|
||||||
|
{
|
||||||
|
if (view_list->size == 0)
|
||||||
|
view_list->size = 4;
|
||||||
|
if (view_list->nr_views == view_list->size)
|
||||||
|
view_list->size <<= 1;
|
||||||
|
|
||||||
|
view_list->views =
|
||||||
|
(gomp_stream_view_p *) gomp_realloc (view_list->views,
|
||||||
|
view_list->size * sizeof (gomp_stream_view_p));
|
||||||
|
}
|
||||||
|
|
||||||
|
view_list->views[view_list->nr_views] = view;
|
||||||
|
view_list->nr_views += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect a VIEW to a STREAM and also to the TASK which will use it.
|
||||||
|
This effectively builds the runtime task graph. */
|
||||||
|
|
||||||
|
void
|
||||||
|
GOMP_stream_connect_view (void *t, void *s, void *v)
|
||||||
|
{
|
||||||
|
gomp_stream_task_p task = (gomp_stream_task_p) t;
|
||||||
|
gomp_stream_p stream = (gomp_stream_p) s;
|
||||||
|
gomp_stream_view_p view = (gomp_stream_view_p) v;
|
||||||
|
|
||||||
|
gomp_stream_view_handle_p vh = (view->type == READ_VIEW) ?
|
||||||
|
&stream->read_views : &stream->write_views;
|
||||||
|
gomp_stream_view_list_p stream_list = &vh->view_list;
|
||||||
|
gomp_stream_view_list_p task_list = (view->type == READ_VIEW) ?
|
||||||
|
&task->read_view_list : &task->write_view_list;
|
||||||
|
|
||||||
|
view->stream = stream;
|
||||||
|
|
||||||
|
/* A read view's lower index is shifted by the buffer_size as the
|
||||||
|
stream is initially empty. This is equivalent to releasing the
|
||||||
|
original buffer_size elements. A write view will start with
|
||||||
|
buffer_size free space. */
|
||||||
|
if (view->type == READ_VIEW)
|
||||||
|
view->lower_index = stream->buffer_size;
|
||||||
|
else
|
||||||
|
view->local_min_value = stream->buffer_size;
|
||||||
|
|
||||||
|
/* 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_stream_add_view_to_list (view, task_list);
|
||||||
|
|
||||||
|
/* 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_stream_add_view_to_list (view, stream_list);
|
||||||
|
gomp_mutex_unlock (&vh->connect_view_mutex);
|
||||||
|
__sync_fetch_and_add (&vh->nr_registered_views, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether all the expected views on STREAM have already
|
||||||
|
connected. */
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
gomp_stream_check_connected (gomp_stream_p stream)
|
||||||
|
{
|
||||||
|
if (!stream->expected_ready_p)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (stream->connected_p)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ((stream->read_views.view_list.nr_views
|
||||||
|
== stream->read_views.nr_expected_views)
|
||||||
|
&& (stream->write_views.view_list.nr_views
|
||||||
|
== stream->write_views.nr_expected_views))
|
||||||
|
{
|
||||||
|
stream->connected_p = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until all the streams to which TASK connects are ready and
|
||||||
|
connected to all producer/consumer tasks. */
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
|
||||||
|
for (i = 0; i < num_read_views; ++i)
|
||||||
|
if (!gomp_stream_check_connected (task->read_view_list.views[i]->stream))
|
||||||
|
done = false;
|
||||||
|
|
||||||
|
for (i = 0; i < num_write_views; ++i)
|
||||||
|
if (!gomp_stream_check_connected (task->write_view_list.views[i]->stream))
|
||||||
|
done = false;
|
||||||
|
}
|
||||||
|
while (!done);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stream communication/synchronization. */
|
||||||
|
|
||||||
|
/* Compute the minimum of the LOWER_INDEX fields of all views in the
|
||||||
|
LIST of views. This is used during the termination phase to give
|
||||||
|
access to the readers up to the highest committed index. This is
|
||||||
|
only useful when producers, not too far apart in indices they
|
||||||
|
committed, forget to commit up to the last index that should appear
|
||||||
|
in the stream. */
|
||||||
|
|
||||||
|
static inline unsigned long long
|
||||||
|
gomp_stream_compute_lower_max (gomp_stream_view_list_p list)
|
||||||
|
{
|
||||||
|
unsigned long long local_max = 0;
|
||||||
|
gomp_stream_view_p *views = list->views;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < list->nr_views; ++i)
|
||||||
|
if (views[i]->lower_index > local_max)
|
||||||
|
local_max = views[i]->lower_index;
|
||||||
|
|
||||||
|
return local_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the minimum of the LOWER_INDEX fields of all views in the
|
||||||
|
LIST of views. For a LIST of read views, this minimum represents
|
||||||
|
the highest index released by all read views on a stream (i.e. the
|
||||||
|
index of elements that all consumers have already discarded) and
|
||||||
|
therefore the highest index a write view will be allowed to acquire
|
||||||
|
for writing. For a LIST of write views, this minimum represents
|
||||||
|
the highest index all producers have committed and thus the highest
|
||||||
|
index available for reading. */
|
||||||
|
|
||||||
|
static inline unsigned long long
|
||||||
|
gomp_stream_compute_lower_min (gomp_stream_view_list_p list)
|
||||||
|
{
|
||||||
|
unsigned long long local_min = GOMP_STREAM_MAX_INDEX;
|
||||||
|
gomp_stream_view_p *views = list->views;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < list->nr_views; ++i)
|
||||||
|
if (views[i]->lower_index < local_min)
|
||||||
|
local_min = views[i]->lower_index;
|
||||||
|
|
||||||
|
return local_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the minimum of the UPPER_INDEX fields of all views in the
|
||||||
|
LIST of views. Similar to the above, but this is only a hint on
|
||||||
|
the resources that another producer (resp. consumer) has already
|
||||||
|
acquired. If a producer (resp. consumer) has successfully acquired
|
||||||
|
an index with GOMP_stream_stall (resp. GOMP_stream_update) for
|
||||||
|
writing (resp. reading), then all other producers (resp. consumers)
|
||||||
|
on the same stream can access up to the same index without further
|
||||||
|
verification. */
|
||||||
|
|
||||||
|
static inline unsigned long long
|
||||||
|
gomp_stream_compute_upper_min (gomp_stream_view_list_p list)
|
||||||
|
{
|
||||||
|
unsigned long long local_min = GOMP_STREAM_MAX_INDEX;
|
||||||
|
gomp_stream_view_p *views = list->views;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < list->nr_views; ++i)
|
||||||
|
if (views[i]->upper_index < local_min)
|
||||||
|
local_min = views[i]->upper_index;
|
||||||
|
|
||||||
|
return local_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until the producers (resp. consumers) on this stream have
|
||||||
|
committed (resp. released) up to the INDEX position in the stream.
|
||||||
|
When that hapens, the consumer (resp. producer) connected to the
|
||||||
|
stream through VIEW is allowed to access the elements up to
|
||||||
|
INDEX. */
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gomp_stream_wait_release (gomp_stream_view_p view,
|
||||||
|
gomp_stream_view_handle_p vh,
|
||||||
|
const unsigned long long index)
|
||||||
|
{
|
||||||
|
/* Test whether someone already got a hold of a bigger index
|
||||||
|
yet. */
|
||||||
|
|
||||||
|
if (view->local_min_value < index)
|
||||||
|
{
|
||||||
|
while (vh->current_min < index && !view->stream->eos_p)
|
||||||
|
{
|
||||||
|
unsigned long long local_min =
|
||||||
|
gomp_stream_compute_lower_min (&vh->view_list);
|
||||||
|
|
||||||
|
if (vh->current_min == local_min)
|
||||||
|
__asm volatile ("pause" : : : "memory");
|
||||||
|
else
|
||||||
|
vh->current_min = local_min;
|
||||||
|
}
|
||||||
|
view->local_min_value = vh->current_min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
gomp_stream_view_p view = (gomp_stream_view_p) v;
|
||||||
|
view->upper_index = index;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
gomp_stream_wait_release (view, &view->stream->write_views, index);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
if (index > view->stream->write_views.current_min)
|
||||||
|
{
|
||||||
|
return view->stream->write_views.current_min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view->stream->read_views.current_max = index;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request write access for the view V to the stream up to INDEX. */
|
||||||
|
|
||||||
|
void
|
||||||
|
GOMP_stream_stall (void *v, const unsigned long long index)
|
||||||
|
{
|
||||||
|
gomp_stream_view_p view = (gomp_stream_view_p) v;
|
||||||
|
view->upper_index = index;
|
||||||
|
|
||||||
|
if (index > view->stream->write_views.current_max)
|
||||||
|
{
|
||||||
|
gomp_stream_wait_release (view, &view->stream->read_views, index);
|
||||||
|
view->stream->write_views.current_max = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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_view_p view = (gomp_stream_view_p) v;
|
||||||
|
view->lower_index = index + view->stream->buffer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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_view_p view = (gomp_stream_view_p) v;
|
||||||
|
view->lower_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finalization and destruction of the streaming data structures. */
|
||||||
|
|
||||||
|
/* Disconnects VIEW from the stream to which it is connected and free
|
||||||
|
the stream if it was the last task to disconnect. */
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
gomp_stream_unregister_view (gomp_stream_view_p view)
|
||||||
|
{
|
||||||
|
gomp_stream_p stream = view->stream;
|
||||||
|
gomp_stream_view_handle_p vh =
|
||||||
|
(view->type == READ_VIEW) ? &stream->read_views : &stream->write_views;
|
||||||
|
int unregistered_views;
|
||||||
|
|
||||||
|
__sync_fetch_and_add (&(vh->nr_unregistered_views), 1);
|
||||||
|
unregistered_views = __sync_add_and_fetch (&(stream->unregistered_views), 1);
|
||||||
|
|
||||||
|
|
||||||
|
/* Make sure that when multiple views access a stream, the finished
|
||||||
|
views do not hinder the others in the min computation. */
|
||||||
|
if (view->type == READ_VIEW)
|
||||||
|
GOMP_stream_release (view, GOMP_STREAM_MAX_INDEX);
|
||||||
|
/* The last producer exiting will set the eos_p flag and allow the
|
||||||
|
consumers to read up to the highest committed index. */
|
||||||
|
else if (vh->nr_unregistered_views == vh->nr_registered_views)
|
||||||
|
{
|
||||||
|
stream->eos_p = true;
|
||||||
|
vh->current_min = gomp_stream_compute_lower_max (&vh->view_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If all known views arre accounted for, this is the last one
|
||||||
|
unregistering. It frees the memory allocated for the stream as
|
||||||
|
well as all the views on this stream. */
|
||||||
|
if (unregistered_views == (stream->read_views.nr_registered_views
|
||||||
|
+ stream->write_views.nr_registered_views))
|
||||||
|
{
|
||||||
|
gomp_stream_view_list_p read_view_list = &stream->read_views.view_list;
|
||||||
|
gomp_stream_view_list_p write_view_list = &stream->write_views.view_list;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < read_view_list->nr_views; ++i)
|
||||||
|
free (read_view_list->views[i]);
|
||||||
|
|
||||||
|
for (i = 0; i < write_view_list->nr_views; ++i)
|
||||||
|
free (write_view_list->views[i]);
|
||||||
|
|
||||||
|
free (stream->buffer);
|
||||||
|
free (read_view_list->views);
|
||||||
|
free (write_view_list->views);
|
||||||
|
free (stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoked before terminating a stream TASK, this disconnects all the
|
||||||
|
views and for all streams for which it is the last one to
|
||||||
|
disconnect from, it frees up all data structures. */
|
||||||
|
|
||||||
|
void
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
|
Contributed by Antoniu Pop <antoniu.pop@gmail.com>.
|
||||||
|
|
||||||
|
This file is part of the GNU OpenMP Library (libgomp).
|
||||||
|
|
||||||
|
Libgomp is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with libgomp; see the file COPYING.LIB. If not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
MA 02110-1301, USA. */
|
||||||
|
|
||||||
|
/* As a special exception, if you link this library with other files, some
|
||||||
|
of which are compiled with GCC, to produce an executable, this library
|
||||||
|
does not by itself cause the resulting executable to be covered by the
|
||||||
|
GNU General Public License. This exception does not however invalidate
|
||||||
|
any other reasons why the executable file might be covered by the GNU
|
||||||
|
General Public License. */
|
||||||
|
|
||||||
|
/* This implements the stream communication layer for libGOMP. */
|
||||||
|
|
||||||
|
#ifndef GOMP_STREAM_H
|
||||||
|
#define GOMP_STREAM_H 1
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
/* Define the type and maximum value for the indices used within the
|
||||||
|
stream. The indices are strictly monotonically increasing
|
||||||
|
integers, so we need a type that does not wrap around too fast. An
|
||||||
|
implementation of the wrap-around is necessary for systems where
|
||||||
|
this poses a problem. */
|
||||||
|
/* typedef unsigned long long int gomp_stream_index_t; */
|
||||||
|
#define GOMP_STREAM_MAX_INDEX ULLONG_MAX
|
||||||
|
|
||||||
|
/*#define LAZY_SYNCH
|
||||||
|
#define GUARDED_WAKE*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef enum {
|
||||||
|
GOMP_STREAM_INITIALIZED = 1,
|
||||||
|
GOMP_STREAM_ALLOCATED = 2,
|
||||||
|
GOMP_STREAM_PRODUCED = 4,
|
||||||
|
GOMP_STREAM_CONSUMED = 8,
|
||||||
|
GOMP_STREAM_ZOMBIE = 16,
|
||||||
|
GOMP_STREAM_STALL = 32
|
||||||
|
} gomp_stream_state;
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
READ_VIEW,
|
||||||
|
WRITE_VIEW
|
||||||
|
} gomp_stream_view_type_t;
|
||||||
|
|
||||||
|
struct gomp_stream;
|
||||||
|
struct gomp_stream_task;
|
||||||
|
|
||||||
|
|
||||||
|
/* GOMP_STREAM_VIEW data structure. Producer and consumer tasks
|
||||||
|
connect to a GOMP_STREAM using views. */
|
||||||
|
|
||||||
|
typedef struct gomp_stream_view
|
||||||
|
{
|
||||||
|
/* The stream accessed through this view. WARNING: this field needs
|
||||||
|
to be first. */
|
||||||
|
struct gomp_stream *stream;
|
||||||
|
|
||||||
|
/* The alignment directives are needed to ensure these
|
||||||
|
high-potential false-sharing fields are on their own cache
|
||||||
|
lines. */
|
||||||
|
/* Lower and upper bounds accessible in the stream through this
|
||||||
|
view. */
|
||||||
|
unsigned long long lower_index __attribute__((aligned (64)));
|
||||||
|
unsigned long long upper_index __attribute__((aligned (64)));
|
||||||
|
|
||||||
|
/* The task using this view. */
|
||||||
|
struct gomp_stream_task *task __attribute__((aligned (64)));
|
||||||
|
|
||||||
|
/* Setting this flag means the process accessing the stream through
|
||||||
|
this view relinquishes his access to the stream (generally when
|
||||||
|
terminating). */
|
||||||
|
bool end_p;
|
||||||
|
|
||||||
|
/* Type of this view (read or write). */
|
||||||
|
gomp_stream_view_type_t type;
|
||||||
|
|
||||||
|
/* In order to avoid excessive accesses to the global minimum index
|
||||||
|
(released or consumed), which strongly impacts cache traffic, use
|
||||||
|
this duplcated field for an additional level of caching and only
|
||||||
|
update when needed. */
|
||||||
|
unsigned long long local_min_value;
|
||||||
|
|
||||||
|
} gomp_stream_view_t, *gomp_stream_view_p;
|
||||||
|
|
||||||
|
/* List of GOMP_STREAM_VIEWs. As this list is only modified in the
|
||||||
|
initialization phase and we never remove items, we'll use an
|
||||||
|
array. */
|
||||||
|
|
||||||
|
typedef struct gomp_stream_view_list
|
||||||
|
{
|
||||||
|
gomp_stream_view_p *views;
|
||||||
|
int nr_views;
|
||||||
|
int size;
|
||||||
|
} gomp_stream_view_list_t, *gomp_stream_view_list_p;
|
||||||
|
|
||||||
|
|
||||||
|
/* GOMP_STREAM_VIEW_HANDLE data structure. This allows the tasks
|
||||||
|
interacting through the GOMP_STREAM to which this handle is
|
||||||
|
attached to keep updated information global to all similar views on
|
||||||
|
this stream. */
|
||||||
|
|
||||||
|
typedef struct gomp_stream_view_handle
|
||||||
|
{
|
||||||
|
/* The alignment directives are needed to ensure these
|
||||||
|
high-potential false-sharing fields are on their own cache
|
||||||
|
lines. */
|
||||||
|
/* Latest computed value of the min released index and max acquired
|
||||||
|
index values across views. */
|
||||||
|
volatile unsigned long long current_min __attribute__((aligned (64)));
|
||||||
|
volatile unsigned long long current_max __attribute__((aligned (64)));
|
||||||
|
|
||||||
|
/* Bookkeeping for view connections. */
|
||||||
|
gomp_stream_view_list_t view_list __attribute__((aligned (64)));
|
||||||
|
int nr_expected_views;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
/* GOMP_STREAM data structure. */
|
||||||
|
|
||||||
|
typedef struct gomp_stream
|
||||||
|
{
|
||||||
|
/* WARNING: the first two fields (BUFFER and BUFFER_MASK) need to
|
||||||
|
remain in their respective positions. */
|
||||||
|
|
||||||
|
/* The pointer to the buffer, as well as the subsequent buffer
|
||||||
|
description, should be on a single mostly read cache line. The
|
||||||
|
EOS_P flag is only set at the very end of the use of this
|
||||||
|
stream. */
|
||||||
|
/* Circular buffer containing the data communicated through this
|
||||||
|
stream. */
|
||||||
|
char *buffer __attribute__((aligned (64)));
|
||||||
|
|
||||||
|
/* Size of the buffer and the bitmask used for modulo computation
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* True once all the tasks that should be expected to connect to
|
||||||
|
this stream been declared. */
|
||||||
|
bool expected_ready_p;
|
||||||
|
|
||||||
|
/* True once all the tasks expected to connect to this stream have
|
||||||
|
done so. */
|
||||||
|
bool connected_p;
|
||||||
|
|
||||||
|
/* End of stream: true when all producers have finished committing
|
||||||
|
all the data and are terminating. */
|
||||||
|
bool eos_p;
|
||||||
|
|
||||||
|
/* Handles for read and write views on this stream. */
|
||||||
|
gomp_stream_view_handle_t read_views;
|
||||||
|
gomp_stream_view_handle_t write_views;
|
||||||
|
|
||||||
|
/* Barrier used both for waiting for all views to connect to the
|
||||||
|
stream and to find the last view disconnecting (and who therefore
|
||||||
|
frees this stream). */
|
||||||
|
/*gomp_barrier_t view_handling_barrier;*/
|
||||||
|
|
||||||
|
/* Counter of the number of total unregistered views, both read and
|
||||||
|
write, used to determine the last task deconnecting its view.
|
||||||
|
The last task will also free the data structures. */
|
||||||
|
int unregistered_views;
|
||||||
|
|
||||||
|
#ifndef HAVE_SYNC_BUILTINS
|
||||||
|
/* We may need a lock for atomicity if no atomic operations are
|
||||||
|
available. */
|
||||||
|
gomp_mutex_t stream_mutex;
|
||||||
|
#endif
|
||||||
|
} gomp_stream_t, *gomp_stream_p;
|
||||||
|
|
||||||
|
|
||||||
|
/* GOMP_STREAM_TASK data structure. Runtime node in the task
|
||||||
|
graph. */
|
||||||
|
|
||||||
|
typedef struct gomp_stream_task
|
||||||
|
{
|
||||||
|
/* Lists of views on streams used by this task. */
|
||||||
|
gomp_stream_view_list_t read_view_list;
|
||||||
|
gomp_stream_view_list_t write_view_list;
|
||||||
|
|
||||||
|
} gomp_stream_task_t, *gomp_stream_task_p;
|
||||||
|
|
||||||
|
#endif /* GOMP_STREAM_H */
|
Loading…
Reference in New Issue