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_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_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)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR,
|
||||
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)
|
||||
|
||||
|
@ -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)
|
||||
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_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_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)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_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,
|
||||
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))
|
||||
result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
|
||||
break;
|
||||
case 'i':
|
||||
if (!strcmp ("input", p))
|
||||
result = PRAGMA_OMP_CLAUSE_INPUT;
|
||||
break;
|
||||
case 'l':
|
||||
if (!strcmp ("lastprivate", p))
|
||||
result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
|
||||
|
@ -7169,6 +7173,8 @@ c_parser_omp_clause_name (c_parser *parser)
|
|||
case 'o':
|
||||
if (!strcmp ("ordered", p))
|
||||
result = PRAGMA_OMP_CLAUSE_ORDERED;
|
||||
else if (!strcmp ("output", p))
|
||||
result = PRAGMA_OMP_CLAUSE_OUTPUT;
|
||||
break;
|
||||
case 'p':
|
||||
if (!strcmp ("private", p))
|
||||
|
@ -7267,6 +7273,157 @@ c_parser_omp_variable_list (c_parser *parser,
|
|||
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
|
||||
common case for omp clauses. */
|
||||
|
||||
|
@ -7426,6 +7583,15 @@ c_parser_omp_clause_if (c_parser *parser, tree 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:
|
||||
lastprivate ( variable-list ) */
|
||||
|
||||
|
@ -7512,6 +7678,15 @@ c_parser_omp_clause_ordered (c_parser *parser, tree list)
|
|||
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:
|
||||
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);
|
||||
c_name = "if";
|
||||
break;
|
||||
case PRAGMA_OMP_CLAUSE_INPUT:
|
||||
clauses = c_parser_omp_clause_input (parser, clauses);
|
||||
c_name = "input";
|
||||
break;
|
||||
case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
|
||||
clauses = c_parser_omp_clause_lastprivate (parser, clauses);
|
||||
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);
|
||||
c_name = "ordered";
|
||||
break;
|
||||
case PRAGMA_OMP_CLAUSE_OUTPUT:
|
||||
clauses = c_parser_omp_clause_output (parser, clauses);
|
||||
c_name = "output";
|
||||
break;
|
||||
case PRAGMA_OMP_CLAUSE_PRIVATE:
|
||||
clauses = c_parser_omp_clause_private (parser, clauses);
|
||||
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_PRIVATE) \
|
||||
| (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
|
||||
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_FIRSTPRIVATE,
|
||||
PRAGMA_OMP_CLAUSE_IF,
|
||||
PRAGMA_OMP_CLAUSE_INPUT,
|
||||
PRAGMA_OMP_CLAUSE_LASTPRIVATE,
|
||||
PRAGMA_OMP_CLAUSE_NOWAIT,
|
||||
PRAGMA_OMP_CLAUSE_NUM_THREADS,
|
||||
PRAGMA_OMP_CLAUSE_ORDERED,
|
||||
PRAGMA_OMP_CLAUSE_OUTPUT,
|
||||
PRAGMA_OMP_CLAUSE_PRIVATE,
|
||||
PRAGMA_OMP_CLAUSE_REDUCTION,
|
||||
PRAGMA_OMP_CLAUSE_SCHEDULE,
|
||||
|
|
|
@ -10272,6 +10272,20 @@ c_finish_omp_clauses (tree clauses)
|
|||
bitmap_set_bit (&lastprivate_head, DECL_UID (t));
|
||||
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_NUM_THREADS:
|
||||
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;
|
||||
check_non_private = "reduction";
|
||||
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:
|
||||
decl = OMP_CLAUSE_DECL (c);
|
||||
|
@ -5959,6 +5968,8 @@ gimplify_adjust_omp_clauses (tree *list_p)
|
|||
= (n->value & GOVD_FIRSTPRIVATE) != 0;
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_INPUT:
|
||||
case OMP_CLAUSE_OUTPUT:
|
||||
case OMP_CLAUSE_REDUCTION:
|
||||
case OMP_CLAUSE_COPYIN:
|
||||
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)
|
||||
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_END, "GOMP_single_copy_end",
|
||||
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. */
|
||||
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;
|
||||
|
|
|
@ -307,6 +307,12 @@ dump_omp_clause (pretty_printer *buffer, tree clause, int spc, int flags)
|
|||
case OMP_CLAUSE_LASTPRIVATE:
|
||||
name = "lastprivate";
|
||||
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:
|
||||
name = "copyin";
|
||||
goto print_remap;
|
||||
|
|
|
@ -233,6 +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 */
|
||||
4, /* OMP_CLAUSE_REDUCTION */
|
||||
1, /* OMP_CLAUSE_COPYIN */
|
||||
1, /* OMP_CLAUSE_COPYPRIVATE */
|
||||
|
@ -243,7 +245,7 @@ unsigned const char omp_clause_num_ops[] =
|
|||
0, /* OMP_CLAUSE_ORDERED */
|
||||
0, /* OMP_CLAUSE_DEFAULT */
|
||||
3, /* OMP_CLAUSE_COLLAPSE */
|
||||
0 /* OMP_CLAUSE_UNTIED */
|
||||
0, /* OMP_CLAUSE_UNTIED */
|
||||
};
|
||||
|
||||
const char * const omp_clause_code_name[] =
|
||||
|
@ -253,6 +255,8 @@ const char * const omp_clause_code_name[] =
|
|||
"shared",
|
||||
"firstprivate",
|
||||
"lastprivate",
|
||||
"input",
|
||||
"output",
|
||||
"reduction",
|
||||
"copyin",
|
||||
"copyprivate",
|
||||
|
@ -10215,6 +10219,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
|
|||
case OMP_CLAUSE_PRIVATE:
|
||||
case OMP_CLAUSE_SHARED:
|
||||
case OMP_CLAUSE_FIRSTPRIVATE:
|
||||
case OMP_CLAUSE_INPUT:
|
||||
case OMP_CLAUSE_OUTPUT:
|
||||
case OMP_CLAUSE_COPYIN:
|
||||
case OMP_CLAUSE_COPYPRIVATE:
|
||||
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). */
|
||||
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).
|
||||
OMP_CLAUSE_REDUCTION_CODE: The tree_code of the operator.
|
||||
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_PRIVATE, \
|
||||
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) \
|
||||
((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus != UNKNOWN_LOCATION)
|
||||
#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 \
|
||||
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 \
|
||||
time.c fortran.c affinity.c
|
||||
time.c fortran.c affinity.c stream.c
|
||||
|
||||
nodist_noinst_HEADERS = libgomp_f.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 \
|
||||
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 \
|
||||
fortran.lo affinity.lo
|
||||
fortran.lo affinity.lo stream.lo
|
||||
libgomp_la_OBJECTS = $(am_libgomp_la_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@
|
||||
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 \
|
||||
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 \
|
||||
time.c fortran.c affinity.c
|
||||
time.c fortran.c affinity.c stream.c
|
||||
|
||||
nodist_noinst_HEADERS = libgomp_f.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)/sem.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)/team.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "mutex.h"
|
||||
#include "bar.h"
|
||||
#include "ptrlock.h"
|
||||
#include "stream.h"
|
||||
|
||||
|
||||
/* 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_static_next;
|
||||
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;
|
||||
|
||||
|
|
|
@ -179,4 +179,21 @@ extern bool GOMP_single_start (void);
|
|||
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_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 */
|
||||
|
|
|
@ -102,4 +102,29 @@ int omp_get_active_level (void) __GOMP_NOTHROW;
|
|||
}
|
||||
#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 */
|
||||
|
|
|
@ -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