*
* This function only returns when at least N packets are in our pool.
*
+ * If counting in our pool's main stack didn't give us the number we
+ * are seeking, we check if the return stack is filled and add those
+ * to our main stack. Then we retry.
+ *
* \param n number of packets needed
*/
void PacketPoolWaitForN(int n)
{
PktPool *my_pool = GetThreadPacketPool();
- Packet *p = NULL;
+ Packet *p, *pp;
while (1) {
- int i = 0;
PacketPoolWait();
/* count packets in our stack */
- p = my_pool->head;
+ int i = 0;
+ pp = p = my_pool->head;
while (p != NULL) {
if (++i == n)
return;
+ pp = p;
p = p->next;
}
- /* continue counting in the return stack */
+ /* check return stack, return to our pool and retry counting */
if (my_pool->return_stack.head != NULL) {
SCMutexLock(&my_pool->return_stack.mutex);
- p = my_pool->return_stack.head;
- while (p != NULL) {
- if (++i == n) {
- SCMutexUnlock(&my_pool->return_stack.mutex);
- return;
- }
- p = p->next;
+ /* Move all the packets from the locked return stack to the local stack. */
+ if (pp) {
+ pp->next = my_pool->return_stack.head;
+ } else {
+ my_pool->head = my_pool->return_stack.head;
}
+ my_pool->return_stack.head = NULL;
+ SC_ATOMIC_RESET(my_pool->return_stack.sync_now);
SCMutexUnlock(&my_pool->return_stack.mutex);
/* or signal that we need packets and wait */
return;
}
+/** number of packets to keep reserved when calculating the the pending
+ * return packets count. This assumes we need at max 10 packets in one
+ * PacketPoolWaitForN call. The actual number is 9 now, so this has a
+ * bit of margin. */
+#define RESERVED_PACKETS 10
+
/**
* \brief Set the max_pending_return_packets value
*
void PacketPoolPostRunmodes(void)
{
extern intmax_t max_pending_packets;
-
+ intmax_t pending_packets = max_pending_packets;
+ if (pending_packets < RESERVED_PACKETS) {
+ FatalError(SC_ERR_INVALID_ARGUMENT, "'max-pending-packets' setting "
+ "must be at least %d", RESERVED_PACKETS);
+ }
uint32_t threads = TmThreadCountThreadsByTmmFlags(TM_FLAG_DETECT_TM);
if (threads == 0)
return;
- if (threads > max_pending_packets)
- return;
- uint32_t packets = (max_pending_packets / threads) - 1;
+ uint32_t packets = (pending_packets / threads) - 1;
if (packets < max_pending_return_packets)
max_pending_return_packets = packets;
+ /* make sure to have a margin in the return logic */
+ if (max_pending_return_packets >= RESERVED_PACKETS)
+ max_pending_return_packets -= RESERVED_PACKETS;
+
SCLogDebug("detect threads %u, max packets %u, max_pending_return_packets %u",
- threads, threads, max_pending_return_packets);
+ threads, packets, max_pending_return_packets);
}