| /* k_pipe_buffer.c */ |
| |
| /* |
| * Copyright (c) 1997-2015 Wind River Systems, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| /* Implementation remarks: |
| * - when using a floating end pointer: do not use pipe_desc->iBuffsize for |
| * (pipe_desc->end_ptr - pipe_desc->begin_ptr) |
| */ |
| |
| #include <microkernel/base_api.h> |
| #include <k_pipe_buffer.h> |
| #include <string.h> |
| #include <toolchain.h> |
| #include <sections.h> |
| #include <misc/__assert.h> |
| |
| #define STORE_NBR_MARKERS |
| /* NOTE: the number of pending write and read Xfers is always stored, |
| * as it is required for the pipes to function properly. It is stored in the |
| * pipe descriptor fields num_pending_writes and num_pending_reads. |
| * |
| * In the Writer and Reader MarkersList, the number of markers (==nbr. of |
| * unreleased Xfers) is monitored as well. They actually equal |
| * num_pending_writes and num_pending_reads. |
| * Their existence depends on STORE_NBR_MARKERS. A reason to have them |
| * additionally is that some extra consistency checking is performed in the |
| * markers manipulation functionality itself. |
| * Drawback: double storage of nbr. of pending write Xfers (but for test |
| * purposes this is acceptable I think) |
| */ |
| |
| #define CHECK_BUFFER_POINTER(data_ptr) \ |
| __ASSERT_NO_MSG(desc->begin_ptr <= data_ptr && data_ptr < desc->end_ptr) |
| |
| static void pipe_intrusion_check(struct _k_pipe_desc *desc, |
| unsigned char *begin_ptr, |
| int size); |
| |
| /** |
| * Markers |
| */ |
| |
| static int MarkerFindFree(struct _k_pipe_marker markers[]) |
| { |
| struct _k_pipe_marker *pM = markers; |
| int i; |
| |
| for (i = 0; i < MAXNBR_PIPE_MARKERS; i++, pM++) { |
| if (pM->pointer == NULL) { |
| break; |
| } |
| } |
| if (i == MAXNBR_PIPE_MARKERS) { |
| i = -1; |
| } |
| |
| return i; |
| } |
| |
| static void MarkerLinkToListAfter(struct _k_pipe_marker markers[], |
| int iMarker, |
| int iNewMarker) |
| { |
| int iNextMarker; /* index of next marker in original list */ |
| |
| /* let the original list be aware of the new marker */ |
| if (iMarker != -1) { |
| iNextMarker = markers[iMarker].next; |
| markers[iMarker].next = iNewMarker; |
| if (iNextMarker != -1) { |
| markers[iNextMarker].prev = iNewMarker; |
| } else { |
| /* there was no next marker */ |
| } |
| } else { |
| iNextMarker = -1; /* there wasn't even a marker */ |
| } |
| |
| /* link the new marker with the marker and next marker */ |
| markers[iNewMarker].prev = iMarker; |
| markers[iNewMarker].next = iNextMarker; |
| } |
| |
| static int MarkerAddLast(struct _k_pipe_marker_list *pMarkerList, |
| unsigned char *pointer, |
| int size, |
| bool buffer_xfer_busy) |
| { |
| int i = MarkerFindFree(pMarkerList->markers); |
| |
| if (i == -1) { |
| return i; |
| } |
| |
| pMarkerList->markers[i].pointer = pointer; |
| pMarkerList->markers[i].size = size; |
| pMarkerList->markers[i].buffer_xfer_busy = buffer_xfer_busy; |
| |
| if (pMarkerList->first_marker == -1) { |
| __ASSERT_NO_MSG(pMarkerList->last_marker == -1); |
| pMarkerList->first_marker = i; /* we still need to set prev & next */ |
| } else { |
| __ASSERT_NO_MSG(pMarkerList->last_marker != -1); |
| __ASSERT_NO_MSG( |
| pMarkerList->markers[pMarkerList->last_marker].next == -1); |
| } |
| |
| MarkerLinkToListAfter(pMarkerList->markers, pMarkerList->last_marker, i); |
| |
| __ASSERT_NO_MSG(pMarkerList->markers[i].next == -1); |
| pMarkerList->last_marker = i; |
| |
| #ifdef STORE_NBR_MARKERS |
| pMarkerList->num_markers++; |
| __ASSERT_NO_MSG(pMarkerList->num_markers > 0); |
| #endif |
| |
| return i; |
| } |
| |
| static void MarkerUnlinkFromList(struct _k_pipe_marker markers[], |
| int iMarker, |
| int *piPredecessor, |
| int *piSuccessor) |
| { |
| int iNextMarker = markers[iMarker].next; |
| int iPrevMarker = markers[iMarker].prev; |
| |
| /* remove the marker from the list */ |
| markers[iMarker].next = -1; |
| markers[iMarker].prev = -1; |
| |
| /* repair the chain */ |
| if (iPrevMarker != -1) { |
| markers[iPrevMarker].next = iNextMarker; |
| } |
| if (iNextMarker != -1) { |
| markers[iNextMarker].prev = iPrevMarker; |
| } |
| *piPredecessor = iPrevMarker; |
| *piSuccessor = iNextMarker; |
| } |
| |
| static void MarkerDelete(struct _k_pipe_marker_list *pMarkerList, int index) |
| { |
| int i; |
| int iPredecessor; |
| int iSuccessor; |
| |
| i = index; |
| |
| __ASSERT_NO_MSG(i != -1); |
| |
| pMarkerList->markers[i].pointer = NULL; |
| MarkerUnlinkFromList(pMarkerList->markers, i, |
| &iPredecessor, &iSuccessor); |
| |
| /* update first/last info */ |
| if (i == pMarkerList->last_marker) { |
| pMarkerList->last_marker = iPredecessor; |
| } |
| if (i == pMarkerList->first_marker) { |
| pMarkerList->first_marker = iSuccessor; |
| } |
| |
| #ifdef STORE_NBR_MARKERS |
| pMarkerList->num_markers--; |
| __ASSERT_NO_MSG(pMarkerList->num_markers >= 0); |
| |
| if (pMarkerList->num_markers == 0) { |
| __ASSERT_NO_MSG(pMarkerList->first_marker == -1); |
| __ASSERT_NO_MSG(pMarkerList->last_marker == -1); |
| } |
| #endif |
| } |
| |
| static void MarkersClear(struct _k_pipe_marker_list *pMarkerList) |
| { |
| struct _k_pipe_marker *pM = pMarkerList->markers; |
| int i; |
| |
| for (i = 0; i < MAXNBR_PIPE_MARKERS; i++, pM++) { |
| memset(pM, 0, sizeof(struct _k_pipe_marker)); |
| pM->next = -1; |
| pM->prev = -1; |
| } |
| #ifdef STORE_NBR_MARKERS |
| pMarkerList->num_markers = 0; |
| #endif |
| pMarkerList->first_marker = -1; |
| pMarkerList->last_marker = -1; |
| pMarkerList->post_wrap_around_marker = -1; |
| } |
| |
| /**/ |
| |
| /* note on setting/clearing markers/guards: |
| * |
| * If there is at least one marker, there is a guard and equals one of the |
| * markers; if there are no markers (*), there is no guard. |
| * Consequently, if a marker is add when there were none, the guard will equal |
| * it. If additional markers are add, the guard will not change. |
| * However, if a marker is deleted: |
| * if it equals the guard a new guard must be selected (**) |
| * if not, guard doesn't change |
| * |
| * (*) we need to housekeep how much markers there are or we can inspect the |
| * guard |
| * (**) for this, the complete markers table needs to be investigated |
| */ |
| |
| /* |
| * This function will see if one or more 'areas' in the buffer can be made |
| * available (either for writing xor reading). |
| * Note: such a series of areas starts from the beginning. |
| */ |
| static int ScanMarkers(struct _k_pipe_marker_list *pMarkerList, |
| int *piSizeBWA, int *piSizeAWA, int *piNbrPendingXfers) |
| { |
| struct _k_pipe_marker *pM; |
| bool bMarkersAreNowAWA; |
| int index; |
| |
| index = pMarkerList->first_marker; |
| |
| __ASSERT_NO_MSG(index != -1); |
| |
| bMarkersAreNowAWA = false; |
| do { |
| int index_next; |
| |
| __ASSERT_NO_MSG(index == pMarkerList->first_marker); |
| |
| if (index == pMarkerList->post_wrap_around_marker) { |
| /* from now on, everything is AWA */ |
| bMarkersAreNowAWA = true; |
| } |
| |
| pM = &(pMarkerList->markers[index]); |
| |
| if (pM->buffer_xfer_busy == true) { |
| break; |
| } |
| |
| if (!bMarkersAreNowAWA) { |
| *piSizeBWA += pM->size; |
| } else { |
| *piSizeAWA += pM->size; |
| } |
| |
| index_next = pM->next; |
| /* pMarkerList->first_marker will be updated */ |
| MarkerDelete(pMarkerList, index); |
| /* adjust *piNbrPendingXfers */ |
| if (piNbrPendingXfers) { |
| __ASSERT_NO_MSG(*piNbrPendingXfers >= 0); |
| (*piNbrPendingXfers)--; |
| } |
| index = index_next; |
| } while (index != -1); |
| |
| __ASSERT_NO_MSG(index == pMarkerList->first_marker); |
| |
| if (bMarkersAreNowAWA) { |
| pMarkerList->post_wrap_around_marker = |
| pMarkerList->first_marker; |
| } |
| |
| #ifdef STORE_NBR_MARKERS |
| if (pMarkerList->num_markers == 0) { |
| __ASSERT_NO_MSG(pMarkerList->first_marker == -1); |
| __ASSERT_NO_MSG(pMarkerList->last_marker == -1); |
| __ASSERT_NO_MSG(pMarkerList->post_wrap_around_marker == -1); |
| } |
| #endif |
| |
| return pMarkerList->first_marker; |
| } |
| |
| /** |
| * General |
| */ |
| |
| void BuffInit(unsigned char *pBuffer, |
| int *piBuffSize, |
| struct _k_pipe_desc *desc) |
| { |
| desc->begin_ptr = pBuffer; |
| |
| desc->buffer_size = *piBuffSize; |
| |
| /* reset all pointers */ |
| |
| desc->end_ptr = desc->begin_ptr + |
| OCTET_TO_SIZEOFUNIT(desc->buffer_size); |
| desc->original_end_ptr = desc->end_ptr; |
| |
| /* assumed it is allowed */ |
| desc->buffer_state = BUFF_EMPTY; |
| desc->end_ptr = desc->original_end_ptr; |
| desc->write_ptr = desc->begin_ptr; |
| desc->write_guard = NULL; |
| desc->wrap_around_write = false; |
| desc->read_ptr = desc->begin_ptr; |
| desc->read_guard = NULL; |
| desc->wrap_around_read = true; /* YES!! */ |
| desc->free_space_count = desc->buffer_size; |
| desc->free_space_post_wrap_around = 0; |
| desc->num_pending_reads = 0; |
| desc->available_data_count = 0; |
| desc->available_data_post_wrap_around = 0; |
| desc->num_pending_writes = 0; |
| MarkersClear(&desc->write_markers); |
| MarkersClear(&desc->read_markers); |
| |
| } |
| |
| int CalcFreeSpace(struct _k_pipe_desc *desc, int *free_space_count_ptr, |
| int *free_space_post_wrap_around_ptr) |
| { |
| unsigned char *pStart = desc->write_ptr; |
| unsigned char *pStop = desc->read_ptr; |
| |
| if (desc->write_guard != NULL) { |
| pStop = desc->write_guard; |
| } else { |
| /* |
| * if buffer_state==BUFF_EMPTY but we have a WriteGuard, |
| * we still need to calculate it as a normal [Start,Stop] |
| * interval |
| */ |
| |
| if (desc->buffer_state == BUFF_EMPTY) { |
| *free_space_count_ptr = |
| SIZEOFUNIT_TO_OCTET(desc->end_ptr - pStart); |
| *free_space_post_wrap_around_ptr = |
| SIZEOFUNIT_TO_OCTET(pStop - desc->begin_ptr); |
| return (*free_space_count_ptr + *free_space_post_wrap_around_ptr); |
| /* this sum equals end_ptr-begin_ptr */ |
| } |
| } |
| |
| /* |
| * on the other hand, if buffer_state is full, we do not need a special |
| * flow; it will be correct as (pStop - pStart) equals 0 |
| */ |
| |
| if (pStop >= pStart) { |
| *free_space_count_ptr = SIZEOFUNIT_TO_OCTET(pStop - pStart); |
| *free_space_post_wrap_around_ptr = 0; |
| } else { |
| *free_space_count_ptr = |
| SIZEOFUNIT_TO_OCTET(desc->end_ptr - pStart); |
| *free_space_post_wrap_around_ptr = |
| SIZEOFUNIT_TO_OCTET(pStop - desc->begin_ptr); |
| } |
| return (*free_space_count_ptr + *free_space_post_wrap_around_ptr); |
| } |
| |
| void BuffGetFreeSpace(struct _k_pipe_desc *desc, |
| int *piFreeSpaceTotal, |
| int *free_space_count_ptr, |
| int *free_space_post_wrap_around_ptr) |
| { |
| int free_space_count; |
| int free_space_post_wrap_around; |
| int iFreeSpaceTotal; |
| |
| iFreeSpaceTotal = |
| CalcFreeSpace(desc, &free_space_count, |
| &free_space_post_wrap_around); |
| __ASSERT_NO_MSG(free_space_count == desc->free_space_count); |
| __ASSERT_NO_MSG(free_space_post_wrap_around == desc->free_space_post_wrap_around); |
| *piFreeSpaceTotal = iFreeSpaceTotal; |
| *free_space_count_ptr = desc->free_space_count; |
| *free_space_post_wrap_around_ptr = desc->free_space_post_wrap_around; |
| } |
| |
| void BuffGetFreeSpaceTotal(struct _k_pipe_desc *desc, int *piFreeSpaceTotal) |
| { |
| int dummy1, dummy2; |
| *piFreeSpaceTotal = CalcFreeSpace(desc, &dummy1, &dummy2); |
| __ASSERT_NO_MSG(dummy1 == desc->free_space_count); |
| __ASSERT_NO_MSG(dummy2 == desc->free_space_post_wrap_around); |
| } |
| |
| int BuffEmpty(struct _k_pipe_desc *desc) |
| { |
| /* 0==iAvailDataTotal is an INcorrect condition b/c of async behavior */ |
| |
| int iTotalFreeSpace; |
| |
| BuffGetFreeSpaceTotal(desc, &iTotalFreeSpace); |
| return (desc->buffer_size == iTotalFreeSpace); |
| } |
| |
| int CalcAvailData(struct _k_pipe_desc *desc, int *available_data_count_ptr, |
| int *available_data_post_wrap_around_ptr) |
| { |
| unsigned char *pStart = desc->read_ptr; |
| unsigned char *pStop = desc->write_ptr; |
| |
| if (NULL != desc->read_guard) { |
| pStop = desc->read_guard; |
| } else { |
| /* |
| * if buffer_state==BUFF_FULL but we have a ReadGuard, |
| * we still need to calculate it as a normal [Start,Stop] interval |
| */ |
| |
| if (BUFF_FULL == desc->buffer_state) { |
| *available_data_count_ptr = |
| SIZEOFUNIT_TO_OCTET(desc->end_ptr - pStart); |
| *available_data_post_wrap_around_ptr = |
| SIZEOFUNIT_TO_OCTET(pStop - desc->begin_ptr); |
| return (*available_data_count_ptr + *available_data_post_wrap_around_ptr); |
| /* this sum equals end_ptr-begin_ptr */ |
| } |
| } |
| |
| /* |
| * on the other hand, if buffer_state is empty, we do not need a |
| * special flow; it will be correct as (pStop - pStart) equals 0 |
| */ |
| |
| if (pStop >= pStart) { |
| *available_data_count_ptr = SIZEOFUNIT_TO_OCTET(pStop - pStart); |
| *available_data_post_wrap_around_ptr = 0; |
| } else { |
| *available_data_count_ptr = |
| SIZEOFUNIT_TO_OCTET(desc->end_ptr - pStart); |
| *available_data_post_wrap_around_ptr = |
| SIZEOFUNIT_TO_OCTET(pStop - desc->begin_ptr); |
| } |
| return (*available_data_count_ptr + *available_data_post_wrap_around_ptr); |
| } |
| |
| void BuffGetAvailData(struct _k_pipe_desc *desc, |
| int *piAvailDataTotal, |
| int *available_data_count_ptr, |
| int *available_data_post_wrap_around_ptr) |
| { |
| int available_data_count; |
| int available_data_post_wrap_around; |
| int iAvailDataTotal; |
| |
| iAvailDataTotal = CalcAvailData(desc, &available_data_count, |
| &available_data_post_wrap_around); |
| __ASSERT_NO_MSG(available_data_count == desc->available_data_count); |
| __ASSERT_NO_MSG(available_data_post_wrap_around == desc->available_data_post_wrap_around); |
| *piAvailDataTotal = iAvailDataTotal; |
| *available_data_count_ptr = desc->available_data_count; |
| *available_data_post_wrap_around_ptr = |
| desc->available_data_post_wrap_around; |
| } |
| |
| void BuffGetAvailDataTotal(struct _k_pipe_desc *desc, int *piAvailDataTotal) |
| { |
| int dummy1, dummy2; |
| |
| *piAvailDataTotal = CalcAvailData(desc, &dummy1, &dummy2); |
| __ASSERT_NO_MSG(dummy1 == desc->available_data_count); |
| __ASSERT_NO_MSG(dummy2 == desc->available_data_post_wrap_around); |
| } |
| |
| int BuffFull(struct _k_pipe_desc *desc) |
| { |
| /* 0==iTotalFreeSpace is an INcorrect condition b/c of async behavior */ |
| |
| int iAvailDataTotal; |
| |
| BuffGetAvailDataTotal(desc, &iAvailDataTotal); |
| return (desc->buffer_size == iAvailDataTotal); |
| } |
| |
| /** |
| * Buffer en-queuing: |
| */ |
| |
| static int AsyncEnQRegstr(struct _k_pipe_desc *desc, int size) |
| { |
| int i; |
| |
| pipe_intrusion_check(desc, desc->write_ptr, size); |
| |
| i = MarkerAddLast(&desc->write_markers, desc->write_ptr, size, true); |
| if (i != -1) { |
| /* adjust num_pending_writes */ |
| __ASSERT_NO_MSG(desc->num_pending_writes >= 0); |
| desc->num_pending_writes++; |
| /* read_guard changes? */ |
| if (desc->read_guard == NULL) { |
| desc->read_guard = desc->write_ptr; |
| } |
| __ASSERT_NO_MSG(desc->write_markers.markers |
| [desc->write_markers.first_marker].pointer == |
| desc->read_guard); |
| /* post_wrap_around_marker changes? */ |
| if (desc->write_markers.post_wrap_around_marker == -1 && |
| desc->wrap_around_write) { |
| desc->write_markers.post_wrap_around_marker = i; |
| } |
| } |
| return i; |
| } |
| |
| static void AsyncEnQFinished(struct _k_pipe_desc *desc, int iTransferID) |
| { |
| desc->write_markers.markers[iTransferID].buffer_xfer_busy = false; |
| |
| if (desc->write_markers.first_marker == iTransferID) { |
| int iNewFirstMarker = ScanMarkers(&desc->write_markers, |
| &desc->available_data_count, |
| &desc->available_data_post_wrap_around, |
| &desc->num_pending_writes); |
| if (iNewFirstMarker != -1) { |
| desc->read_guard = |
| desc->write_markers.markers[iNewFirstMarker].pointer; |
| } else { |
| desc->read_guard = NULL; |
| } |
| } |
| } |
| |
| int BuffEnQ(struct _k_pipe_desc *desc, int size, unsigned char **ppWrite) |
| { |
| int iTransferID; |
| |
| if (BuffEnQA(desc, size, ppWrite, &iTransferID) == 0) { |
| return 0; |
| } |
| |
| /* check ret value */ |
| |
| BuffEnQA_End(desc, iTransferID, size /* optional */); |
| return size; |
| } |
| |
| int BuffEnQA(struct _k_pipe_desc *desc, int size, unsigned char **ppWrite, |
| int *piTransferID) |
| { |
| if (size > desc->free_space_count) { |
| return 0; |
| } |
| *piTransferID = AsyncEnQRegstr(desc, size); |
| if (*piTransferID == -1) { |
| return 0; |
| } |
| |
| *ppWrite = desc->write_ptr; |
| |
| /* adjust write pointer and free space*/ |
| |
| desc->write_ptr += OCTET_TO_SIZEOFUNIT(size); |
| if (desc->end_ptr == desc->write_ptr) { |
| desc->write_ptr = desc->begin_ptr; |
| desc->free_space_count = desc->free_space_post_wrap_around; |
| desc->free_space_post_wrap_around = 0; |
| desc->wrap_around_write = true; |
| desc->wrap_around_read = false; |
| desc->read_markers.post_wrap_around_marker = -1; |
| } else { |
| desc->free_space_count -= size; |
| } |
| |
| if (desc->write_ptr == desc->read_ptr) { |
| desc->buffer_state = BUFF_FULL; |
| } else { |
| desc->buffer_state = BUFF_OTHER; |
| } |
| |
| CHECK_BUFFER_POINTER(desc->write_ptr); |
| |
| return size; |
| } |
| |
| void BuffEnQA_End(struct _k_pipe_desc *desc, int iTransferID, |
| int size /* optional */) |
| { |
| ARG_UNUSED(size); |
| |
| /* An asynchronous data transfer to the buffer has finished */ |
| |
| AsyncEnQFinished(desc, iTransferID); |
| } |
| |
| /** |
| * Buffer de-queuing: |
| */ |
| |
| static int AsyncDeQRegstr(struct _k_pipe_desc *desc, int size) |
| { |
| int i; |
| |
| pipe_intrusion_check(desc, desc->read_ptr, size); |
| |
| i = MarkerAddLast(&desc->read_markers, desc->read_ptr, size, true); |
| if (i != -1) { |
| /* adjust num_pending_reads */ |
| __ASSERT_NO_MSG(desc->num_pending_reads >= 0); |
| desc->num_pending_reads++; |
| /* write_guard changes? */ |
| if (desc->write_guard == NULL) { |
| desc->write_guard = desc->read_ptr; |
| } |
| __ASSERT_NO_MSG(desc->read_markers.markers |
| [desc->read_markers.first_marker].pointer == |
| desc->write_guard); |
| /* post_wrap_around_marker changes? */ |
| if (desc->read_markers.post_wrap_around_marker == -1 && |
| desc->wrap_around_read) { |
| desc->read_markers.post_wrap_around_marker = i; |
| } |
| } |
| return i; |
| } |
| |
| static void AsyncDeQFinished(struct _k_pipe_desc *desc, int iTransferID) |
| { |
| desc->read_markers.markers[iTransferID].buffer_xfer_busy = false; |
| |
| if (desc->read_markers.first_marker == iTransferID) { |
| int iNewFirstMarker = ScanMarkers(&desc->read_markers, |
| &desc->free_space_count, |
| &desc->free_space_post_wrap_around, |
| &desc->num_pending_reads); |
| if (iNewFirstMarker != -1) { |
| desc->write_guard = |
| desc->read_markers.markers[iNewFirstMarker].pointer; |
| } else { |
| desc->write_guard = NULL; |
| } |
| } |
| } |
| |
| int BuffDeQ(struct _k_pipe_desc *desc, int size, unsigned char **ppRead) |
| { |
| int iTransferID; |
| |
| if (BuffDeQA(desc, size, ppRead, &iTransferID) == 0) { |
| return 0; |
| } |
| BuffDeQA_End(desc, iTransferID, size /* optional */); |
| return size; |
| } |
| |
| int BuffDeQA(struct _k_pipe_desc *desc, int size, unsigned char **ppRead, |
| int *piTransferID) |
| { |
| /* asynchronous data transfer; read guard pointers must be set */ |
| |
| if (size > desc->available_data_count) { |
| /* free space is from read to guard pointer/end pointer */ |
| return 0; |
| } |
| *piTransferID = AsyncDeQRegstr(desc, size); |
| if (*piTransferID == -1) { |
| return 0; |
| } |
| |
| *ppRead = desc->read_ptr; |
| |
| /* adjust read pointer and avail data */ |
| |
| desc->read_ptr += OCTET_TO_SIZEOFUNIT(size); |
| if (desc->end_ptr == desc->read_ptr) { |
| desc->read_ptr = desc->begin_ptr; |
| desc->available_data_count = |
| desc->available_data_post_wrap_around; |
| desc->available_data_post_wrap_around = 0; |
| desc->wrap_around_write = false; |
| desc->wrap_around_read = true; |
| desc->write_markers.post_wrap_around_marker = -1; |
| } else { |
| desc->available_data_count -= size; |
| } |
| |
| if (desc->write_ptr == desc->read_ptr) { |
| desc->buffer_state = BUFF_EMPTY; |
| } else { |
| desc->buffer_state = BUFF_OTHER; |
| } |
| |
| CHECK_BUFFER_POINTER(desc->read_ptr); |
| |
| return size; |
| } |
| |
| void BuffDeQA_End(struct _k_pipe_desc *desc, int iTransferID, |
| int size /* optional */) |
| { |
| ARG_UNUSED(size); |
| |
| /* An asynchronous data transfer from the buffer has finished */ |
| |
| AsyncDeQFinished(desc, iTransferID); |
| } |
| |
| /** |
| * Buffer instrusion |
| */ |
| |
| static bool AreasCheck4Intrusion(unsigned char *pBegin1, int iSize1, |
| unsigned char *pBegin2, int iSize2) |
| { |
| unsigned char *pEnd1; |
| unsigned char *pEnd2; |
| |
| pEnd1 = pBegin1 + OCTET_TO_SIZEOFUNIT(iSize1); |
| pEnd2 = pBegin2 + OCTET_TO_SIZEOFUNIT(iSize2); |
| |
| /* |
| * 2 tests are required to determine the status of the 2 areas, |
| * in terms of their position wrt each other |
| */ |
| |
| if (pBegin2 >= pBegin1) { |
| /* check intrusion of pBegin2 in [pBegin1, pEnd1( */ |
| if (pBegin2 < pEnd1) { |
| /* intrusion!! */ |
| return true; |
| } |
| |
| /* |
| * pBegin2 lies outside and to the right of the first |
| * area, intrusion is impossible |
| */ |
| return false; |
| } |
| |
| /* pBegin2 lies to the left of (pBegin1, pEnd1) */ |
| /* check end pointer: is pEnd2 in (pBegin1, pEnd1( ?? */ |
| if (pEnd2 > pBegin1) { |
| /* intrusion!! */ |
| return true; |
| } |
| |
| /* |
| * pEnd2 lies outside and to the left of the first area, |
| * intrusion is impossible |
| */ |
| return false; |
| } |
| |
| static void pipe_intrusion_check(struct _k_pipe_desc *desc, |
| unsigned char *begin_ptr, |
| int size) |
| { |
| /* |
| * check possible collision with all existing data areas, |
| * both for read and write areas |
| */ |
| |
| int index; |
| struct _k_pipe_marker_list *pMarkerList; |
| |
| /* write markers */ |
| |
| #ifdef STORE_NBR_MARKERS |
| /* first a small consistency check */ |
| |
| if (desc->write_markers.num_markers == 0) { |
| __ASSERT_NO_MSG(desc->write_markers.first_marker == -1); |
| __ASSERT_NO_MSG(desc->write_markers.last_marker == -1); |
| __ASSERT_NO_MSG(desc->write_markers.post_wrap_around_marker == -1); |
| } |
| #endif |
| |
| pMarkerList = &desc->write_markers; |
| index = pMarkerList->first_marker; |
| |
| while (index != -1) { |
| struct _k_pipe_marker *pM; |
| |
| pM = &(pMarkerList->markers[index]); |
| |
| if (AreasCheck4Intrusion(begin_ptr, size, |
| pM->pointer, pM->size) != 0) { |
| __ASSERT_NO_MSG(1 == 0); |
| } |
| index = pM->next; |
| } |
| |
| /* read markers */ |
| |
| #ifdef STORE_NBR_MARKERS |
| /* first a small consistency check */ |
| |
| if (desc->read_markers.num_markers == 0) { |
| __ASSERT_NO_MSG(desc->read_markers.first_marker == -1); |
| __ASSERT_NO_MSG(desc->read_markers.last_marker == -1); |
| __ASSERT_NO_MSG(desc->read_markers.post_wrap_around_marker == -1); |
| } |
| #endif |
| |
| pMarkerList = &desc->read_markers; |
| index = pMarkerList->first_marker; |
| |
| while (index != -1) { |
| struct _k_pipe_marker *pM; |
| |
| pM = &(pMarkerList->markers[index]); |
| |
| if (AreasCheck4Intrusion(begin_ptr, size, |
| pM->pointer, pM->size) != 0) { |
| __ASSERT_NO_MSG(1 == 0); |
| } |
| index = pM->next; |
| } |
| } |