* The tcp_lro_sort() routine is comparable to qsort(), except it has * a worst case complexity limit of O(MIN(N,64)*N), where N is the * number of elements to sort and 64 is the number of sequence bits * available. The algorithm is bit-slicing the 64-bit sequence number, * sorting one bit at a time from the most significant bit until the * least significant one, skipping the constant bits. Th
| 1015 | * typically called a radix sort. |
| 1016 | */ |
| 1017 | static void |
| 1018 | tcp_lro_sort(struct lro_mbuf_sort *parray, uint32_t size) |
| 1019 | { |
| 1020 | struct lro_mbuf_sort temp; |
| 1021 | uint64_t ones; |
| 1022 | uint64_t zeros; |
| 1023 | uint32_t x; |
| 1024 | uint32_t y; |
| 1025 | |
| 1026 | repeat: |
| 1027 | /* for small arrays insertion sort is faster */ |
| 1028 | if (size <= 12) { |
| 1029 | for (x = 1; x < size; x++) { |
| 1030 | temp = parray[x]; |
| 1031 | for (y = x; y > 0 && temp.seq < parray[y - 1].seq; y--) |
| 1032 | parray[y] = parray[y - 1]; |
| 1033 | parray[y] = temp; |
| 1034 | } |
| 1035 | return; |
| 1036 | } |
| 1037 | |
| 1038 | /* compute sequence bits which are constant */ |
| 1039 | ones = 0; |
| 1040 | zeros = 0; |
| 1041 | for (x = 0; x != size; x++) { |
| 1042 | ones |= parray[x].seq; |
| 1043 | zeros |= ~parray[x].seq; |
| 1044 | } |
| 1045 | |
| 1046 | /* compute bits which are not constant into "ones" */ |
| 1047 | ones &= zeros; |
| 1048 | if (ones == 0) |
| 1049 | return; |
| 1050 | |
| 1051 | /* pick the most significant bit which is not constant */ |
| 1052 | ones = tcp_lro_msb_64(ones); |
| 1053 | |
| 1054 | /* |
| 1055 | * Move entries having cleared sequence bits to the beginning |
| 1056 | * of the array: |
| 1057 | */ |
| 1058 | for (x = y = 0; y != size; y++) { |
| 1059 | /* skip set bits */ |
| 1060 | if (parray[y].seq & ones) |
| 1061 | continue; |
| 1062 | /* swap entries */ |
| 1063 | temp = parray[x]; |
| 1064 | parray[x] = parray[y]; |
| 1065 | parray[y] = temp; |
| 1066 | x++; |
| 1067 | } |
| 1068 | |
| 1069 | KASSERT(x != 0 && x != size, ("Memory is corrupted\n")); |
| 1070 | |
| 1071 | /* sort zeros */ |
| 1072 | tcp_lro_sort(parray, x); |
| 1073 | |
| 1074 | /* sort ones */ |
no test coverage detected