In some situations, if you are not consuming a buffer port worth of data on
every invocation of a kernel, or if you are not producing a buffer port worth of
data on every invocation, then you can control the buffer synchronization by
declaring the kernel port using async
to declare the
async buffer port in kernel function prototype. The example below illustrates that
the kernel simple
uses:
-
ifm
- Synchronous input buffer port.
-
wts
- Asynchronous input buffer port.
-
ofm
- Asynchronous output buffer port.
The declaration below informs the compiler to omit synchronization of the
buffer named wts
upon entry to the kernel. You must use buffer port
synchronization member function shown inside the kernel code before
accessing the buffer port using read/write iterators/references, as shown below.
void simple(adf::input_buffer<uint8>& ifm, adf::input_async_buffer<uint8>& wts, adf::output_async_buffer<uint8>& ofm)
{
...
wts.acquire(); // acquire lock unconditionally inside the kernel
if (<somecondition>) {
ofm.acquire(); // acquire output buffer conditionally
}
... // do some computation
wts.release(); // release input buffer port inside the kernel
if (<somecondition>) {
ofm.release(); // release output buffer port conditionally
}
...
};
The acquire()
member function of the buffer
object wts
performs the appropriate synchronization
and initialization to ensure that the buffer port object is available for read or
write. This function keeps track of the appropriate buffer pointers and locks to be
acquired internally, even if the buffer port is shared across AI Engine processors
and can be double buffered. This function can be called unconditionally or
conditionally under dynamic control and is potentially a blocking operation. It is
your responsibility to ensure that the corresponding release()
member function is executed sometime later (possibly even in
a subsequent kernel call) to release the lock associated with that buffer object.
Incorrect synchronization can lead to a deadlock in your code.