1 /*
2  * Copyright 2010-2016 Intel Corporation.
3  *
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation, version 2.1.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16  * 02110-1301 USA.
17  *
18  * Disclaimer: The codes contained in these modules may be specific
19  * to the Intel Software Development Platform codenamed Knights Ferry,
20  * and the Intel product codenamed Knights Corner, and are not backward
21  * compatible with other Intel products. Additionally, Intel will NOT
22  * support the codes or instruction set in future products.
23  *
24  * Intel offers no warranty of any kind regarding the code. This code is
25  * licensed on an "AS IS" basis and Intel is not obligated to provide
26  * any support, assistance, installation, training, or other services
27  * of any kind. Intel is also not obligated to provide any updates,
28  * enhancements or extensions. Intel specifically disclaims any warranty
29  * of merchantability, non-infringement, fitness for any particular
30  * purpose, and any other warranty.
31  *
32  * Further, Intel disclaims all liability of any kind, including but
33  * not limited to liability for infringement of any proprietary rights,
34  * relating to the use of the code, even if Intel is notified of the
35  * possibility of such liability. Except as expressly stated in an Intel
36  * license agreement provided with this code and agreed upon with Intel,
37  * no license, express or implied, by estoppel or otherwise, to any
38  * intellectual property rights is granted herein.
39  */
40 
41 #ifndef _COIPIPELINE_SOURCE_H
42 #define _COIPIPELINE_SOURCE_H
43 
44 /** @ingroup COIPipeline
45  *  @addtogroup COIPipelineSource
46 @{
47 * @file source/COIPipeline_source.h
48 */
49 #ifndef DOXYGEN_SHOULD_SKIP_THIS
50 
51 #include "../common/COITypes_common.h"
52 #include "../common/COIResult_common.h"
53 
54 #ifdef __cplusplus
55 extern "C" {
56 #endif
57 #endif // DOXYGEN_SHOULD_SKIP_THIS
58 
59 
60 
61 //////////////////////////////////////////////////////////////////////////////
62 /// These flags specify how a buffer will be used within a run function. They
63 /// allow the runtime to make optimizations in how it moves the data around.
64 /// These flags can affect the correctness of an application, so they must be
65 /// set properly. For example, if a buffer is used in a run function with the
66 /// COI_SINK_READ flag and then mapped on the source, the runtime may use a
67 /// previously cached version of the buffer instead of retrieving data from
68 /// the sink.
69 typedef enum COI_ACCESS_FLAGS
70 {
71     /// Specifies that the run function will only read the associated buffer.
72     COI_SINK_READ = 1,
73 
74     /// Specifies that the run function will write to the associated buffer.
75     COI_SINK_WRITE,
76 
77     /// Specifies that the run function will overwrite the entire associated
78     /// buffer and therefore the buffer will not be synchronized with the
79     /// source before execution.
80     COI_SINK_WRITE_ENTIRE,
81 
82     /// Specifies that the run function will only read the associated buffer
83     /// and will maintain the reference count on the buffer after
84     /// run function exit.
85     COI_SINK_READ_ADDREF,
86 
87     /// Specifies that the run function will write to the associated buffer
88     /// and will maintain the reference count on the buffer after
89     /// run function exit.
90     COI_SINK_WRITE_ADDREF,
91 
92     /// Specifies that the run function will overwrite the entire associated
93     /// buffer and therefore the buffer will not be synchronized with the
94     /// source before execution and will maintain the reference count on the
95     /// buffer after run function exit.
96     COI_SINK_WRITE_ENTIRE_ADDREF
97 } COI_ACCESS_FLAGS;
98 
99 #define COI_PIPELINE_MAX_PIPELINES 512
100 #define COI_PIPELINE_MAX_IN_BUFFERS 16384
101 #define COI_PIPELINE_MAX_IN_MISC_DATA_LEN 32768
102 
103 
104 ///////////////////////////////////////////////////////////////////////////////
105 ///
106 /// Create a pipeline associated with a remote process. This pipeline can
107 /// then be used to execute remote functions and to share data using
108 /// COIBuffers.
109 ///
110 /// @param  in_Process
111 ///         [in] A handle to an already existing process that the pipeline
112 ///         will be associated with.
113 ///
114 /// @param  in_Mask
115 ///         [in] An optional mask of the set of hardware threads on which the
116 ///         sink pipeline command processing thread could run.
117 ///
118 /// @param  in_StackSize
119 ///         [in] An optional value that will be used when the pipeline
120 ///         processing thread is created on the sink. If the user passes in
121 ///         0 the OS default stack size will be used. Otherwise the value
122 ///         must be PTHREAD_STACK_MIN (16384) bytes or larger and must be
123 ///         a multiple of a page (4096 bytes).
124 ///
125 /// @param  out_pPipeline
126 ///         [out] Handle returned to uniquely identify the pipeline that was
127 ///         created for use in later API calls.
128 ///
129 ///
130 /// @return COI_SUCCESS if the pipeline was successfully created.
131 ///
132 /// @return COI_INVALID_HANDLE if the in_Process handle passed in was invalid.
133 ///
134 /// @return COI_INVALID_POINTER if the out_pPipeline pointer was NULL.
135 ///
136 /// @return COI_RESOURCE_EXHAUSTED if no more COIPipelines can be created. The
137 ///         maximum number of pipelines allowed is COI_PIPELINE_MAX_PIPELINES.
138 ///         It is recommended in most cases to not exceed the number of CPU's
139 ///         that are reported on the offload device, performance will suffer.
140 ///
141 ///
142 /// @return COI_OUT_OF_RANGE if the in_StackSize > 0 &&
143 ///         in_StackSize < PTHREAD_STACK_MIN or if in_StackSize is not a
144 ///         multiple of a page (4096 bytes).
145 ///
146 /// @return COI_OUT_OF_RANGE if the in_Mask is set to all zeroes. If no mask
147 ///         is desired then the in_Mask should be passed as NULL, otherwise
148 ///         at least one thread must be set.
149 ///
150 /// @return COI_TIME_OUT_REACHED if establishing the communication channel with
151 ///         the remote pipeline timed out.
152 ///
153 /// @return COI_RETRY if the pipeline cannot be created due to the number of
154 ///         source-to-sink connections in use. A subsequent call to
155 ///         COIPipelineCreate may succeed if resources are freed up.
156 ///
157 /// @return COI_PROCESS_DIED if in_Process died.
158 ///
159 COIACCESSAPI
160 COIRESULT
161 COIPipelineCreate(
162     COIPROCESS          in_Process,
163     COI_CPU_MASK        in_Mask,
164     uint32_t            in_StackSize,
165     COIPIPELINE        *out_pPipeline);
166 
167 ///////////////////////////////////////////////////////////////////////////////
168 ///
169 /// Destroys the indicated pipeline, releasing its resources.
170 ///
171 /// @param  in_Pipeline
172 ///         [in] Pipeline to destroy.
173 ///
174 ///
175 /// @return COI_SUCCESS if the pipeline was destroyed
176 ///
177 COIACCESSAPI
178 COIRESULT
179 COIPipelineDestroy(
180     COIPIPELINE         in_Pipeline);
181 
182 
183 //////////////////////////////////////////////////////////////////////////////
184 ///
185 /// Enqueues a function in the remote process binary to be executed. The
186 /// function execution is asynchronous in regards to the Source and all
187 /// run functions enqueued on a pipeline are executed in-order. The run
188 /// function will only execute when all of the required buffers are present
189 /// in the Sink's memory.
190 ///
191 /// Potential Hazards while using Runfunctions:
192 ///
193 /// 1. Proper care has to be taken while setting the input dependencies for
194 ///    RunFunctions. Setting it incorrectly can lead to cyclic dependencies
195 ///    and can cause the respective pipeline to stall.
196 /// 2. RunFunctions can also segfault if enough memory space is not available
197 ///    on the sink for the buffers passed in. Buffers that are AddRef'd
198 ///    need to be accounted for available memory space. In other
199 ///    words, this memory is not available for use until it is freed up.
200 /// 3. Unexpected segmentation faults or erroneous behavior can occur if
201 ///    handles or data passed in to Runfunction gets destroyed before the
202 ///    RunFunction finishes.
203 ///    For example, if a variable passed in as Misc data or the buffer gets
204 ///    destroyed before the runtime receives the completion notification
205 ///    of the Runfunction, it can cause unexpected behavior. So it is always
206 ///    recommended to wait for RunFunction completion event before any related
207 ///    destroy event occurs.
208 ///
209 /// The runtime expects users to handle such scenarios. COIPipelineRunFunction
210 /// returns COI_SUCCESS for above cases because it was queued up successfully.
211 /// Also if you try to destroy a pipeline with a stalled function then the
212 /// destroy call will hang. COIPipelineDestroy waits until all the functions
213 /// enqueued are finished executing.
214 ///
215 /// @param  in_Pipeline
216 ///         [in] Handle to a previously created pipeline that this run
217 ///         function should be enqueued to.
218 ///
219 /// @param  in_Function
220 ///         [in] Previously returned handle from a call to
221 ///         COIPipelineGetFunctionHandle() that represents a function in the
222 ///         application running on the Sink process.
223 ///
224 /// @param  in_NumBuffers
225 ///         [in] The number of buffers that are being passed to the run
226 ///         function. This number must match the number of buffers in the
227 ///         in_pBuffers and in_pBufferAccessFlags arrays. Must be less than
228 ///         COI_PIPELINE_MAX_IN_BUFFERS.
229 ///
230 /// @param  in_pBuffers
231 ///         [in] An array of COIBUFFER handles that the function is expected
232 ///         to use during its execution. Each buffer when it arrives at the
233 ///         Sink process will be at least 4k page aligned, thus, using a very
234 ///         large number of small buffers is memory inefficient and should be
235 ///         avoided.
236 ///
237 /// @param  in_pBufferAccessFlags
238 ///         [in] An array of flag values which correspond to the buffers
239 ///         passed in the in_pBuffers parameter. These flags are used to
240 ///         track dependencies between different run functions being
241 ///         executed from different pipelines.
242 ///
243 /// @param  in_NumDependencies
244 ///         [in] The number of dependencies specified in the in_pDependencies
245 ///         array. This may be 0 if the caller does not want the run function
246 ///         to wait for any dependencies.
247 ///
248 /// @param  in_pDependencies
249 ///         [in] An optional array of COIEVENT objects that this run
250 ///         function will wait for before executing. This allows the user to
251 ///         create dependencies between run functions in different pipelines.
252 ///         The user may pass in NULL if they do not wish to wait for any
253 ///         dependencies to complete.
254 ///
255 /// @param  in_pMiscData
256 ///         [in] Pointer to user defined data, typically used to pass
257 ///         parameters to Sink side functions. Should only be used for small
258 ///         amounts data since the data will be placed directly in the
259 ///         Driver's command buffer. COIBuffers should be used to pass large
260 ///         amounts of data.
261 ///
262 /// @param  in_MiscDataLen
263 ///         [in] Size of the in_pMiscData in bytes. Must be less than
264 ///         COI_PIPELINE_MAX_IN_MISC_DATA_LEN, and should usually be much
265 ///         smaller, see documentation for the parameter in_pMiscData.
266 ///
267 /// @param  out_pAsyncReturnValue
268 ///         [out] Pointer to user-allocated memory where the return value from
269 ///         the run function will be placed. This memory should not be read
270 ///         until out_pCompletion has been signaled.
271 ///
272 /// @param  in_AsyncReturnValueLen
273 ///         [in] Size of the out_pAsyncReturnValue in bytes.
274 ///
275 /// @param  out_pCompletion
276 ///         [out] An optional pointer to a COIEVENT object
277 ///         that will be signaled when this run function has completed
278 ///         execution. The user may pass in NULL if they wish for this function
279 ///         to be synchronous, otherwise if a COIEVENT object is passed in the
280 ///         function is then asynchronous and closes after enqueuing the
281 ///         RunFunction and passes back the COIEVENT that will be signaled
282 ///         once the RunFunction has completed.
283 ///
284 /// @return COI_SUCCESS if the function was successfully placed in a
285 ///         pipeline for future execution. Note that the actual
286 ///         execution of the function will occur in the future.
287 ///
288 /// @return COI_OUT_OF_RANGE if in_NumBuffers is greater than
289 ///         COI_PIPELINE_MAX_IN_BUFFERS or if in_MiscDataLen is greater than
290 ///         COI_PIPELINE_MAX_IN_MISC_DATA_LEN.
291 ///
292 /// @return COI_INVALID_HANDLE if the pipeline handle passed in was invalid.
293 ///
294 /// @return COI_INVALID_HANDLE if the function handle passed in was invalid.
295 ///
296 /// @return COI_INVALID_HANDLE if any of the buffers passed in are invalid.
297 ///
298 /// @return COI_ARGUMENT_MISMATCH if in_NumDependencies is non-zero while
299 ///         in_pDependencies was passed in as NULL.
300 ///
301 /// @return COI_ARGUMENT_MISMATCH if in_pDependencies is non-NULL but
302 ///         in_NumDependencies is zero.
303 ///
304 /// @return COI_ARGUMENT_MISMATCH if in_MiscDataLen is non-zero while
305 ///         in_pMiscData was passed in as NULL.
306 ///
307 /// @return COI_ARGUMENT_MISMATCH if in_pMiscData is non-NULL but
308 ///         in_MiscDataLen is zero.
309 ///
310 /// @return COI_ARGUMENT_MISMATCH if in_NumBuffers is non-zero and in_pBuffers
311 ///         or in_pBufferAccessFlags are NULL.
312 ///
313 /// @return COI_ARGUMENT_MISMATCH if in_pBuffers is non-NULL but
314 ///         in_NumBuffers is zero.
315 ///
316 /// @return COI_ARGUMENT_MISMATCH if in_pBufferAccessFlags is non-NULL but
317 ///         in_NumBuffers is zero.
318 ///
319 /// @return COI_ARGUMENT_MISMATCH if in_ReturnValueLen is non-zero while
320 ///         in_pReturnValue was passed in as NULL.
321 ///
322 /// @return COI_ARGUMENT_MISMATCH if in_pReturnValue is non-NULL but
323 ///         in_ReturnValueLen is zero.
324 ///
325 /// @return COI_RETRY if any input buffers are still mapped when
326 ///         passed to the run function.
327 ///
328 /// @return COI_MISSING_DEPENDENCY if buffer was not created on the process
329 ///         associated with the pipeline that was passed in.
330 ///
331 /// @return COI_OUT_OF_RANGE if any of the access flags in
332 ///         in_pBufferAccessFlags is not a valid COI_ACCESS_FLAGS.
333 ///
334 COIACCESSAPI
335 COIRESULT
336 COIPipelineRunFunction(
337     COIPIPELINE         in_Pipeline,
338     COIFUNCTION         in_Function,
339     uint32_t            in_NumBuffers,
340     const   COIBUFFER          *in_pBuffers,
341     const   COI_ACCESS_FLAGS   *in_pBufferAccessFlags,
342     uint32_t            in_NumDependencies,
343     const   COIEVENT           *in_pDependencies,
344     const   void               *in_pMiscData,
345     uint16_t            in_MiscDataLen,
346     void               *out_pAsyncReturnValue,
347     uint16_t            in_AsyncReturnValueLen,
348     COIEVENT           *out_pCompletion);
349 
350 
351 //////////////////////////////////////////////////////////////////////////////
352 ///
353 /// Retrieve the engine that the pipeline is associated with.
354 ///
355 /// @param  in_Pipeline
356 ///         [in] Pipeline to query.
357 ///
358 /// @param  out_pEngine
359 ///         [out] The handle of the Engine.
360 ///
361 /// @return COI_SUCCESS if the engine was retrieved.
362 ///
363 /// @return COI_INVALID_HANDLE if the pipeline handle passed in was invalid.
364 ///
365 /// @return COI_INVALID_POINTER if the out_pEngine parameter is NULL.
366 ///
367 /// @return COI_PROCESS_DIED if the process associated with this engine died.
368 ///
369 COIACCESSAPI
370 COIRESULT
371 COIPipelineGetEngine(
372     COIPIPELINE         in_Pipeline,
373     COIENGINE          *out_pEngine);
374 
375 //////////////////////////////////////////////////////////////////////////////
376 ///
377 /// Add a particular core:thread pair to a COI_CPU_MASK.
378 ///
379 /// @param  in_Process
380 ///         [in] A handle to an already existing process that the pipeline
381 ///         will be associated with.
382 ///
383 /// @param  in_CoreID
384 ///         [in] Core to affinitize to; must be less than the number of cores
385 ///         on the device.
386 ///
387 /// @param  in_ThreadID
388 ///         [in] Thread on the core to affinitize to (0 - 3).
389 ///
390 /// @param  out_pMask
391 ///         [out] Pointer to the mask to set.
392 ///
393 /// @warning Unless it is explicitly done, the contents of the mask may not
394 ///          be zero when creating or declaring a COI_CPU_MASK variable.
395 ///
396 /// @return COI_SUCCESS if the mask was set.
397 ///
398 /// @return COI_OUT_OF_RANGE if the in_CoreID or in_ThreadID is out of range.
399 ///
400 /// @return COI_INVALID_POINTER if out_pMask is invalid.
401 ///
402 /// @return COI_INVALID_HANDLE if in_Process is invalid.
403 ///
404 COIACCESSAPI
405 COIRESULT
406 COIPipelineSetCPUMask(
407     COIPROCESS          in_Process,
408     uint32_t            in_CoreID,
409     uint8_t             in_ThreadID,
410     COI_CPU_MASK       *out_pMask);
411 
412 //////////////////////////////////////////////////////////////////////////////
413 ///
414 /// Clears a given mask. Note that the memory contents of COI_CPU_MASK are not
415 /// guaranteed to be zero when declaring a COI_CPU_MASK variable. Thus, prior
416 /// to setting a specific affinity to in_Mask it is important to call this
417 /// function first.
418 ///
419 /// @param  in_Mask
420 ///         [in] Pointer to the mask to clear.
421 ///
422 /// @return COI_SUCCESS if the mask was cleared.
423 ///
424 /// @return COI_INVALID_POINTER if in_Mask is invalid.
425 ///
426 COIACCESSAPI
427 COIRESULT
428 COIPipelineClearCPUMask(
429     COI_CPU_MASK       *in_Mask);
430 
431 #ifdef __cplusplus
432 } /* extern "C" */
433 #endif
434 
435 #endif /* _COIPIPELINE_SOURCE_H */
436 
437 /*! @} */
438