suricata
tm-threads.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2024 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23  * \author Eric Leblond <eric@regit.org>
24  *
25  * Thread management functions.
26  */
27 
28 #include "suricata-common.h"
29 #include "suricata.h"
30 #include "stream.h"
31 #include "runmodes.h"
32 #include "thread-callbacks.h"
33 #include "threadvars.h"
34 #include "thread-storage.h"
35 #include "tm-queues.h"
36 #include "tm-queuehandlers.h"
37 #include "tm-threads.h"
38 #include "capture-hooks.h"
39 #include "tmqh-packetpool.h"
40 #include "threads.h"
41 #include "util-affinity.h"
42 #include "util-debug.h"
43 #include "util-privs.h"
44 #include "util-cpu.h"
45 #include "util-profiling.h"
46 #include "util-signal.h"
47 #include "queue.h"
48 #include "util-validate.h"
50 
51 #ifdef PROFILE_LOCKING
52 thread_local uint64_t mutex_lock_contention;
53 thread_local uint64_t mutex_lock_wait_ticks;
54 thread_local uint64_t mutex_lock_cnt;
55 
56 thread_local uint64_t spin_lock_contention;
57 thread_local uint64_t spin_lock_wait_ticks;
58 thread_local uint64_t spin_lock_cnt;
59 
60 thread_local uint64_t rww_lock_contention;
61 thread_local uint64_t rww_lock_wait_ticks;
62 thread_local uint64_t rww_lock_cnt;
63 
64 thread_local uint64_t rwr_lock_contention;
65 thread_local uint64_t rwr_lock_wait_ticks;
66 thread_local uint64_t rwr_lock_cnt;
67 #endif
68 
69 #ifdef OS_FREEBSD
70 #include <sched.h>
71 #include <sys/param.h>
72 #include <sys/resource.h>
73 #include <sys/cpuset.h>
74 #include <sys/thr.h>
75 #define cpu_set_t cpuset_t
76 #endif /* OS_FREEBSD */
77 
78 /* prototypes */
79 static int SetCPUAffinity(uint16_t cpu);
80 static void TmThreadDeinitMC(ThreadVars *tv);
81 
82 /* root of the threadvars list */
83 ThreadVars *tv_root[TVT_MAX] = { NULL };
84 
85 /* lock to protect tv_root */
87 
88 /**
89  * \brief Check if a thread flag is set.
90  *
91  * \retval 1 flag is set.
92  * \retval 0 flag is not set.
93  */
94 int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
95 {
96  return (SC_ATOMIC_GET(tv->flags) & flag) ? 1 : 0;
97 }
98 
99 /**
100  * \brief Set a thread flag.
101  */
102 void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
103 {
104  SC_ATOMIC_OR(tv->flags, flag);
105 }
106 
107 /**
108  * \brief Unset a thread flag.
109  */
110 void TmThreadsUnsetFlag(ThreadVars *tv, uint32_t flag)
111 {
112  SC_ATOMIC_AND(tv->flags, ~flag);
113 }
114 
116  ThreadVars *tv, PacketQueueNoLock *decode_pq, TmSlot *slot)
117 {
118  while (decode_pq->top != NULL) {
119  Packet *extra_p = PacketDequeueNoLock(decode_pq);
120  if (unlikely(extra_p == NULL))
121  continue;
122  DEBUG_VALIDATE_BUG_ON(extra_p->flow != NULL);
123 
124  if (TmThreadsSlotProcessPkt(tv, slot, extra_p) != TM_ECODE_OK) {
126  }
127  }
129 }
130 
131 /**
132  * \brief Separate run function so we can call it recursively.
133  */
135 {
136  for (TmSlot *s = slot; s != NULL; s = s->slot_next) {
137  PACKET_PROFILING_TMM_START(p, s->tm_id);
138  TmEcode r = s->SlotFunc(tv, p, SC_ATOMIC_GET(s->slot_data));
139  PACKET_PROFILING_TMM_END(p, s->tm_id);
140  DEBUG_VALIDATE_BUG_ON(p->flow != NULL);
141 
142  /* handle error */
143  if (unlikely(r == TM_ECODE_FAILED)) {
144  /* Encountered error. Return packets to packetpool and return */
145  TmThreadsSlotProcessPktFail(tv, NULL);
146  return TM_ECODE_FAILED;
147  }
148  if (s->tm_flags & TM_FLAG_DECODE_TM) {
149  if (TmThreadsProcessDecodePseudoPackets(tv, &tv->decode_pq, s->slot_next) !=
150  TM_ECODE_OK) {
151  return TM_ECODE_FAILED;
152  }
153  }
154  }
155 
156  return TM_ECODE_OK;
157 }
158 
159 /** \internal
160  *
161  * \brief Process flow timeout packets
162  *
163  * Process flow timeout pseudo packets. During shutdown this loop
164  * is run until the flow engine kills the thread and the queue is
165  * empty.
166  */
168 {
169  TmSlot *fw_slot = tv->tm_flowworker;
170  int r = TM_ECODE_OK;
171 
172  if (tv->stream_pq == NULL || fw_slot == NULL) {
173  SCLogDebug("not running TmThreadTimeoutLoop %p/%p", tv->stream_pq, fw_slot);
174  return r;
175  }
176 
177  SCLogDebug("flow end loop starting");
178  while (1) {
180  uint32_t len = tv->stream_pq->len;
182  if (len > 0) {
183  while (len--) {
187  if (likely(p)) {
188  DEBUG_VALIDATE_BUG_ON(p->flow != NULL);
189  r = TmThreadsSlotProcessPkt(tv, fw_slot, p);
190  if (r == TM_ECODE_FAILED) {
191  break;
192  }
193  }
194  }
195  } else {
197  break;
198  }
199  SleepUsec(1);
200  }
201  }
202  SCLogDebug("flow end loop complete");
204 
205  return r;
206 }
207 
208 static bool TmThreadsSlotPktAcqLoopInit(ThreadVars *tv)
209 {
210  TmSlot *s = tv->tm_slots;
211 
213 
214  if (tv->thread_setup_flags != 0)
216 
218  PacketPoolInit();
219 
220  for (TmSlot *slot = s; slot != NULL; slot = slot->slot_next) {
221  if (slot->SlotThreadInit != NULL) {
222  void *slot_data = NULL;
223  TmEcode r = slot->SlotThreadInit(tv, slot->slot_initdata, &slot_data);
224  if (r != TM_ECODE_OK) {
225  if (r == TM_ECODE_DONE) {
226  EngineDone();
228  goto error;
229  } else {
231  goto error;
232  }
233  }
234  (void)SC_ATOMIC_SET(slot->slot_data, slot_data);
235  }
236 
237  /* if the flowworker module is the first, get the threads input queue */
238  if (slot == (TmSlot *)tv->tm_slots && (slot->tm_id == TMM_FLOWWORKER)) {
239  tv->stream_pq = tv->inq->pq;
240  tv->tm_flowworker = slot;
241  SCLogDebug("pre-stream packetqueue %p (inq)", tv->stream_pq);
243  if (tv->flow_queue == NULL) {
245  goto error;
246  }
247  /* setup a queue */
248  } else if (slot->tm_id == TMM_FLOWWORKER) {
249  tv->stream_pq_local = SCCalloc(1, sizeof(PacketQueue));
250  if (tv->stream_pq_local == NULL)
251  FatalError("failed to alloc PacketQueue");
254  tv->tm_flowworker = slot;
255  SCLogDebug("pre-stream packetqueue %p (local)", tv->stream_pq);
257  if (tv->flow_queue == NULL) {
259  goto error;
260  }
261  }
262  }
263 
265 
267 
268  return true;
269 
270 error:
271  return false;
272 }
273 
275 {
276  TmSlot *s = tv->tm_slots;
277  bool rc = true;
278 
280 
282 
283  /* process all pseudo packets the flow timeout may throw at us */
285 
288 
290 
291  for (TmSlot *slot = s; slot != NULL; slot = slot->slot_next) {
292  if (slot->SlotThreadExitPrintStats != NULL) {
293  slot->SlotThreadExitPrintStats(tv, SC_ATOMIC_GET(slot->slot_data));
294  }
295 
296  if (slot->SlotThreadDeinit != NULL) {
297  TmEcode r = slot->SlotThreadDeinit(tv, SC_ATOMIC_GET(slot->slot_data));
298  if (r != TM_ECODE_OK) {
300  rc = false;
301  break;
302  }
303  }
304  }
305 
306  tv->stream_pq = NULL;
308  return rc;
309 }
310 
311 static void *TmThreadsSlotPktAcqLoop(void *td)
312 {
313  ThreadVars *tv = (ThreadVars *)td;
314  TmSlot *s = tv->tm_slots;
315  TmEcode r = TM_ECODE_OK;
316 
317  /* check if we are setup properly */
318  if (s == NULL || s->PktAcqLoop == NULL || tv->tmqh_in == NULL || tv->tmqh_out == NULL) {
319  SCLogError("TmSlot or ThreadVars badly setup: s=%p,"
320  " PktAcqLoop=%p, tmqh_in=%p,"
321  " tmqh_out=%p",
322  s, s ? s->PktAcqLoop : NULL, tv->tmqh_in, tv->tmqh_out);
324  pthread_exit(NULL);
325  return NULL;
326  }
327 
328  if (!TmThreadsSlotPktAcqLoopInit(td)) {
329  goto error;
330  }
331 
332  bool run = TmThreadsWaitForUnpause(tv);
333 
334  while (run) {
335  r = s->PktAcqLoop(tv, SC_ATOMIC_GET(s->slot_data), s);
336 
337  if (r == TM_ECODE_FAILED) {
339  run = false;
340  }
342  run = false;
343  }
344  if (r == TM_ECODE_DONE) {
345  run = false;
346  }
347  }
349  goto error;
350  }
351 
352  SCLogDebug("%s ending", tv->name);
353  pthread_exit((void *) 0);
354  return NULL;
355 
356 error:
357  pthread_exit(NULL);
358  return NULL;
359 }
360 
361 /**
362  * Wait for the thread to be unpaused.
363  *
364  * A thread killed while still in the initial pause skips its main loop,
365  * except mgmt threads (TVT_MGMT): they run one pass to do final work
366  * (e.g. the last stats output) - their loops test THV_KILL and exit
367  * after the pass. RX/worker loops have no top KILL test and would do
368  * real work during teardown (a pcap-file pass dispatches into a pipeline
369  * being torn down), so they keep skipping.
370  */
372 {
375 
376  while (TmThreadsCheckFlag(tv, THV_PAUSE)) {
377  SleepUsec(100);
378 
381  return tv->type == TVT_MGMT;
382  }
383  }
384 
386  }
387 
388  return true;
389 }
390 
391 static void *TmThreadsLib(void *td)
392 {
393  ThreadVars *tv = (ThreadVars *)td;
394  TmSlot *s = tv->tm_slots;
395 
396  /* check if we are setup properly */
397  if (s == NULL || tv->tmqh_in == NULL || tv->tmqh_out == NULL) {
398  SCLogError("TmSlot or ThreadVars badly setup: s=%p, tmqh_in=%p,"
399  " tmqh_out=%p",
400  s, tv->tmqh_in, tv->tmqh_out);
402  return NULL;
403  }
404 
405  if (!TmThreadsSlotPktAcqLoopInit(tv)) {
406  goto error;
407  }
408 
409  if (!TmThreadsWaitForUnpause(tv)) {
410  goto error;
411  }
412 
413  return NULL;
414 
415 error:
416  tv->stream_pq = NULL;
417  return (void *)-1;
418 }
419 
420 static void *TmThreadsSlotVar(void *td)
421 {
422  ThreadVars *tv = (ThreadVars *)td;
423  TmSlot *s = (TmSlot *)tv->tm_slots;
424  Packet *p = NULL;
425  TmEcode r = TM_ECODE_OK;
426 
428  PacketPoolInit();//Empty();
429 
431 
432  if (tv->thread_setup_flags != 0)
434 
435  /* Drop the capabilities for this thread */
436  SCDropCaps(tv);
437 
438  /* check if we are setup properly */
439  if (s == NULL || tv->tmqh_in == NULL || tv->tmqh_out == NULL) {
441  pthread_exit(NULL);
442  return NULL;
443  }
444 
445  for (; s != NULL; s = s->slot_next) {
446  if (s->SlotThreadInit != NULL) {
447  void *slot_data = NULL;
448  r = s->SlotThreadInit(tv, s->slot_initdata, &slot_data);
449  if (r != TM_ECODE_OK) {
451  goto error;
452  }
453  (void)SC_ATOMIC_SET(s->slot_data, slot_data);
454  }
455 
456  /* special case: we need to access the stream queue
457  * from the flow timeout code */
458 
459  /* if the flowworker module is the first, get the threads input queue */
460  if (s == (TmSlot *)tv->tm_slots && (s->tm_id == TMM_FLOWWORKER)) {
461  tv->stream_pq = tv->inq->pq;
462  tv->tm_flowworker = s;
463  SCLogDebug("pre-stream packetqueue %p (inq)", tv->stream_pq);
465  if (tv->flow_queue == NULL) {
467  pthread_exit(NULL);
468  return NULL;
469  }
470  /* setup a queue */
471  } else if (s->tm_id == TMM_FLOWWORKER) {
472  tv->stream_pq_local = SCCalloc(1, sizeof(PacketQueue));
473  if (tv->stream_pq_local == NULL)
474  FatalError("failed to alloc PacketQueue");
477  tv->tm_flowworker = s;
478  SCLogDebug("pre-stream packetqueue %p (local)", tv->stream_pq);
480  if (tv->flow_queue == NULL) {
482  pthread_exit(NULL);
483  return NULL;
484  }
485  }
486  }
487 
489 
490  // Each 'worker' thread uses this func to process/decode the packet read.
491  // Each decode method is different to receive methods in that they do not
492  // enter infinite loops. They use this as the core loop. As a result, at this
493  // point the worker threads can be considered both initialized and running.
495  bool run = TmThreadsWaitForUnpause(tv);
496 
497  s = (TmSlot *)tv->tm_slots;
498 
499  while (run) {
500  /* input a packet */
501  p = tv->tmqh_in(tv);
502 
503  /* if we didn't get a packet see if we need to do some housekeeping */
504  if (unlikely(p == NULL)) {
505  if (tv->flow_queue && SC_ATOMIC_GET(tv->flow_queue->non_empty)) {
507  if (p != NULL) {
510  }
511  }
512  }
513 
514  if (p != NULL) {
515  /* run the thread module(s) */
516  r = TmThreadsSlotVarRun(tv, p, s);
517  if (r == TM_ECODE_FAILED) {
520  break;
521  }
522 
523  /* output the packet */
524  tv->tmqh_out(tv, p);
525 
526  /* now handle the stream pq packets */
527  TmThreadsHandleInjectedPackets(tv);
528  }
529 
531  run = false;
532  }
533  }
535  goto error;
536  }
538 
539  pthread_exit(NULL);
540  return NULL;
541 
542 error:
543  tv->stream_pq = NULL;
544  pthread_exit(NULL);
545  return NULL;
546 }
547 
548 static void *TmThreadsManagement(void *td)
549 {
550  ThreadVars *tv = (ThreadVars *)td;
551  TmSlot *s = (TmSlot *)tv->tm_slots;
552  TmEcode r = TM_ECODE_OK;
553 
554  BUG_ON(s == NULL);
555 
557 
558  if (tv->thread_setup_flags != 0)
560 
561  /* Drop the capabilities for this thread */
562  SCDropCaps(tv);
563 
564  SCLogDebug("%s starting", tv->name);
565 
566  if (s->SlotThreadInit != NULL) {
567  void *slot_data = NULL;
568  r = s->SlotThreadInit(tv, s->slot_initdata, &slot_data);
569  if (r != TM_ECODE_OK) {
571  pthread_exit(NULL);
572  return NULL;
573  }
574  (void)SC_ATOMIC_SET(s->slot_data, slot_data);
575  }
576 
578 
580 
581  r = s->Management(tv, SC_ATOMIC_GET(s->slot_data));
582  /* handle error */
583  if (r == TM_ECODE_FAILED) {
585  }
586 
589  }
590 
593 
594  if (s->SlotThreadExitPrintStats != NULL) {
595  s->SlotThreadExitPrintStats(tv, SC_ATOMIC_GET(s->slot_data));
596  }
597 
598  if (s->SlotThreadDeinit != NULL) {
599  r = s->SlotThreadDeinit(tv, SC_ATOMIC_GET(s->slot_data));
600  if (r != TM_ECODE_OK) {
602  pthread_exit(NULL);
603  return NULL;
604  }
605  }
606 
608  pthread_exit((void *) 0);
609  return NULL;
610 }
611 
612 /**
613  * \brief We set the slot functions.
614  *
615  * \param tv Pointer to the TV to set the slot function for.
616  * \param name Name of the slot variant.
617  * \param fn_p Pointer to a custom slot function. Used only if slot variant
618  * "name" is "custom".
619  *
620  * \retval TmEcode TM_ECODE_OK on success; TM_ECODE_FAILED on failure.
621  */
622 static TmEcode TmThreadSetSlots(ThreadVars *tv, const char *name, void *(*fn_p)(void *))
623 {
624  if (name == NULL) {
625  if (fn_p == NULL) {
626  printf("Both slot name and function pointer can't be NULL inside "
627  "TmThreadSetSlots\n");
628  goto error;
629  } else {
630  name = "custom";
631  }
632  }
633 
634  if (strcmp(name, "varslot") == 0) {
635  tv->tm_func = TmThreadsSlotVar;
636  } else if (strcmp(name, "pktacqloop") == 0) {
637  tv->tm_func = TmThreadsSlotPktAcqLoop;
638  } else if (strcmp(name, "management") == 0) {
639  tv->tm_func = TmThreadsManagement;
640  } else if (strcmp(name, "command") == 0) {
641  tv->tm_func = TmThreadsManagement;
642  } else if (strcmp(name, "lib") == 0) {
643  tv->tm_func = TmThreadsLib;
644  } else if (strcmp(name, "custom") == 0) {
645  if (fn_p == NULL)
646  goto error;
647  tv->tm_func = fn_p;
648  } else {
649  printf("Error: Slot \"%s\" not supported\n", name);
650  goto error;
651  }
652 
653  return TM_ECODE_OK;
654 
655 error:
656  return TM_ECODE_FAILED;
657 }
658 
659 /**
660  * \brief Appends a new entry to the slots.
661  *
662  * \param tv TV the slot is attached to.
663  * \param tm TM to append.
664  * \param data Data to be passed on to the slot init function.
665  *
666  * \retval The allocated TmSlot or NULL if there is an error
667  */
668 void TmSlotSetFuncAppend(ThreadVars *tv, TmModule *tm, const void *data)
669 {
670  TmSlot *slot = SCCalloc(1, sizeof(TmSlot));
671  if (unlikely(slot == NULL))
672  return;
673  SC_ATOMIC_INITPTR(slot->slot_data);
674  slot->SlotThreadInit = tm->ThreadInit;
675  slot->slot_initdata = data;
676  if (tm->Func) {
677  slot->SlotFunc = tm->Func;
678  } else if (tm->PktAcqLoop) {
679  slot->PktAcqLoop = tm->PktAcqLoop;
680  if (tm->PktAcqBreakLoop) {
681  tv->break_loop = true;
682  }
683  } else if (tm->Management) {
684  slot->Management = tm->Management;
685  }
687  slot->SlotThreadDeinit = tm->ThreadDeinit;
688  /* we don't have to check for the return value "-1". We wouldn't have
689  * received a TM as arg, if it didn't exist */
690  slot->tm_id = TmModuleGetIDForTM(tm);
691  slot->tm_flags |= tm->flags;
692 
693  tv->tmm_flags |= tm->flags;
694  tv->cap_flags |= tm->cap_flags;
695 
696  if (tv->tm_slots == NULL) {
697  tv->tm_slots = slot;
698  } else {
699  TmSlot *a = (TmSlot *)tv->tm_slots, *b = NULL;
700 
701  /* get the last slot */
702  for ( ; a != NULL; a = a->slot_next) {
703  b = a;
704  }
705  /* append the new slot */
706  if (b != NULL) {
707  b->slot_next = slot;
708  }
709  }
710 }
711 
712 #if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined __sun
713 static int SetCPUAffinitySet(cpu_set_t *cs)
714 {
715 #if defined OS_FREEBSD
716  int r = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID,
717  SCGetThreadIdLong(), sizeof(cpu_set_t),cs);
718 #elif OS_DARWIN
719  int r = thread_policy_set(mach_thread_self(), THREAD_AFFINITY_POLICY,
720  (void*)cs, THREAD_AFFINITY_POLICY_COUNT);
721 #else
722  pid_t tid = (pid_t)syscall(SYS_gettid);
723  int r = sched_setaffinity(tid, sizeof(cpu_set_t), cs);
724 #endif /* OS_FREEBSD */
725 
726  if (r != 0) {
727  printf("Warning: sched_setaffinity failed (%" PRId32 "): %s\n", r,
728  strerror(errno));
729  return -1;
730  }
731 
732  return 0;
733 }
734 #endif
735 
736 
737 /**
738  * \brief Set the thread affinity on the calling thread.
739  *
740  * \param cpuid Id of the core/cpu to setup the affinity.
741  *
742  * \retval 0 If all goes well; -1 if something is wrong.
743  */
744 static int SetCPUAffinity(uint16_t cpuid)
745 {
746 #if defined __OpenBSD__ || defined __sun
747  return 0;
748 #else
749  int cpu = (int)cpuid;
750 
751 #if defined OS_WIN32 || defined __CYGWIN__
752  DWORD cs = 1 << cpu;
753 
754  int r = (0 == SetThreadAffinityMask(GetCurrentThread(), cs));
755  if (r != 0) {
756  printf("Warning: sched_setaffinity failed (%" PRId32 "): %s\n", r,
757  strerror(errno));
758  return -1;
759  }
760  SCLogDebug("CPU Affinity for thread %lu set to CPU %" PRId32,
761  SCGetThreadIdLong(), cpu);
762 
763  return 0;
764 
765 #else
766  cpu_set_t cs;
767  memset(&cs, 0, sizeof(cs));
768 
769  CPU_ZERO(&cs);
770  CPU_SET(cpu, &cs);
771  return SetCPUAffinitySet(&cs);
772 #endif /* windows */
773 #endif /* not supported */
774 }
775 
776 
777 /**
778  * \brief Set the thread options (thread priority).
779  *
780  * \param tv Pointer to the ThreadVars to setup the thread priority.
781  *
782  * \retval TM_ECODE_OK.
783  */
785 {
787  tv->thread_priority = prio;
788 
789  return TM_ECODE_OK;
790 }
791 
792 /**
793  * \brief Adjusting nice value for threads.
794  */
796 {
797  SCEnter();
798 #ifndef __CYGWIN__
799 #ifdef OS_WIN32
800  if (0 == SetThreadPriority(GetCurrentThread(), tv->thread_priority)) {
801  SCLogError("Error setting priority for "
802  "thread %s: %s",
803  tv->name, strerror(errno));
804  } else {
805  SCLogDebug("Priority set to %"PRId32" for thread %s",
807  }
808 #else
809  int ret = nice(tv->thread_priority);
810  if (ret == -1) {
811  SCLogError("Error setting nice value %d "
812  "for thread %s: %s",
813  tv->thread_priority, tv->name, strerror(errno));
814  } else {
815  SCLogDebug("Nice value set to %"PRId32" for thread %s",
817  }
818 #endif /* OS_WIN32 */
819 #endif
820  SCReturn;
821 }
822 
823 
824 /**
825  * \brief Set the thread options (cpu affinity).
826  *
827  * \param tv pointer to the ThreadVars to setup the affinity.
828  * \param cpu cpu on which affinity is set.
829  *
830  * \retval TM_ECODE_OK
831  */
833 {
835  tv->cpu_affinity = cpu;
836 
837  return TM_ECODE_OK;
838 }
839 
840 
842 {
844  return TM_ECODE_OK;
845 
846  if (type > MAX_CPU_SET) {
847  SCLogError("invalid cpu type family");
848  return TM_ECODE_FAILED;
849  }
850 
852  tv->cpu_affinity = type;
853 
854  return TM_ECODE_OK;
855 }
856 
858 {
859  if (type >= MAX_CPU_SET) {
860  SCLogError("invalid cpu type family");
861  return 0;
862  }
863 
865 }
866 
867 /**
868  * \brief Set the thread options (cpu affinitythread).
869  * Priority should be already set by pthread_create.
870  *
871  * \param tv pointer to the ThreadVars of the calling thread.
872  */
874 {
876  SCLogPerf("Setting affinity for thread \"%s\"to cpu/core "
877  "%"PRIu16", thread id %lu", tv->name, tv->cpu_affinity,
879  SetCPUAffinity(tv->cpu_affinity);
880  }
881 
882 #if !defined __CYGWIN__ && !defined OS_WIN32 && !defined __OpenBSD__ && !defined __sun
887  bool use_iface_affinity = RunmodeIsAutofp() && tv->cpu_affinity == RECEIVE_CPU_SET &&
888  FindAffinityByInterface(taf, tv->iface_name) != NULL;
889  use_iface_affinity |= RunmodeIsWorkers() && tv->cpu_affinity == WORKER_CPU_SET &&
890  FindAffinityByInterface(taf, tv->iface_name) != NULL;
891 
892  if (use_iface_affinity) {
894  }
895 
896  if (UtilAffinityGetAffinedCPUNum(taf) == 0) {
897  if (!taf->nocpu_warned) {
898  SCLogWarning("No CPU affinity set for %s", AffinityGetYamlPath(taf));
899  taf->nocpu_warned = true;
900  }
901  }
902 
903  if (taf->mode_flag == EXCLUSIVE_AFFINITY) {
904  uint16_t cpu = AffinityGetNextCPU(tv, taf);
905  SetCPUAffinity(cpu);
906  /* If CPU is in a set overwrite the default thread prio */
907  if (CPU_ISSET(cpu, &taf->lowprio_cpu)) {
909  } else if (CPU_ISSET(cpu, &taf->medprio_cpu)) {
911  } else if (CPU_ISSET(cpu, &taf->hiprio_cpu)) {
913  } else {
914  tv->thread_priority = taf->prio;
915  }
916  SCLogPerf("Setting prio %d for thread \"%s\" to cpu/core "
917  "%d, thread id %lu", tv->thread_priority,
918  tv->name, cpu, SCGetThreadIdLong());
919  } else {
920  SetCPUAffinitySet(&taf->cpu_set);
921  tv->thread_priority = taf->prio;
922  SCLogPerf("Setting prio %d for thread \"%s\", "
923  "thread id %lu", tv->thread_priority,
925  }
927  }
928 #endif
929 
930  return TM_ECODE_OK;
931 }
932 
933 /**
934  * \brief Creates and returns the TV instance for a new thread.
935  *
936  * \param name Name of this TV instance
937  * \param inq_name Incoming queue name
938  * \param inqh_name Incoming queue handler name as set by TmqhSetup()
939  * \param outq_name Outgoing queue name
940  * \param outqh_name Outgoing queue handler as set by TmqhSetup()
941  * \param slots String representation for the slot function to be used
942  * \param fn_p Pointer to function when \"slots\" is of type \"custom\"
943  * \param mucond Flag to indicate whether to initialize the condition
944  * and the mutex variables for this newly created TV.
945  *
946  * \retval the newly created TV instance, or NULL on error
947  */
948 ThreadVars *TmThreadCreate(const char *name, const char *inq_name, const char *inqh_name,
949  const char *outq_name, const char *outqh_name, const char *slots,
950  void * (*fn_p)(void *), int mucond)
951 {
952  Tmq *tmq = NULL;
953  Tmqh *tmqh = NULL;
954 
955  SCLogDebug("creating thread \"%s\"...", name);
956 
958  if (unlikely(tv == NULL))
959  goto error;
960 
962 
963  strlcpy(tv->name, name, sizeof(tv->name));
964 
965  /* default state for every newly created thread */
967 
968  /* set the incoming queue */
969  if (inq_name != NULL && strcmp(inq_name, "packetpool") != 0) {
970  SCLogDebug("inq_name \"%s\"", inq_name);
971 
972  tmq = TmqGetQueueByName(inq_name);
973  if (tmq == NULL) {
974  tmq = TmqCreateQueue(inq_name);
975  if (tmq == NULL)
976  goto error;
977  }
978  SCLogDebug("tmq %p", tmq);
979 
980  tv->inq = tmq;
981  tv->inq->reader_cnt++;
982  SCLogDebug("tv->inq %p", tv->inq);
983  }
984  if (inqh_name != NULL) {
985  SCLogDebug("inqh_name \"%s\"", inqh_name);
986 
987  int id = TmqhNameToID(inqh_name);
988  if (id <= 0) {
989  goto error;
990  }
991  tmqh = TmqhGetQueueHandlerByName(inqh_name);
992  if (tmqh == NULL)
993  goto error;
994 
995  tv->tmqh_in = tmqh->InHandler;
996  tv->inq_id = (uint8_t)id;
997  SCLogDebug("tv->tmqh_in %p", tv->tmqh_in);
998  }
999 
1000  /* set the outgoing queue */
1001  if (outqh_name != NULL) {
1002  SCLogDebug("outqh_name \"%s\"", outqh_name);
1003 
1004  int id = TmqhNameToID(outqh_name);
1005  if (id <= 0) {
1006  goto error;
1007  }
1008 
1009  tmqh = TmqhGetQueueHandlerByName(outqh_name);
1010  if (tmqh == NULL)
1011  goto error;
1012 
1013  tv->tmqh_out = tmqh->OutHandler;
1014  tv->outq_id = (uint8_t)id;
1015 
1016  if (outq_name != NULL && strcmp(outq_name, "packetpool") != 0) {
1017  SCLogDebug("outq_name \"%s\"", outq_name);
1018 
1019  if (tmqh->OutHandlerCtxSetup != NULL) {
1020  tv->outctx = tmqh->OutHandlerCtxSetup(outq_name);
1021  if (tv->outctx == NULL)
1022  goto error;
1023  tv->outq = NULL;
1024  } else {
1025  tmq = TmqGetQueueByName(outq_name);
1026  if (tmq == NULL) {
1027  tmq = TmqCreateQueue(outq_name);
1028  if (tmq == NULL)
1029  goto error;
1030  }
1031  SCLogDebug("tmq %p", tmq);
1032 
1033  tv->outq = tmq;
1034  tv->outctx = NULL;
1035  tv->outq->writer_cnt++;
1036  }
1037  }
1038  }
1039 
1040  if (TmThreadSetSlots(tv, slots, fn_p) != TM_ECODE_OK) {
1041  goto error;
1042  }
1043 
1044  if (mucond != 0)
1045  TmThreadInitMC(tv);
1046 
1048 
1049  return tv;
1050 
1051 error:
1052  SCLogError("failed to setup a thread");
1053 
1054  ThreadVarsFree(tv);
1055  return NULL;
1056 }
1057 
1058 /**
1059  * \brief Creates and returns a TV instance for a Packet Processing Thread.
1060  * This function doesn't support custom slots, and hence shouldn't be
1061  * supplied \"custom\" as its slot type. All PPT threads are created
1062  * with a mucond(see TmThreadCreate declaration) of 0. Hence the tv
1063  * conditional variables are not used to kill the thread.
1064  *
1065  * \param name Name of this TV instance
1066  * \param inq_name Incoming queue name
1067  * \param inqh_name Incoming queue handler name as set by TmqhSetup()
1068  * \param outq_name Outgoing queue name
1069  * \param outqh_name Outgoing queue handler as set by TmqhSetup()
1070  * \param slots String representation for the slot function to be used
1071  *
1072  * \retval the newly created TV instance, or NULL on error
1073  */
1074 ThreadVars *TmThreadCreatePacketHandler(const char *name, const char *inq_name,
1075  const char *inqh_name, const char *outq_name,
1076  const char *outqh_name, const char *slots)
1077 {
1078  ThreadVars *tv = NULL;
1079 
1080  tv = TmThreadCreate(name, inq_name, inqh_name, outq_name, outqh_name,
1081  slots, NULL, 0);
1082 
1083  if (tv != NULL) {
1084  tv->type = TVT_PPT;
1086  }
1087 
1088  return tv;
1089 }
1090 
1091 /**
1092  * \brief Creates and returns the TV instance for a Management thread(MGMT).
1093  * This function supports only custom slot functions and hence a
1094  * function pointer should be sent as an argument.
1095  *
1096  * \param name Name of this TV instance
1097  * \param fn_p Pointer to function when \"slots\" is of type \"custom\"
1098  * \param mucond Flag to indicate whether to initialize the condition
1099  * and the mutex variables for this newly created TV.
1100  *
1101  * \retval the newly created TV instance, or NULL on error
1102  */
1103 ThreadVars *TmThreadCreateMgmtThread(const char *name, void *(fn_p)(void *),
1104  int mucond)
1105 {
1106  ThreadVars *tv = NULL;
1107 
1108  tv = TmThreadCreate(name, NULL, NULL, NULL, NULL, "custom", fn_p, mucond);
1109 
1110  if (tv != NULL) {
1111  tv->type = TVT_MGMT;
1114  }
1115 
1116  return tv;
1117 }
1118 
1119 /**
1120  * \brief Creates and returns the TV instance for a Management thread(MGMT).
1121  * This function supports only custom slot functions and hence a
1122  * function pointer should be sent as an argument.
1123  *
1124  * \param name Name of this TV instance
1125  * \param module Name of TmModule with MANAGEMENT flag set.
1126  * \param mucond Flag to indicate whether to initialize the condition
1127  * and the mutex variables for this newly created TV.
1128  *
1129  * \retval the newly created TV instance, or NULL on error
1130  */
1131 ThreadVars *TmThreadCreateMgmtThreadByName(const char *name, const char *module,
1132  int mucond)
1133 {
1134  ThreadVars *tv = NULL;
1135 
1136  tv = TmThreadCreate(name, NULL, NULL, NULL, NULL, "management", NULL, mucond);
1137 
1138  if (tv != NULL) {
1139  tv->type = TVT_MGMT;
1142 
1143  TmModule *m = TmModuleGetByName(module);
1144  if (m) {
1145  TmSlotSetFuncAppend(tv, m, NULL);
1146  }
1147  }
1148 
1149  return tv;
1150 }
1151 
1152 /**
1153  * \brief Creates and returns the TV instance for a Command thread (CMD).
1154  * This function supports only custom slot functions and hence a
1155  * function pointer should be sent as an argument.
1156  *
1157  * \param name Name of this TV instance
1158  * \param module Name of TmModule with COMMAND flag set.
1159  * \param mucond Flag to indicate whether to initialize the condition
1160  * and the mutex variables for this newly created TV.
1161  *
1162  * \retval the newly created TV instance, or NULL on error
1163  */
1164 ThreadVars *TmThreadCreateCmdThreadByName(const char *name, const char *module,
1165  int mucond)
1166 {
1167  ThreadVars *tv = NULL;
1168 
1169  tv = TmThreadCreate(name, NULL, NULL, NULL, NULL, "command", NULL, mucond);
1170 
1171  if (tv != NULL) {
1172  tv->type = TVT_CMD;
1175 
1176  TmModule *m = TmModuleGetByName(module);
1177  if (m) {
1178  TmSlotSetFuncAppend(tv, m, NULL);
1179  }
1180  }
1181 
1182  return tv;
1183 }
1184 
1185 /**
1186  * \brief Appends this TV to tv_root based on its type
1187  *
1188  * \param type holds the type this TV belongs to.
1189  */
1191 {
1193 
1194  if (tv_root[type] == NULL) {
1195  tv_root[type] = tv;
1196  tv->next = NULL;
1197 
1199 
1200  return;
1201  }
1202 
1203  ThreadVars *t = tv_root[type];
1204 
1205  while (t) {
1206  if (t->next == NULL) {
1207  t->next = tv;
1208  tv->next = NULL;
1209  break;
1210  }
1211 
1212  t = t->next;
1213  }
1214 
1216 }
1217 
1218 static bool ThreadStillHasPackets(ThreadVars *tv)
1219 {
1220  if (tv->inq != NULL && !tv->inq->is_packet_pool) {
1221  /* we wait till we dry out all the inq packets, before we
1222  * kill this thread. Do note that you should have disabled
1223  * packet acquire by now using TmThreadDisableReceiveThreads()*/
1224  PacketQueue *q = tv->inq->pq;
1225  SCMutexLock(&q->mutex_q);
1226  uint32_t len = q->len;
1227  SCMutexUnlock(&q->mutex_q);
1228  if (len != 0) {
1229  return true;
1230  }
1231  }
1232 
1233  if (tv->stream_pq != NULL) {
1235  uint32_t len = tv->stream_pq->len;
1237 
1238  if (len != 0) {
1239  return true;
1240  }
1241  }
1242  return false;
1243 }
1244 
1245 /**
1246  * \brief Kill a thread.
1247  *
1248  * \param tv A ThreadVars instance corresponding to the thread that has to be
1249  * killed.
1250  *
1251  * \retval r 1 killed successfully
1252  * 0 not yet ready, needs another look
1253  */
1254 static int TmThreadKillThread(ThreadVars *tv)
1255 {
1256  BUG_ON(tv == NULL);
1257 
1258  /* kill only once :) */
1259  if (TmThreadsCheckFlag(tv, THV_DEAD)) {
1260  return 1;
1261  }
1262 
1263  /* set the thread flag informing the thread that it needs to be
1264  * terminated */
1267 
1268  /* to be sure, signal more */
1269  if (!(TmThreadsCheckFlag(tv, THV_CLOSED))) {
1270  if (tv->inq_id != TMQH_NOT_SET) {
1272  if (qh != NULL && qh->InShutdownHandler != NULL) {
1273  qh->InShutdownHandler(tv);
1274  }
1275  }
1276  if (tv->inq != NULL) {
1277  for (int i = 0; i < (tv->inq->reader_cnt + tv->inq->writer_cnt); i++) {
1278  SCMutexLock(&tv->inq->pq->mutex_q);
1279  SCCondSignal(&tv->inq->pq->cond_q);
1280  SCMutexUnlock(&tv->inq->pq->mutex_q);
1281  }
1282  SCLogDebug("signalled tv->inq->id %" PRIu32 "", tv->inq->id);
1283  }
1284 
1285  if (tv->ctrl_cond != NULL ) {
1287  pthread_cond_broadcast(tv->ctrl_cond);
1289  }
1290  return 0;
1291  }
1292 
1293  if (tv->outctx != NULL) {
1294  if (tv->outq_id != TMQH_NOT_SET) {
1296  if (qh != NULL && qh->OutHandlerCtxFree != NULL) {
1297  qh->OutHandlerCtxFree(tv->outctx);
1298  tv->outctx = NULL;
1299  }
1300  }
1301  }
1302 
1303  /* Join the thread and flag as dead, unless the thread ID is 0 as
1304  * its not a thread created by Suricata. */
1305  if (tv->t) {
1306  pthread_join(tv->t, NULL);
1307  SCLogDebug("thread %s stopped", tv->name);
1308  }
1310  return 1;
1311 }
1312 
1313 static bool ThreadBusy(ThreadVars *tv)
1314 {
1315  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
1316  TmModule *tm = TmModuleGetById(s->tm_id);
1317  if (tm && tm->ThreadBusy != NULL) {
1318  if (tm->ThreadBusy(tv, SC_ATOMIC_GET(s->slot_data)))
1319  return true;
1320  }
1321  }
1322  return false;
1323 }
1324 
1325 /** \internal
1326  *
1327  * \brief make sure that all packet threads are done processing their
1328  * in-flight packets, including 'injected' flow packets.
1329  */
1330 static void TmThreadDrainPacketThreads(void)
1331 {
1332  ThreadVars *tv = NULL;
1333  struct timeval start_ts;
1334  struct timeval cur_ts;
1335  gettimeofday(&start_ts, NULL);
1336 
1337 again:
1338  gettimeofday(&cur_ts, NULL);
1339  if ((cur_ts.tv_sec - start_ts.tv_sec) > 60) {
1340  SCLogWarning("unable to get all packet threads "
1341  "to process their packets in time");
1342  return;
1343  }
1344 
1346 
1347  /* all receive threads are part of packet processing threads */
1348  tv = tv_root[TVT_PPT];
1349  while (tv) {
1350  if (ThreadStillHasPackets(tv)) {
1351  /* we wait till we dry out all the inq packets, before we
1352  * kill this thread. Do note that you should have disabled
1353  * packet acquire by now using TmThreadDisableReceiveThreads()*/
1355 
1356  /* sleep outside lock */
1357  SleepMsec(1);
1358  goto again;
1359  }
1360  if (ThreadBusy(tv)) {
1362 
1364  if (p != NULL) {
1368  PacketQueue *q = tv->stream_pq;
1369  SCMutexLock(&q->mutex_q);
1370  PacketEnqueue(q, p);
1371  SCCondSignal(&q->cond_q);
1372  SCMutexUnlock(&q->mutex_q);
1373  }
1374 
1375  /* don't sleep while holding a lock */
1376  SleepMsec(1);
1377  goto again;
1378  }
1379  tv = tv->next;
1380  }
1381 
1383 }
1384 
1385 /**
1386  * \brief Disable all threads having the specified TMs.
1387  *
1388  * Breaks out of the packet acquisition loop, and bumps
1389  * into the 'flow loop', where it will process packets
1390  * from the flow engine's shutdown handling.
1391  */
1393 {
1394  ThreadVars *tv = NULL;
1395  struct timeval start_ts;
1396  struct timeval cur_ts;
1397  gettimeofday(&start_ts, NULL);
1398 
1399 again:
1400  gettimeofday(&cur_ts, NULL);
1401  if ((cur_ts.tv_sec - start_ts.tv_sec) > 60) {
1402  FatalError("Engine unable to disable detect "
1403  "thread - \"%s\". Killing engine",
1404  tv->name);
1405  }
1406 
1408 
1409  /* all receive threads are part of packet processing threads */
1410  tv = tv_root[TVT_PPT];
1411 
1412  /* we do have to keep in mind that TVs are arranged in the order
1413  * right from receive to log. The moment we fail to find a
1414  * receive TM amongst the slots in a tv, it indicates we are done
1415  * with all receive threads */
1416  while (tv) {
1417  int disable = 0;
1418  TmModule *tm = NULL;
1419  /* obtain the slots for this TV */
1420  TmSlot *slots = tv->tm_slots;
1421  while (slots != NULL) {
1422  tm = TmModuleGetById(slots->tm_id);
1423 
1424  if (tm->flags & TM_FLAG_RECEIVE_TM) {
1425  disable = 1;
1426  break;
1427  }
1428 
1429  slots = slots->slot_next;
1430  continue;
1431  }
1432 
1433  if (disable) {
1434  if (ThreadStillHasPackets(tv)) {
1435  /* we wait till we dry out all the inq packets, before we
1436  * kill this thread. Do note that you should have disabled
1437  * packet acquire by now using TmThreadDisableReceiveThreads()*/
1439  /* don't sleep while holding a lock */
1440  SleepMsec(1);
1441  goto again;
1442  }
1443 
1444  if (ThreadBusy(tv)) {
1446 
1448  if (p != NULL) {
1452  PacketQueue *q = tv->stream_pq;
1453  SCMutexLock(&q->mutex_q);
1454  PacketEnqueue(q, p);
1455  SCCondSignal(&q->cond_q);
1456  SCMutexUnlock(&q->mutex_q);
1457  }
1458 
1459  /* don't sleep while holding a lock */
1460  SleepMsec(1);
1461  goto again;
1462  }
1463 
1464  /* we found a receive TV. Send it a KILL_PKTACQ signal. */
1465  if (tm && tm->PktAcqBreakLoop != NULL) {
1466  tm->PktAcqBreakLoop(tv, SC_ATOMIC_GET(slots->slot_data));
1467  }
1469 
1470  if (tv->inq != NULL) {
1471  for (int i = 0; i < (tv->inq->reader_cnt + tv->inq->writer_cnt); i++) {
1472  SCMutexLock(&tv->inq->pq->mutex_q);
1473  SCCondSignal(&tv->inq->pq->cond_q);
1474  SCMutexUnlock(&tv->inq->pq->mutex_q);
1475  }
1476  SCLogDebug("signalled tv->inq->id %" PRIu32 "", tv->inq->id);
1477  }
1478 
1479  /* wait for it to enter the 'flow loop' stage */
1480  while (!TmThreadsCheckFlag(tv, THV_FLOW_LOOP)) {
1482 
1483  SleepMsec(1);
1484  goto again;
1485  }
1486  }
1487 
1488  tv = tv->next;
1489  }
1490 
1492 
1493  /* finally wait for all packet threads to have
1494  * processed all of their 'live' packets so we
1495  * don't process the last live packets together
1496  * with FFR packets */
1497  TmThreadDrainPacketThreads();
1498 }
1499 
1500 #ifdef DEBUG_VALIDATION
1501 static void TmThreadDumpThreads(void);
1502 #endif
1503 
1504 static void TmThreadDebugValidateNoMorePackets(void)
1505 {
1506 #ifdef DEBUG_VALIDATION
1508  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
1509  if (ThreadStillHasPackets(tv)) {
1511  TmThreadDumpThreads();
1513  }
1514  }
1516 #endif
1517 }
1518 
1519 /** \internal
1520  * \brief check if a thread has any of the modules indicated by TM_FLAG_*
1521  * \param tv thread
1522  * \param flags TM_FLAG_*'s
1523  * \retval bool true if at least on of the flags is present */
1524 static inline bool CheckModuleFlags(const ThreadVars *tv, const uint8_t flags)
1525 {
1526  return (tv->tmm_flags & flags) != 0;
1527 }
1528 
1529 /**
1530  * \brief Disable all packet threads
1531  * \param set flag to set
1532  * \param check flag to check
1533  * \param module_flags bitflags of TmModule's to apply the `set` flag to.
1534  *
1535  * Support 2 stages in shutting down the packet threads:
1536  * 1. set THV_REQ_FLOW_LOOP and wait for THV_FLOW_LOOP
1537  * 2. set THV_KILL and wait for THV_RUNNING_DONE
1538  *
1539  * During step 1 the main loop is exited, and the flow loop logic is entered.
1540  * During step 2, the flow loop logic is done and the thread closes.
1541  *
1542  * `module_flags` limits which threads are disabled
1543  */
1545  const uint16_t set, const uint16_t check, const uint8_t module_flags)
1546 {
1547  struct timeval start_ts;
1548  struct timeval cur_ts;
1549 
1550  /* first drain all packet threads of their packets */
1551  TmThreadDrainPacketThreads();
1552 
1553  /* since all the threads possibly able to produce more packets
1554  * are now gone or inactive, we should see no packets anywhere
1555  * anymore. */
1556  TmThreadDebugValidateNoMorePackets();
1557 
1558  gettimeofday(&start_ts, NULL);
1559 again:
1560  gettimeofday(&cur_ts, NULL);
1561  if ((cur_ts.tv_sec - start_ts.tv_sec) > 60) {
1562  FatalError("Engine unable to disable packet "
1563  "threads. Killing engine");
1564  }
1565 
1566  /* loop through the packet threads and kill them */
1568  for (ThreadVars *tv = tv_root[TVT_PPT]; tv != NULL; tv = tv->next) {
1569  /* only set flow worker threads to THV_REQ_FLOW_LOOP */
1570  if (!CheckModuleFlags(tv, module_flags)) {
1571  SCLogDebug("%s does not have any of the modules %02x, skip", tv->name, module_flags);
1572  continue;
1573  }
1574  TmThreadsSetFlag(tv, set);
1575 
1576  /* separate worker threads (autofp) will still wait at their
1577  * input queues. So nudge them here so they will observe the
1578  * THV_KILL flag. */
1579  if (tv->inq != NULL) {
1580  for (int i = 0; i < (tv->inq->reader_cnt + tv->inq->writer_cnt); i++) {
1581  SCMutexLock(&tv->inq->pq->mutex_q);
1582  SCCondSignal(&tv->inq->pq->cond_q);
1583  SCMutexUnlock(&tv->inq->pq->mutex_q);
1584  }
1585  SCLogDebug("signalled tv->inq->id %" PRIu32 "", tv->inq->id);
1586  }
1587 
1588  /* wait for it to reach the expected state */
1589  if (!TmThreadsCheckFlag(tv, check)) {
1591  SCLogDebug("%s did not reach state %u, again", tv->name, check);
1592 
1593  SleepMsec(1);
1594  goto again;
1595  }
1596  }
1598 }
1599 
1600 #define MIN_WAIT_TIME 100
1601 #define MAX_WAIT_TIME 999999
1603 {
1604  ThreadVars *tv = NULL;
1605  unsigned int sleep_usec = MIN_WAIT_TIME;
1606 
1607  BUG_ON((family < 0) || (family >= TVT_MAX));
1608 
1609 again:
1611  tv = tv_root[family];
1612 
1613  while (tv) {
1614  int r = TmThreadKillThread(tv);
1615  if (r == 0) {
1617  SleepUsec(sleep_usec);
1618  sleep_usec *= 2; /* slowly back off */
1619  sleep_usec = MIN(sleep_usec, MAX_WAIT_TIME);
1620  goto again;
1621  }
1622  sleep_usec = MIN_WAIT_TIME; /* reset */
1623 
1624  tv = tv->next;
1625  }
1627 }
1628 #undef MIN_WAIT_TIME
1629 #undef MAX_WAIT_TIME
1630 
1632 {
1633  int i = 0;
1634 
1635  for (i = 0; i < TVT_MAX; i++) {
1637  }
1638 }
1639 
1640 static void TmThreadFree(ThreadVars *tv)
1641 {
1642  TmSlot *s;
1643  TmSlot *ps;
1644  if (tv == NULL)
1645  return;
1646 
1647  SCLogDebug("Freeing thread '%s'.", tv->name);
1648 
1650 
1651  if (tv->flow_queue) {
1652  BUG_ON(tv->flow_queue->qlen != 0);
1653  SCFree(tv->flow_queue);
1654  }
1655 
1657 
1658  TmThreadDeinitMC(tv);
1659 
1660  if (tv->printable_name) {
1662  }
1663 
1664  if (tv->iface_name) {
1665  SCFree(tv->iface_name);
1666  }
1667 
1668  if (tv->stream_pq_local) {
1672  }
1673 
1674  s = (TmSlot *)tv->tm_slots;
1675  while (s) {
1676  ps = s;
1677  s = s->slot_next;
1678  SCFree(ps);
1679  }
1680 
1682  ThreadVarsFree(tv);
1683 }
1684 
1686 {
1687  ThreadVars *tv = NULL;
1688  ThreadVars *ptv = NULL;
1689 
1690  if ((family < 0) || (family >= TVT_MAX))
1691  return;
1692 
1694  tv = tv_root[family];
1695 
1696  while (tv) {
1697  ptv = tv;
1698  tv = tv->next;
1699  TmThreadFree(ptv);
1700  }
1701  tv_root[family] = NULL;
1703 }
1704 
1705 /**
1706  * \brief Spawns a thread associated with the ThreadVars instance tv
1707  *
1708  * \retval TM_ECODE_OK on success and TM_ECODE_FAILED on failure
1709  */
1711 {
1712  pthread_attr_t attr;
1713  if (tv->tm_func == NULL) {
1714  FatalError("No thread function set");
1715  }
1716 
1717  /* Initialize and set thread detached attribute */
1718  pthread_attr_init(&attr);
1719 
1720  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1721 
1722  /* Adjust thread stack size if configured */
1724  SCLogDebug("Setting per-thread stack size to %" PRIu64, threading_set_stack_size);
1725  if (pthread_attr_setstacksize(&attr, (size_t)threading_set_stack_size)) {
1726  FatalError("Unable to increase stack size to %" PRIu64 " in thread attributes",
1728  }
1729  }
1730 
1731  int rc = pthread_create(&tv->t, &attr, tv->tm_func, (void *)tv);
1732  pthread_attr_destroy(&attr);
1733  if (rc) {
1734  FatalError("Unable to create thread %s with pthread_create(): retval %d: %s", tv->name, rc,
1735  strerror(errno));
1736  }
1737 
1738 #if DEBUG && HAVE_PTHREAD_GETATTR_NP
1740  if (pthread_getattr_np(tv->t, &attr) == 0) {
1741  size_t stack_size;
1742  void *stack_addr;
1743  pthread_attr_getstack(&attr, &stack_addr, &stack_size);
1744  SCLogDebug("stack: %p; size %" PRIu64, stack_addr, (uintmax_t)stack_size);
1745  pthread_attr_destroy(&attr);
1746  } else {
1747  SCLogDebug("Unable to retrieve current stack-size for display; return code from "
1748  "pthread_getattr_np() is %" PRId32,
1749  rc);
1750  }
1751  }
1752 #endif
1753 
1755 
1756  TmThreadAppend(tv, tv->type);
1757  return TM_ECODE_OK;
1758 }
1759 
1760 /**
1761  * \brief Spawns a "fake" lib thread associated with the ThreadVars instance tv
1762  *
1763  * \retval TM_ECODE_OK on success and TM_ECODE_FAILED on failure
1764  */
1766 {
1767  if (tv->tm_func == NULL) {
1768  printf("ERROR: no thread function set\n");
1769  return TM_ECODE_FAILED;
1770  }
1771 
1772  if (tv->tm_func((void *)tv) == (void *)-1) {
1773  return TM_ECODE_FAILED;
1774  }
1775 
1777 
1778  return TM_ECODE_OK;
1779 }
1780 
1781 /**
1782  * \brief Initializes the mutex and condition variables for this TV
1783  *
1784  * It can be used by a thread to control a wait loop that can also be
1785  * influenced by other threads.
1786  *
1787  * \param tv Pointer to a TV instance
1788  */
1790 {
1791  if ( (tv->ctrl_mutex = SCMalloc(sizeof(*tv->ctrl_mutex))) == NULL) {
1792  FatalError("Fatal error encountered in TmThreadInitMC. "
1793  "Exiting...");
1794  }
1795 
1796  if (SCCtrlMutexInit(tv->ctrl_mutex, NULL) != 0) {
1797  printf("Error initializing the tv->m mutex\n");
1798  exit(EXIT_FAILURE);
1799  }
1800 
1801  if ( (tv->ctrl_cond = SCMalloc(sizeof(*tv->ctrl_cond))) == NULL) {
1802  FatalError("Fatal error encountered in TmThreadInitMC. "
1803  "Exiting...");
1804  }
1805 
1806  if (SCCtrlCondInit(tv->ctrl_cond, NULL) != 0) {
1807  FatalError("Error initializing the tv->cond condition "
1808  "variable");
1809  }
1810 }
1811 
1812 static void TmThreadDeinitMC(ThreadVars *tv)
1813 {
1814  if (tv->ctrl_mutex) {
1816  SCFree(tv->ctrl_mutex);
1817  }
1818  if (tv->ctrl_cond) {
1820  SCFree(tv->ctrl_cond);
1821  }
1822 }
1823 
1824 /**
1825  * \brief Waits till the specified flag(s) is(are) set. We don't bother if
1826  * the kill flag has been set or not on the thread.
1827  *
1828  * \param tv Pointer to the TV instance.
1829  */
1831 {
1832  while (!TmThreadsCheckFlag(tv, flags)) {
1833  SleepUsec(100);
1834  }
1835 }
1836 
1837 /**
1838  * \brief Unpauses a thread
1839  *
1840  * \param tv Pointer to a TV instance that has to be unpaused
1841  */
1843 {
1845 }
1846 
1847 static TmEcode WaitOnThreadsRunningByType(const int t)
1848 {
1849  struct timeval start_ts;
1850  struct timeval cur_ts;
1851  uint32_t thread_cnt = 0;
1852 
1853  /* on retries, this will init to the last thread that started up already */
1854  ThreadVars *tv_start = tv_root[t];
1856  for (ThreadVars *tv = tv_start; tv != NULL; tv = tv->next) {
1857  thread_cnt++;
1858  }
1860 
1861  /* give threads a second each to start up, plus a margin of a minute. */
1862  uint32_t time_budget = 60 + thread_cnt;
1863 
1864  gettimeofday(&start_ts, NULL);
1865 again:
1867  ThreadVars *tv = tv_start;
1868  while (tv != NULL) {
1871 
1872  SCLogError("thread \"%s\" failed to "
1873  "start: flags %04x",
1874  tv->name, SC_ATOMIC_GET(tv->flags));
1875  return TM_ECODE_FAILED;
1876  }
1877 
1880 
1881  /* 60 seconds provided for the thread to transition from
1882  * THV_INIT_DONE to THV_RUNNING */
1883  gettimeofday(&cur_ts, NULL);
1884  if (((uint32_t)cur_ts.tv_sec - (uint32_t)start_ts.tv_sec) > time_budget) {
1885  SCLogError("thread \"%s\" failed to "
1886  "start in time: flags %04x. Total threads: %u. Time budget %us",
1887  tv->name, SC_ATOMIC_GET(tv->flags), thread_cnt, time_budget);
1888  return TM_ECODE_FAILED;
1889  }
1890 
1891  /* sleep a little to give the thread some
1892  * time to start running */
1893  SleepUsec(100);
1894  goto again;
1895  }
1896  tv_start = tv;
1897 
1898  tv = tv->next;
1899  }
1901  return TM_ECODE_OK;
1902 }
1903 
1904 /**
1905  * \brief Waits for all threads to be in a running state
1906  *
1907  * \retval TM_ECODE_OK if all are running or error if a thread failed
1908  */
1910 {
1911  uint16_t RX_num = 0;
1912  uint16_t W_num = 0;
1913  uint16_t FM_num = 0;
1914  uint16_t FR_num = 0;
1915  uint16_t TX_num = 0;
1916 
1917  for (int i = 0; i < TVT_MAX; i++) {
1918  if (WaitOnThreadsRunningByType(i) != TM_ECODE_OK)
1919  return TM_ECODE_FAILED;
1920  }
1921 
1923  for (int i = 0; i < TVT_MAX; i++) {
1924  for (ThreadVars *tv = tv_root[i]; tv != NULL; tv = tv->next) {
1925  if (strncmp(thread_name_autofp, tv->name, strlen(thread_name_autofp)) == 0)
1926  RX_num++;
1927  else if (strncmp(thread_name_workers, tv->name, strlen(thread_name_workers)) == 0)
1928  W_num++;
1929  else if (strncmp(thread_name_verdict, tv->name, strlen(thread_name_verdict)) == 0)
1930  TX_num++;
1931  else if (strncmp(thread_name_flow_mgr, tv->name, strlen(thread_name_flow_mgr)) == 0)
1932  FM_num++;
1933  else if (strncmp(thread_name_flow_rec, tv->name, strlen(thread_name_flow_rec)) == 0)
1934  FR_num++;
1935  }
1936  }
1938 
1939  /* Construct a welcome string displaying
1940  * initialized thread types and counts */
1941  uint16_t app_len = 32;
1942  uint16_t buf_len = 256;
1943 
1944  char append_str[app_len];
1945  char thread_counts[buf_len];
1946 
1947  strlcpy(thread_counts, "Threads created -> ", strlen("Threads created -> ") + 1);
1948  if (RX_num > 0) {
1949  snprintf(append_str, app_len, "RX: %u ", RX_num);
1950  strlcat(thread_counts, append_str, buf_len);
1951  }
1952  if (W_num > 0) {
1953  snprintf(append_str, app_len, "W: %u ", W_num);
1954  strlcat(thread_counts, append_str, buf_len);
1955  }
1956  if (TX_num > 0) {
1957  snprintf(append_str, app_len, "TX: %u ", TX_num);
1958  strlcat(thread_counts, append_str, buf_len);
1959  }
1960  if (FM_num > 0) {
1961  snprintf(append_str, app_len, "FM: %u ", FM_num);
1962  strlcat(thread_counts, append_str, buf_len);
1963  }
1964  if (FR_num > 0) {
1965  snprintf(append_str, app_len, "FR: %u ", FR_num);
1966  strlcat(thread_counts, append_str, buf_len);
1967  }
1968  snprintf(append_str, app_len, " Engine started.");
1969  strlcat(thread_counts, append_str, buf_len);
1970  SCLogNotice("%s", thread_counts);
1971 
1972  return TM_ECODE_OK;
1973 }
1974 
1975 /**
1976  * \brief Unpauses all threads present in tv_root
1977  */
1979 {
1981  for (int i = 0; i < TVT_MAX; i++) {
1982  ThreadVars *tv = tv_root[i];
1983  while (tv != NULL) {
1985  tv = tv->next;
1986  }
1987  }
1989 }
1990 
1991 /**
1992  * \brief Used to check the thread for certain conditions of failure.
1993  */
1995 {
1997  for (int i = 0; i < TVT_MAX; i++) {
1998  ThreadVars *tv = tv_root[i];
1999  while (tv) {
2001  FatalError("thread %s failed", tv->name);
2002  }
2003  tv = tv->next;
2004  }
2005  }
2007 }
2008 
2009 /**
2010  * \brief Used to check if all threads have finished their initialization. On
2011  * finding an un-initialized thread, it waits till that thread completes
2012  * its initialization, before proceeding to the next thread.
2013  *
2014  * \retval TM_ECODE_OK all initialized properly
2015  * \retval TM_ECODE_FAILED failure
2016  */
2018 {
2019  struct timeval start_ts;
2020  struct timeval cur_ts;
2021  gettimeofday(&start_ts, NULL);
2022 
2023 again:
2025  for (int i = 0; i < TVT_MAX; i++) {
2026  ThreadVars *tv = tv_root[i];
2027  while (tv != NULL) {
2030 
2031  SCLogError("thread \"%s\" failed to "
2032  "initialize: flags %04x",
2033  tv->name, SC_ATOMIC_GET(tv->flags));
2034  return TM_ECODE_FAILED;
2035  }
2036 
2037  if (!(TmThreadsCheckFlag(tv, THV_INIT_DONE))) {
2039 
2040  gettimeofday(&cur_ts, NULL);
2041  if ((cur_ts.tv_sec - start_ts.tv_sec) > 120) {
2042  SCLogError("thread \"%s\" failed to "
2043  "initialize in time: flags %04x",
2044  tv->name, SC_ATOMIC_GET(tv->flags));
2045  return TM_ECODE_FAILED;
2046  }
2047 
2048  /* sleep a little to give the thread some
2049  * time to finish initialization */
2050  SleepUsec(100);
2051  goto again;
2052  }
2053 
2056  SCLogError("thread \"%s\" failed to "
2057  "initialize.",
2058  tv->name);
2059  return TM_ECODE_FAILED;
2060  }
2063  SCLogError("thread \"%s\" closed on "
2064  "initialization.",
2065  tv->name);
2066  return TM_ECODE_FAILED;
2067  }
2068 
2069  tv = tv->next;
2070  }
2071  }
2073 
2074  return TM_ECODE_OK;
2075 }
2076 
2077 /**
2078  * \brief returns a count of all the threads that match the flag
2079  */
2081 {
2082  uint32_t cnt = 0;
2084  for (int i = 0; i < TVT_MAX; i++) {
2085  ThreadVars *tv = tv_root[i];
2086  while (tv != NULL) {
2087  if ((tv->tmm_flags & flags) == flags)
2088  cnt++;
2089 
2090  tv = tv->next;
2091  }
2092  }
2094  return cnt;
2095 }
2096 
2097 #ifdef DEBUG_VALIDATION
2098 static void TmThreadDoDumpSlots(const ThreadVars *tv)
2099 {
2100  for (TmSlot *s = tv->tm_slots; s != NULL; s = s->slot_next) {
2102  SCLogNotice("tv %p: -> slot %p tm_id %d name %s",
2103  tv, s, s->tm_id, m->name);
2104  }
2105 }
2106 
2107 static void TmThreadDumpThreads(void)
2108 {
2110  for (int i = 0; i < TVT_MAX; i++) {
2111  ThreadVars *tv = tv_root[i];
2112  while (tv != NULL) {
2113  const uint32_t flags = SC_ATOMIC_GET(tv->flags);
2114  SCLogNotice("tv %p: type %u name %s tmm_flags %02X flags %X stream_pq %p",
2115  tv, tv->type, tv->name, tv->tmm_flags, flags, tv->stream_pq);
2116  if (tv->inq && tv->stream_pq == tv->inq->pq) {
2117  SCLogNotice("tv %p: stream_pq at tv->inq %u", tv, tv->inq->id);
2118  } else if (tv->stream_pq_local != NULL) {
2119  for (Packet *xp = tv->stream_pq_local->top; xp != NULL; xp = xp->next) {
2120  SCLogNotice("tv %p: ==> stream_pq_local: pq.len %u packet src %s",
2121  tv, tv->stream_pq_local->len, PktSrcToString(xp->pkt_src));
2122  }
2123  }
2124  for (Packet *xp = tv->decode_pq.top; xp != NULL; xp = xp->next) {
2125  SCLogNotice("tv %p: ==> decode_pq: decode_pq.len %u packet src %s",
2126  tv, tv->decode_pq.len, PktSrcToString(xp->pkt_src));
2127  }
2128  TmThreadDoDumpSlots(tv);
2129  tv = tv->next;
2130  }
2131  }
2134 }
2135 #endif
2136 
2137 /* Aligned to CLS to avoid false sharing between atomic ops. */
2138 typedef struct Thread_ {
2139  ThreadVars *tv; /**< threadvars structure */
2140  const char *name;
2141  int type;
2142  int in_use; /**< bool to indicate this is in use */
2143 
2144  SC_ATOMIC_DECLARE(SCTime_t, pktts); /**< current packet time of this thread
2145  * (offline mode) */
2146  SCTime_t sys_sec_stamp; /**< timestamp in real system
2147  * time when the pktts was last updated. */
2149 } __attribute__((aligned(CLS))) Thread;
2151 typedef struct Threads_ {
2152  Thread *threads;
2153  size_t threads_size;
2154  int threads_cnt;
2156 
2157 static bool thread_store_sealed = false;
2158 static Threads thread_store = { NULL, 0, 0 };
2159 static SCMutex thread_store_lock = SCMUTEX_INITIALIZER;
2160 
2162 {
2163  SCMutexLock(&thread_store_lock);
2164  DEBUG_VALIDATE_BUG_ON(thread_store_sealed);
2165  thread_store_sealed = true;
2166  SCMutexUnlock(&thread_store_lock);
2167 }
2168 
2170 {
2171  SCMutexLock(&thread_store_lock);
2172  DEBUG_VALIDATE_BUG_ON(!thread_store_sealed);
2173  thread_store_sealed = false;
2174  SCMutexUnlock(&thread_store_lock);
2175 }
2176 
2178 {
2179  SCMutexLock(&thread_store_lock);
2180  for (size_t s = 0; s < thread_store.threads_size; s++) {
2181  Thread *t = &thread_store.threads[s];
2182  if (t == NULL || t->in_use == 0)
2183  continue;
2184 
2185  SCLogNotice("Thread %"PRIuMAX", %s type %d, tv %p in_use %d",
2186  (uintmax_t)s+1, t->name, t->type, t->tv, t->in_use);
2187  if (t->tv) {
2188  ThreadVars *tv = t->tv;
2189  const uint32_t flags = SC_ATOMIC_GET(tv->flags);
2190  SCLogNotice("tv %p type %u name %s tmm_flags %02X flags %X",
2191  tv, tv->type, tv->name, tv->tmm_flags, flags);
2192  }
2193  }
2194  SCMutexUnlock(&thread_store_lock);
2195 }
2196 
2197 #define STEP 32
2198 /**
2199  * \retval id thread id, or 0 if not found
2200  */
2202 {
2203  SCMutexLock(&thread_store_lock);
2204  DEBUG_VALIDATE_BUG_ON(thread_store_sealed);
2205  if (thread_store.threads == NULL) {
2206  thread_store.threads = SCCalloc(STEP, sizeof(Thread));
2207  BUG_ON(thread_store.threads == NULL);
2208  thread_store.threads_size = STEP;
2209  }
2210 
2211  size_t s;
2212  for (s = 0; s < thread_store.threads_size; s++) {
2213  if (thread_store.threads[s].in_use == 0) {
2214  Thread *t = &thread_store.threads[s];
2215  SCSpinInit(&t->spin, 0);
2216  SCSpinLock(&t->spin);
2217  t->name = tv->name;
2218  t->type = type;
2219  t->tv = tv;
2220  t->in_use = 1;
2221  SCSpinUnlock(&t->spin);
2222 
2223  SCMutexUnlock(&thread_store_lock);
2224  return (int)(s+1);
2225  }
2226  }
2227 
2228  /* if we get here the array is completely filled */
2229  void *newmem = SCRealloc(thread_store.threads, ((thread_store.threads_size + STEP) * sizeof(Thread)));
2230  BUG_ON(newmem == NULL);
2231  thread_store.threads = newmem;
2232  memset((uint8_t *)thread_store.threads + (thread_store.threads_size * sizeof(Thread)), 0x00, STEP * sizeof(Thread));
2233 
2234  Thread *t = &thread_store.threads[thread_store.threads_size];
2235  SCSpinInit(&t->spin, 0);
2236  SCSpinLock(&t->spin);
2237  t->name = tv->name;
2238  t->type = type;
2239  t->tv = tv;
2240  t->in_use = 1;
2241  SCSpinUnlock(&t->spin);
2242 
2243  s = thread_store.threads_size;
2244  thread_store.threads_size += STEP;
2245 
2246  SCMutexUnlock(&thread_store_lock);
2247  return (int)(s+1);
2248 }
2249 #undef STEP
2250 
2251 void TmThreadsUnregisterThread(const int id)
2252 {
2253  SCMutexLock(&thread_store_lock);
2254  DEBUG_VALIDATE_BUG_ON(thread_store_sealed);
2255  if (id <= 0 || id > (int)thread_store.threads_size) {
2256  SCMutexUnlock(&thread_store_lock);
2257  return;
2258  }
2259 
2260  /* id is one higher than index */
2261  int idx = id - 1;
2262 
2263  /* reset thread_id, which serves as clearing the record */
2264  thread_store.threads[idx].in_use = 0;
2265 
2266  /* check if we have at least one registered thread left */
2267  size_t s;
2268  for (s = 0; s < thread_store.threads_size; s++) {
2269  Thread *t = &thread_store.threads[s];
2270  if (t->in_use == 1) {
2271  goto end;
2272  }
2273  }
2274 
2275  /* if we get here no threads are registered */
2276  SCFree(thread_store.threads);
2277  thread_store.threads = NULL;
2278  thread_store.threads_size = 0;
2279  thread_store.threads_cnt = 0;
2280 
2281 end:
2282  SCMutexUnlock(&thread_store_lock);
2283 }
2284 
2285 void TmThreadsSetThreadTimestamp(const int id, const SCTime_t ts)
2286 {
2287  SCTime_t now = SCTimeGetTime();
2288  int idx = id - 1;
2289  Thread *t = &thread_store.threads[idx];
2290  SCSpinLock(&t->spin);
2291  SC_ATOMIC_SET(t->pktts, ts);
2292 
2293 #ifdef DEBUG
2294  if (t->sys_sec_stamp.secs != 0) {
2295  SCTime_t tmpts = SCTIME_ADD_SECS(t->sys_sec_stamp, 3);
2296  if (SCTIME_CMP_LT(tmpts, now)) {
2297  SCLogDebug("%s: thread slept for %u secs", t->name, (uint32_t)(now.secs - tmpts.secs));
2298  }
2299  }
2300 #endif
2301 
2302  t->sys_sec_stamp = now;
2303  SCSpinUnlock(&t->spin);
2304 }
2305 
2307 {
2308  static SCTime_t nullts = SCTIME_INITIALIZER;
2309  bool ready = true;
2310  for (size_t s = 0; s < thread_store.threads_size; s++) {
2311  Thread *t = &thread_store.threads[s];
2312  if (!t->in_use) {
2313  break;
2314  }
2315  SCSpinLock(&t->spin);
2316  if (t->type != TVT_PPT) {
2317  SCSpinUnlock(&t->spin);
2318  continue;
2319  }
2320  if (SCTIME_CMP_EQ(t->sys_sec_stamp, nullts)) {
2321  ready = false;
2322  SCSpinUnlock(&t->spin);
2323  break;
2324  }
2325  SCSpinUnlock(&t->spin);
2326  }
2327  return ready;
2328 }
2329 
2331 {
2332  SCTime_t now = SCTimeGetTime();
2333  for (size_t s = 0; s < thread_store.threads_size; s++) {
2334  Thread *t = &thread_store.threads[s];
2335  if (!t->in_use) {
2336  break;
2337  }
2338  SCSpinLock(&t->spin);
2339  if (t->type != TVT_PPT) {
2340  SCSpinUnlock(&t->spin);
2341  continue;
2342  }
2343  SC_ATOMIC_SET(t->pktts, ts);
2344  t->sys_sec_stamp = now;
2345  SCSpinUnlock(&t->spin);
2346  }
2347 }
2348 
2350 {
2351  DEBUG_VALIDATE_BUG_ON(idx == 0);
2352  const int i = idx - 1;
2353  Thread *t = &thread_store.threads[i];
2354  return SC_ATOMIC_GET(t->pktts);
2355 }
2356 
2357 void TmThreadsGetMinimalTimestamp(struct timeval *ts)
2358 {
2359  struct timeval local = { 0 };
2360  static SCTime_t nullts = SCTIME_INITIALIZER;
2361  bool set = false;
2362  SCTime_t now = SCTimeGetTime();
2363 
2364  for (size_t s = 0; s < thread_store.threads_size; s++) {
2365  Thread *t = &thread_store.threads[s];
2366  if (t->in_use == 0) {
2367  break;
2368  }
2369  SCSpinLock(&t->spin);
2370  /* only packet threads set timestamps based on packets */
2371  if (t->type != TVT_PPT) {
2372  SCSpinUnlock(&t->spin);
2373  continue;
2374  }
2375  SCTime_t pktts = SC_ATOMIC_GET(t->pktts);
2376  if (SCTIME_CMP_NEQ(pktts, nullts)) {
2377  SCTime_t sys_sec_stamp = SCTIME_ADD_SECS(t->sys_sec_stamp, 5);
2378  /* ignore sleeping threads */
2379  if (SCTIME_CMP_LT(sys_sec_stamp, now)) {
2380  SCSpinUnlock(&t->spin);
2381  continue;
2382  }
2383  if (!set) {
2384  SCTIME_TO_TIMEVAL(&local, pktts);
2385  set = true;
2386  } else {
2387  if (SCTIME_CMP_LT(pktts, SCTIME_FROM_TIMEVAL(&local))) {
2388  SCTIME_TO_TIMEVAL(&local, pktts);
2389  }
2390  }
2391  }
2392  SCSpinUnlock(&t->spin);
2393  }
2394  *ts = local;
2395  SCLogDebug("ts->tv_sec %"PRIuMAX, (uintmax_t)ts->tv_sec);
2396 }
2397 
2399 {
2400  uint16_t ncpus = UtilCpuGetNumProcessorsOnline();
2401  int thread_max = TmThreadGetNbThreads(WORKER_CPU_SET);
2402  /* always create at least one thread */
2403  if (thread_max == 0)
2404  thread_max = ncpus * threading_detect_ratio;
2405  if (thread_max < 1)
2406  thread_max = 1;
2407  if (thread_max > 1024) {
2408  SCLogWarning("limited number of 'worker' threads to 1024. Wanted %d", thread_max);
2409  thread_max = 1024;
2410  }
2411  return (uint16_t)thread_max;
2412 }
2413 
2414 /** \brief inject a flow into a threads flow queue
2415  */
2416 void TmThreadsInjectFlowById(Flow *f, const int id)
2417 {
2418  if (id > 0 && id <= (int)thread_store.threads_size) {
2419  int idx = id - 1;
2420  Thread *t = &thread_store.threads[idx];
2421  ThreadVars *tv = t->tv;
2422  if (tv != NULL && tv->flow_queue != NULL) {
2424 
2425  /* wake up listening thread(s) if necessary */
2426  if (tv->inq != NULL) {
2427  SCMutexLock(&tv->inq->pq->mutex_q);
2428  SCCondSignal(&tv->inq->pq->cond_q);
2429  SCMutexUnlock(&tv->inq->pq->mutex_q);
2430  } else if (tv->break_loop) {
2431  TmThreadsCaptureBreakLoop(tv);
2432  }
2433  return;
2434  }
2435  }
2436  BUG_ON(1);
2437 }
2438 
2439 #ifdef UNITTESTS
2440 #include "util-unittest-helper.h"
2441 #include <pthread.h>
2442 
2443 static void *UnpauseHelper(void *arg)
2444 {
2445  ThreadVars *tv = (ThreadVars *)arg;
2446  /* only unpause once the caller is in the pause wait: THV_PAUSED is
2447  * set by the caller on entry, so the fixed-delay race where the
2448  * caller is descheduled past the unpause window cannot happen */
2449  while (!TmThreadsCheckFlag(tv, THV_PAUSED)) {
2450  SleepUsec(100);
2451  }
2453  return NULL;
2454 }
2455 
2456 static int TmThreadsTestWaitForUnpause01(void)
2457 {
2458  ThreadVars th_v;
2459  memset(&th_v, 0, sizeof(th_v));
2460  th_v.type = TVT_MGMT;
2461 
2462  /* killed while still in the initial pause: mgmt threads must still
2463  * run their main loop once to do final work */
2468 
2469  memset(&th_v, 0, sizeof(th_v));
2470  th_v.type = TVT_PPT;
2471 
2472  /* non-mgmt threads keep skipping the main loop */
2477 
2478  PASS;
2479 }
2480 
2481 static int TmThreadsTestWaitForUnpause02(void)
2482 {
2483  /* unpause arrives while the thread spins in the pause wait */
2484  ThreadVars th_v;
2485  memset(&th_v, 0, sizeof(th_v));
2486 
2488  pthread_t th;
2489  /* a failed create would leave THV_PAUSE set forever: fail the test
2490  * instead of spinning in the pause wait */
2491  int rc = pthread_create(&th, NULL, UnpauseHelper, &th_v);
2492  FAIL_IF(rc != 0);
2493 
2495  pthread_join(th, NULL);
2497 
2498  PASS;
2499 }
2500 
2502 {
2503  UtRegisterTest("TmThreadsTestWaitForUnpause01", TmThreadsTestWaitForUnpause01);
2504  UtRegisterTest("TmThreadsTestWaitForUnpause02", TmThreadsTestWaitForUnpause02);
2505 }
2506 
2507 #endif /* UNITTESTS */
thread_name_workers
const char * thread_name_workers
Definition: runmodes.c:67
TmThreadSetCPUAffinity
TmEcode TmThreadSetCPUAffinity(ThreadVars *tv, uint16_t cpu)
Set the thread options (cpu affinity).
Definition: tm-threads.c:832
TmModule_::cap_flags
uint8_t cap_flags
Definition: tm-modules.h:77
ThreadsAffinityType_::medprio_cpu
cpu_set_t medprio_cpu
Definition: util-affinity.h:81
TmSlot_::tm_id
int tm_id
Definition: tm-threads.h:70
SCTmThreadsSlotPacketLoopFinish
bool SCTmThreadsSlotPacketLoopFinish(ThreadVars *tv)
Definition: tm-threads.c:274
Tmq_::writer_cnt
uint16_t writer_cnt
Definition: tm-queues.h:35
ThreadVars_::flow_queue
struct FlowQueue_ * flow_queue
Definition: threadvars.h:130
TmThreadsTimeSubsysIsReady
bool TmThreadsTimeSubsysIsReady(void)
Definition: tm-threads.c:2306
TmThreadInitMC
void TmThreadInitMC(ThreadVars *tv)
Initializes the mutex and condition variables for this TV.
Definition: tm-threads.c:1789
tm-threads.h
RECEIVE_CPU_SET
@ RECEIVE_CPU_SET
Definition: util-affinity.h:57
TmThreadsSealThreads
void TmThreadsSealThreads(void)
Definition: tm-threads.c:2161
spin_lock_cnt
thread_local uint64_t spin_lock_cnt
ThreadsAffinityType_::nb_threads
uint32_t nb_threads
Definition: util-affinity.h:85
TVT_CMD
@ TVT_CMD
Definition: tm-threads-common.h:90
len
uint8_t len
Definition: app-layer-dnp3.h:2
ts
uint64_t ts
Definition: source-erf-file.c:68
TmThreadLibSpawn
TmEcode TmThreadLibSpawn(ThreadVars *tv)
Spawns a "fake" lib thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1765
TmThreadsSlotVarRun
TmEcode TmThreadsSlotVarRun(ThreadVars *tv, Packet *p, TmSlot *slot)
Separate run function so we can call it recursively.
Definition: tm-threads.c:134
TmThreadSpawn
TmEcode TmThreadSpawn(ThreadVars *tv)
Spawns a thread associated with the ThreadVars instance tv.
Definition: tm-threads.c:1710
TmThreadCreateMgmtThreadByName
ThreadVars * TmThreadCreateMgmtThreadByName(const char *name, const char *module, int mucond)
Creates and returns the TV instance for a Management thread(MGMT). This function supports only custom...
Definition: tm-threads.c:1131
TmThreadDisablePacketThreads
void TmThreadDisablePacketThreads(const uint16_t set, const uint16_t check, const uint8_t module_flags)
Disable all packet threads.
Definition: tm-threads.c:1544
ThreadVars_::iface_name
char * iface_name
Definition: threadvars.h:134
TmqhNameToID
int TmqhNameToID(const char *name)
Definition: tm-queuehandlers.c:53
threading_set_cpu_affinity
bool threading_set_cpu_affinity
Definition: runmodes.c:61
TmThreadSetupOptions
TmEcode TmThreadSetupOptions(ThreadVars *tv)
Set the thread options (cpu affinitythread). Priority should be already set by pthread_create.
Definition: tm-threads.c:873
SCTIME_CMP_NEQ
#define SCTIME_CMP_NEQ(a, b)
Definition: util-time.h:107
Tmq_::id
uint16_t id
Definition: tm-queues.h:33
ThreadVars_::name
char name[16]
Definition: threadvars.h:64
thread_name_flow_mgr
const char * thread_name_flow_mgr
Definition: runmodes.c:69
Thread_::SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(SCTime_t, pktts)
TmThreadContinueThreads
void TmThreadContinueThreads(void)
Unpauses all threads present in tv_root.
Definition: tm-threads.c:1978
CLS
#define CLS
Definition: suricata-common.h:77
TmThreadCreatePacketHandler
ThreadVars * TmThreadCreatePacketHandler(const char *name, const char *inq_name, const char *inqh_name, const char *outq_name, const char *outqh_name, const char *slots)
Creates and returns a TV instance for a Packet Processing Thread. This function doesn't support custo...
Definition: tm-threads.c:1074
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:386
SCCtrlMutexDestroy
#define SCCtrlMutexDestroy
Definition: threads-debug.h:380
AffinityGetYamlPath
char * AffinityGetYamlPath(ThreadsAffinityType *taf)
Get the YAML path for the given affinity type. The path is built using the parent name (if available)...
Definition: util-affinity.c:431
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:101
CaptureStatsSetup
void CaptureStatsSetup(ThreadVars *tv)
Definition: decode.c:1131
ThreadVars_::outctx
void * outctx
Definition: threadvars.h:103
THV_FLOW_LOOP
#define THV_FLOW_LOOP
Definition: threadvars.h:47
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
PKT_SRC_SHUTDOWN_FLUSH
@ PKT_SRC_SHUTDOWN_FLUSH
Definition: decode.h:64
rwr_lock_cnt
thread_local uint64_t rwr_lock_cnt
TmThreadsSetFlag
void TmThreadsSetFlag(ThreadVars *tv, uint32_t flag)
Set a thread flag.
Definition: tm-threads.c:102
TmThreadWaitForFlag
void TmThreadWaitForFlag(ThreadVars *tv, uint32_t flags)
Waits till the specified flag(s) is(are) set. We don't bother if the kill flag has been set or not on...
Definition: tm-threads.c:1830
PacketEnqueue
void PacketEnqueue(PacketQueue *q, Packet *p)
Definition: packet-queue.c:175
thread-callbacks.h
PacketQueue_
simple fifo queue for packets with mutex and cond Calling the mutex or triggering the cond is respons...
Definition: packet-queue.h:49
TmSlot_::SlotFunc
TmSlotFunc SlotFunc
Definition: tm-threads.h:56
THV_DEINIT
#define THV_DEINIT
Definition: threadvars.h:44
TM_ECODE_DONE
@ TM_ECODE_DONE
Definition: tm-threads-common.h:83
PKT_SRC_CAPTURE_TIMEOUT
@ PKT_SRC_CAPTURE_TIMEOUT
Definition: decode.h:62
Packet_::flags
uint32_t flags
Definition: decode.h:562
ThreadsAffinityType_::lowprio_cpu
cpu_set_t lowprio_cpu
Definition: util-affinity.h:80
threads.h
UtilAffinityGetAffinedCPUNum
uint16_t UtilAffinityGetAffinedCPUNum(ThreadsAffinityType *taf)
Return the total number of CPUs in a given affinity.
Definition: util-affinity.c:1045
Threads
Threads
Definition: tm-threads.c:2155
Tmq_::pq
PacketQueue * pq
Definition: tm-queues.h:36
Flow_
Flow data structure.
Definition: flow.h:359
TmThreadsUnsealThreads
void TmThreadsUnsealThreads(void)
Definition: tm-threads.c:2169
PRIO_HIGH
@ PRIO_HIGH
Definition: threads.h:90
ThreadVars_::t
pthread_t t
Definition: threadvars.h:58
SCSetThreadName
#define SCSetThreadName(n)
Definition: threads.h:305
PRIO_MEDIUM
@ PRIO_MEDIUM
Definition: threads.h:89
thread_name_flow_rec
const char * thread_name_flow_rec
Definition: runmodes.c:70
Tmqh_::OutHandler
void(* OutHandler)(ThreadVars *, Packet *)
Definition: tm-queuehandlers.h:40
THV_RUNNING
#define THV_RUNNING
Definition: threadvars.h:54
TmThreadCountThreadsByTmmFlags
uint32_t TmThreadCountThreadsByTmmFlags(uint8_t flags)
returns a count of all the threads that match the flag
Definition: tm-threads.c:2080
ThreadVars_::outq
Tmq * outq
Definition: threadvars.h:102
thread_name_autofp
const char * thread_name_autofp
Definition: runmodes.c:65
WORKER_CPU_SET
@ WORKER_CPU_SET
Definition: util-affinity.h:58
TVT_MAX
@ TVT_MAX
Definition: tm-threads-common.h:91
Tmq_::is_packet_pool
bool is_packet_pool
Definition: tm-queues.h:32
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
ThreadVars_::stream_pq_local
struct PacketQueue_ * stream_pq_local
Definition: threadvars.h:115
MIN
#define MIN(x, y)
Definition: suricata-common.h:413
tv_root
ThreadVars * tv_root[TVT_MAX]
Definition: tm-threads.c:83
SCSpinLock
#define SCSpinLock
Definition: threads-debug.h:236
ThreadVars_::cpu_affinity
uint16_t cpu_affinity
Definition: threadvars.h:72
TmThreadDisableReceiveThreads
void TmThreadDisableReceiveThreads(void)
Disable all threads having the specified TMs.
Definition: tm-threads.c:1392
util-privs.h
SCCtrlCondDestroy
#define SCCtrlCondDestroy
Definition: threads-debug.h:388
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:122
p
Packet * p
Definition: fuzz_dataset.c:30
TmThreadSetThreadPriority
TmEcode TmThreadSetThreadPriority(ThreadVars *tv, int prio)
Set the thread options (thread priority).
Definition: tm-threads.c:784
SCTIME_CMP_EQ
#define SCTIME_CMP_EQ(a, b)
Definition: util-time.h:108
SCDropCaps
#define SCDropCaps(...)
Definition: util-privs.h:89
m
SCMutex m
Definition: flow-hash.h:6
SleepUsec
#define SleepUsec(usec)
Definition: tm-threads.h:44
TmModule_::ThreadBusy
bool(* ThreadBusy)(ThreadVars *tv, void *thread_data)
Definition: tm-modules.h:67
THREAD_SET_PRIORITY
#define THREAD_SET_PRIORITY
Definition: threadvars.h:141
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:305
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
rww_lock_contention
thread_local uint64_t rww_lock_contention
PacketQueueNoLock_
simple fifo queue for packets
Definition: packet-queue.h:34
FlowEnqueue
void FlowEnqueue(FlowQueue *q, Flow *f)
add a flow to a queue
Definition: flow-queue.c:173
tmqh-packetpool.h
TVT_MGMT
@ TVT_MGMT
Definition: tm-threads-common.h:89
STEP
#define STEP
Definition: tm-threads.c:2197
Thread_::in_use
int in_use
Definition: tm-threads.c:2142
THV_PAUSE
#define THV_PAUSE
Definition: threadvars.h:37
TmThreadsGetThreadTime
SCTime_t TmThreadsGetThreadTime(const int idx)
Definition: tm-threads.c:2349
util-unittest-helper.h
TmModule_::PktAcqLoop
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-modules.h:58
PacketPoolInit
void PacketPoolInit(void)
Definition: tmqh-packetpool.c:235
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
Tmqh_::InHandler
Packet *(* InHandler)(ThreadVars *)
Definition: tm-queuehandlers.h:38
TmThreadsInjectFlowById
void TmThreadsInjectFlowById(Flow *f, const int id)
inject a flow into a threads flow queue
Definition: tm-threads.c:2416
ThreadVars_::cap_flags
uint8_t cap_flags
Definition: threadvars.h:79
rwr_lock_contention
thread_local uint64_t rwr_lock_contention
TmThreadsGetMinimalTimestamp
void TmThreadsGetMinimalTimestamp(struct timeval *ts)
Definition: tm-threads.c:2357
ThreadVarsAlloc
ThreadVars * ThreadVarsAlloc(void)
Allocate a new ThreadVars structure.
Definition: threadvars.c:28
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
TmThreadsProcessDecodePseudoPackets
TmEcode TmThreadsProcessDecodePseudoPackets(ThreadVars *tv, PacketQueueNoLock *decode_pq, TmSlot *slot)
Definition: tm-threads.c:115
TmModule_::ThreadDeinit
TmEcode(* ThreadDeinit)(ThreadVars *, void *)
Definition: tm-modules.h:53
PacketQueue_::mutex_q
SCMutex mutex_q
Definition: packet-queue.h:56
TmModuleGetByName
TmModule * TmModuleGetByName(const char *name)
get a tm module ptr by name
Definition: tm-modules.c:46
THV_RUNNING_DONE
#define THV_RUNNING_DONE
Definition: threadvars.h:45
spin_lock_wait_ticks
thread_local uint64_t spin_lock_wait_ticks
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1366
TmThreadsUnsetFlag
void TmThreadsUnsetFlag(ThreadVars *tv, uint32_t flag)
Unset a thread flag.
Definition: tm-threads.c:110
EXCLUSIVE_AFFINITY
@ EXCLUSIVE_AFFINITY
Definition: util-affinity.h:66
util-signal.h
Tmqh_::InShutdownHandler
void(* InShutdownHandler)(ThreadVars *)
Definition: tm-queuehandlers.h:39
SCCtrlCondInit
#define SCCtrlCondInit
Definition: threads-debug.h:384
ThreadVars_::tmm_flags
uint8_t tmm_flags
Definition: threadvars.h:77
TmThreadSetPrio
void TmThreadSetPrio(ThreadVars *tv)
Adjusting nice value for threads.
Definition: tm-threads.c:795
MIN_WAIT_TIME
#define MIN_WAIT_TIME
Definition: tm-threads.c:1600
capture-hooks.h
Thread_::tv
ThreadVars * tv
Definition: tm-threads.c:2139
TmThreadContinue
void TmThreadContinue(ThreadVars *tv)
Unpauses a thread.
Definition: tm-threads.c:1842
RunmodeIsWorkers
bool RunmodeIsWorkers(void)
Definition: runmodes.c:203
util-debug.h
TmSlot_::PktAcqLoop
TmEcode(* PktAcqLoop)(ThreadVars *, void *, void *)
Definition: tm-threads.h:57
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
TmThreadWaitOnThreadInit
TmEcode TmThreadWaitOnThreadInit(void)
Used to check if all threads have finished their initialization. On finding an un-initialized thread,...
Definition: tm-threads.c:2017
RunmodeIsAutofp
bool RunmodeIsAutofp(void)
Definition: runmodes.c:208
TmModule_::PktAcqBreakLoop
TmEcode(* PktAcqBreakLoop)(ThreadVars *, void *)
Definition: tm-modules.h:61
tv
ThreadVars * tv
Definition: tm-threads.c:2150
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
util-cpu.h
ThreadsAffinityType_::hiprio_cpu
cpu_set_t hiprio_cpu
Definition: util-affinity.h:82
TMQH_NOT_SET
@ TMQH_NOT_SET
Definition: tm-queuehandlers.h:28
ThreadVars_::tm_slots
struct TmSlot_ * tm_slots
Definition: threadvars.h:94
PacketDequeueNoLock
Packet * PacketDequeueNoLock(PacketQueueNoLock *qnl)
Definition: packet-queue.c:208
TmSlot_::Management
TmEcode(* Management)(ThreadVars *, void *)
Definition: tm-threads.h:58
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
threading_set_stack_size
uint64_t threading_set_stack_size
Definition: runmodes.c:62
PKT_PSEUDO_STREAM_END
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1313
SCTime_t::secs
uint64_t secs
Definition: util-time.h:41
TmThreadsSetThreadTimestamp
void TmThreadsSetThreadTimestamp(const int id, const SCTime_t ts)
Definition: tm-threads.c:2285
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
rww_lock_cnt
thread_local uint64_t rww_lock_cnt
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
util-affinity.h
mutex_lock_contention
thread_local uint64_t mutex_lock_contention
SCTIME_FROM_TIMEVAL
#define SCTIME_FROM_TIMEVAL(tv)
Definition: util-time.h:79
TmqGetQueueByName
Tmq * TmqGetQueueByName(const char *name)
Definition: tm-queues.c:60
TmModule_::Management
TmEcode(* Management)(ThreadVars *, void *)
Definition: tm-modules.h:69
spin_lock_contention
thread_local uint64_t spin_lock_contention
TmModule_::Func
TmEcode(* Func)(ThreadVars *, Packet *, void *)
Definition: tm-modules.h:56
TmThreadClearThreadsFamily
void TmThreadClearThreadsFamily(int family)
Definition: tm-threads.c:1685
THV_KILL
#define THV_KILL
Definition: threadvars.h:39
THV_REQ_FLOW_LOOP
#define THV_REQ_FLOW_LOOP
Definition: threadvars.h:46
TmThreadCreate
ThreadVars * TmThreadCreate(const char *name, const char *inq_name, const char *inqh_name, const char *outq_name, const char *outqh_name, const char *slots, void *(*fn_p)(void *), int mucond)
Creates and returns the TV instance for a new thread.
Definition: tm-threads.c:948
FlowQueueNew
FlowQueue * FlowQueueNew(void)
Definition: flow-queue.c:35
SCSpinUnlock
#define SCSpinUnlock
Definition: threads-debug.h:238
PktSrcToString
const char * PktSrcToString(enum PktSrcEnum pkt_src)
Definition: decode.c:894
TmThreadsUnregisterThread
void TmThreadsUnregisterThread(const int id)
Definition: tm-threads.c:2251
TmThreadsRegisterThread
int TmThreadsRegisterThread(ThreadVars *tv, const int type)
Definition: tm-threads.c:2201
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
thread-storage.h
Tmqh_::OutHandlerCtxFree
void(* OutHandlerCtxFree)(void *)
Definition: tm-queuehandlers.h:42
ThreadsAffinityType_::nocpu_warned
bool nocpu_warned
Definition: util-affinity.h:91
__attribute__
struct Thread_ __attribute__((aligned(CLS)))
Definition: tm-threads.c:2149
ThreadVars_::next
struct ThreadVars_ * next
Definition: threadvars.h:123
ThreadVars_::id
int id
Definition: threadvars.h:85
ThreadVars_::type
uint8_t type
Definition: threadvars.h:70
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:322
SCTIME_TO_TIMEVAL
#define SCTIME_TO_TIMEVAL(tv, t)
Definition: util-time.h:97
TmThreadTimeoutLoop
int TmThreadTimeoutLoop(ThreadVars *tv, TmSlot *s)
Definition: tm-threads.c:167
TmModuleGetIDForTM
int TmModuleGetIDForTM(TmModule *tm)
Given a TM Module, returns its id.
Definition: tm-modules.c:88
util-profiling.h
tv_root_lock
SCMutex tv_root_lock
Definition: tm-threads.c:86
SCReturn
#define SCReturn
Definition: util-debug.h:286
stream.h
SCCtrlMutexLock
#define SCCtrlMutexLock(mut)
Definition: threads-debug.h:377
Thread_::sys_sec_stamp
SCTime_t sys_sec_stamp
Definition: tm-threads.c:2146
TmThreadKillThreads
void TmThreadKillThreads(void)
Definition: tm-threads.c:1631
PACKET_PROFILING_TMM_END
#define PACKET_PROFILING_TMM_END(p, id)
Definition: util-profiling.h:139
source-pcap-file-helper.h
Packet_
Definition: decode.h:516
TM_FLAG_DECODE_TM
#define TM_FLAG_DECODE_TM
Definition: tm-modules.h:33
ThreadVars_::ctrl_cond
SCCtrlCondT * ctrl_cond
Definition: threadvars.h:128
CaptureHooksOnPseudoPacketCreated
void CaptureHooksOnPseudoPacketCreated(Packet *p)
Definition: capture-hooks.c:60
TmModuleGetById
TmModule * TmModuleGetById(int id)
Returns a TM Module by its id.
Definition: tm-modules.c:69
MAX_WAIT_TIME
#define MAX_WAIT_TIME
Definition: tm-threads.c:1601
ThreadsAffinityType_::cpu_set
cpu_set_t cpu_set
Definition: util-affinity.h:79
TmSlot_
Definition: tm-threads.h:53
ThreadsAffinityType_::mode_flag
uint8_t mode_flag
Definition: util-affinity.h:89
ThreadVars_::thread_setup_flags
uint8_t thread_setup_flags
Definition: threadvars.h:67
SCTime_t
Definition: util-time.h:40
TmEcode
TmEcode
Definition: tm-threads-common.h:80
name
const char * name
Definition: tm-threads.c:2151
rww_lock_wait_ticks
thread_local uint64_t rww_lock_wait_ticks
queue.h
runmodes.h
StatsSetupPrivate
int StatsSetupPrivate(StatsThreadContext *stats, const char *thread_name)
Definition: counters.c:1312
PacketQueue_::cond_q
SCCondT cond_q
Definition: packet-queue.h:57
TmThreadCreateMgmtThread
ThreadVars * TmThreadCreateMgmtThread(const char *name, void *(fn_p)(void *), int mucond)
Creates and returns the TV instance for a Management thread(MGMT). This function supports only custom...
Definition: tm-threads.c:1103
AffinityGetNextCPU
uint16_t AffinityGetNextCPU(ThreadVars *tv, ThreadsAffinityType *taf)
Definition: util-affinity.c:1008
rwr_lock_wait_ticks
thread_local uint64_t rwr_lock_wait_ticks
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
TM_FLAG_RECEIVE_TM
#define TM_FLAG_RECEIVE_TM
Definition: tm-modules.h:32
TmModule_
Definition: tm-modules.h:47
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1332
SCGetThreadIdLong
#define SCGetThreadIdLong(...)
Definition: threads.h:256
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
TVT_PPT
@ TVT_PPT
Definition: tm-threads-common.h:88
TmThreadsInitThreadsTimestamp
void TmThreadsInitThreadsTimestamp(const SCTime_t ts)
Definition: tm-threads.c:2330
ThreadVars_::stream_pq
struct PacketQueue_ * stream_pq
Definition: threadvars.h:114
TMM_FLOWWORKER
@ TMM_FLOWWORKER
Definition: tm-threads-common.h:34
tm-queuehandlers.h
SCTIME_CMP_LT
#define SCTIME_CMP_LT(a, b)
Definition: util-time.h:105
THV_PAUSED
#define THV_PAUSED
Definition: threadvars.h:38
MAX_CPU_SET
@ MAX_CPU_SET
Definition: util-affinity.h:61
THV_INIT_DONE
#define THV_INIT_DONE
Definition: threadvars.h:36
TmSlotSetFuncAppend
void TmSlotSetFuncAppend(ThreadVars *tv, TmModule *tm, const void *data)
Appends a new entry to the slots.
Definition: tm-threads.c:668
SCCtrlMutexUnlock
#define SCCtrlMutexUnlock(mut)
Definition: threads-debug.h:379
TmThreadKillThreadsFamily
void TmThreadKillThreadsFamily(int family)
Definition: tm-threads.c:1602
th_v
ThreadVars * th_v
Definition: fuzz_dataset.c:29
Thread_::type
int type
Definition: tm-threads.c:2141
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
SCCondSignal
#define SCCondSignal
Definition: threads-debug.h:140
ThreadVars_::inq
Tmq * inq
Definition: threadvars.h:88
Packet_::flow
struct Flow_ * flow
Definition: decode.h:564
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
TmThreadAppend
void TmThreadAppend(ThreadVars *tv, int type)
Appends this TV to tv_root based on its type.
Definition: tm-threads.c:1190
ThreadVars_::thread_priority
int thread_priority
Definition: threadvars.h:73
SleepMsec
#define SleepMsec(msec)
Definition: tm-threads.h:45
flags
uint8_t flags
Definition: decode-gre.h:0
THV_DEAD
#define THV_DEAD
Definition: threadvars.h:53
suricata-common.h
TmThreadSetCPU
TmEcode TmThreadSetCPU(ThreadVars *tv, uint8_t type)
Definition: tm-threads.c:841
tm-queues.h
PacketQueueNoLock_::top
struct Packet_ * top
Definition: packet-queue.h:35
thread_affinity
ThreadsAffinityType thread_affinity[MAX_CPU_SET]
Definition: util-affinity.c:37
ThreadVars_::tmqh_out
void(* tmqh_out)(struct ThreadVars_ *, struct Packet_ *)
Definition: threadvars.h:104
TmThreadsWaitForUnpause
bool TmThreadsWaitForUnpause(ThreadVars *tv)
Wait for a thread to become unpaused.
Definition: tm-threads.c:371
THV_FAILED
#define THV_FAILED
Definition: threadvars.h:40
MANAGEMENT_CPU_SET
@ MANAGEMENT_CPU_SET
Definition: util-affinity.h:60
ThreadVars_::break_loop
bool break_loop
Definition: threadvars.h:131
ThreadVars_::tm_flowworker
struct TmSlot_ * tm_flowworker
Definition: threadvars.h:99
TmThreadGetNbThreads
int TmThreadGetNbThreads(uint8_t type)
Definition: tm-threads.c:857
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:241
StatsSyncCounters
void StatsSyncCounters(StatsThreadContext *stats)
Definition: counters.c:476
PacketQueue_::len
uint32_t len
Definition: packet-queue.h:52
TmSlot_::SlotThreadInit
TmEcode(* SlotThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-threads.h:72
sys_sec_stamp
SCTime_t sys_sec_stamp
Definition: tm-threads.c:2157
TmModule_::ThreadInit
TmEcode(* ThreadInit)(ThreadVars *, const void *, void **)
Definition: tm-modules.h:51
TmSlot_::slot_initdata
const void * slot_initdata
Definition: tm-threads.h:77
FatalError
#define FatalError(...)
Definition: util-debug.h:517
TmThreadsGetWorkerThreadMax
uint16_t TmThreadsGetWorkerThreadMax(void)
Definition: tm-threads.c:2398
ThreadVars_::printable_name
char * printable_name
Definition: threadvars.h:65
TmThreadCreateCmdThreadByName
ThreadVars * TmThreadCreateCmdThreadByName(const char *name, const char *module, int mucond)
Creates and returns the TV instance for a Command thread (CMD). This function supports only custom sl...
Definition: tm-threads.c:1164
THREAD_SET_AFFTYPE
#define THREAD_SET_AFFTYPE
Definition: threadvars.h:142
TmModule_::ThreadExitPrintStats
void(* ThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-modules.h:52
PacketDequeue
Packet * PacketDequeue(PacketQueue *q)
Definition: packet-queue.c:216
threadvars.h
util-validate.h
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:260
SCSpinInit
#define SCSpinInit
Definition: threads-debug.h:239
SCThreadRunInitCallbacks
void SCThreadRunInitCallbacks(ThreadVars *tv)
Definition: thread-callbacks.c:48
ThreadsAffinityType_
Definition: util-affinity.h:72
mutex_lock_wait_ticks
thread_local uint64_t mutex_lock_wait_ticks
PacketQueueNoLock_::len
uint32_t len
Definition: packet-queue.h:37
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
Packet_::next
struct Packet_ * next
Definition: decode.h:648
TmSlot_::tm_flags
uint8_t tm_flags
Definition: tm-threads.h:67
Thread_::name
const char * name
Definition: tm-threads.c:2140
PACKET_PROFILING_TMM_START
#define PACKET_PROFILING_TMM_START(p, id)
Definition: util-profiling.h:131
PacketQueue_::top
struct Packet_ * top
Definition: packet-queue.h:50
ThreadVars_::tmqh_in
struct Packet_ *(* tmqh_in)(struct ThreadVars_ *)
Definition: threadvars.h:89
Tmqh_::OutHandlerCtxSetup
void *(* OutHandlerCtxSetup)(const char *)
Definition: tm-queuehandlers.h:41
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
TmqCreateQueue
Tmq * TmqCreateQueue(const char *name)
SCFree
#define SCFree(p)
Definition: util-mem.h:61
TmSlot_::SlotThreadDeinit
TmEcode(* SlotThreadDeinit)(ThreadVars *, void *)
Definition: tm-threads.h:74
thread_name_verdict
const char * thread_name_verdict
Definition: runmodes.c:68
TmSlot_::SlotThreadExitPrintStats
void(* SlotThreadExitPrintStats)(ThreadVars *, void *)
Definition: tm-threads.h:73
TmqhGetQueueHandlerByID
Tmqh * TmqhGetQueueHandlerByID(const int id)
Definition: tm-queuehandlers.c:77
SC_ATOMIC_INITPTR
#define SC_ATOMIC_INITPTR(name)
Definition: util-atomic.h:317
TmThreadsRegisterTests
void TmThreadsRegisterTests(void)
Definition: tm-threads.c:2501
ThreadVars_::outq_id
uint8_t outq_id
Definition: threadvars.h:82
ThreadVars_::decode_pq
PacketQueueNoLock decode_pq
Definition: threadvars.h:110
SCSpinlock
#define SCSpinlock
Definition: threads-debug.h:235
SCCtrlMutexInit
#define SCCtrlMutexInit(mut, mutattr)
Definition: threads-debug.h:376
ThreadVarsFree
void ThreadVarsFree(ThreadVars *tv)
Free a ThreadVars structure.
Definition: threadvars.c:42
suricata.h
EngineDone
void EngineDone(void)
Used to indicate that the current task is done.
Definition: suricata.c:513
THREAD_SET_AFFINITY
#define THREAD_SET_AFFINITY
Definition: threadvars.h:140
Tmq_
Definition: tm-queues.h:30
Thread_::spin
SCSpinlock spin
Definition: tm-threads.c:2148
TmThreadWaitOnThreadRunning
TmEcode TmThreadWaitOnThreadRunning(void)
Waits for all threads to be in a running state.
Definition: tm-threads.c:1909
TmThreadsListThreads
void TmThreadsListThreads(void)
Definition: tm-threads.c:2177
likely
#define likely(expr)
Definition: util-optimize.h:32
TmSlot_::slot_next
struct TmSlot_ * slot_next
Definition: tm-threads.h:62
TmThreadCheckThreadState
void TmThreadCheckThreadState(void)
Used to check the thread for certain conditions of failure.
Definition: tm-threads.c:1994
type
int type
Definition: tm-threads.c:2152
ThreadVars_::ctrl_mutex
SCCtrlMutex * ctrl_mutex
Definition: threadvars.h:127
ThreadVars_::inq_id
uint8_t inq_id
Definition: threadvars.h:81
ThreadsAffinityType_::prio
int prio
Definition: util-affinity.h:84
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
FindAffinityByInterface
ThreadsAffinityType * FindAffinityByInterface(ThreadsAffinityType *parent, const char *interface_name)
Definition: util-affinity.c:112
UtilCpuGetNumProcessorsOnline
uint16_t UtilCpuGetNumProcessorsOnline(void)
Get the number of cpus online in the system.
Definition: util-cpu.c:108
PacketPoolDestroy
void PacketPoolDestroy(void)
Definition: tmqh-packetpool.c:265
mutex_lock_cnt
thread_local uint64_t mutex_lock_cnt
TmThreadsCheckFlag
int TmThreadsCheckFlag(ThreadVars *tv, uint32_t flag)
Check if a thread flag is set.
Definition: tm-threads.c:94
SCTIME_INITIALIZER
#define SCTIME_INITIALIZER
Definition: util-time.h:51
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:250
SCTIME_ADD_SECS
#define SCTIME_ADD_SECS(ts, s)
Definition: util-time.h:64
TmqhGetQueueHandlerByName
Tmqh * TmqhGetQueueHandlerByName(const char *name)
Definition: tm-queuehandlers.c:65
THV_CLOSED
#define THV_CLOSED
Definition: threadvars.h:41
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
Thread_
Definition: tm-threads.c:2138
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:120
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
SCMutexDestroy
#define SCMutexDestroy
Definition: threads-debug.h:121
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1428
PRIO_LOW
@ PRIO_LOW
Definition: threads.h:88
Tmq_::reader_cnt
uint16_t reader_cnt
Definition: tm-queues.h:34
ThreadVars_::tm_func
void *(* tm_func)(void *)
Definition: threadvars.h:62
SCMutex
#define SCMutex
Definition: threads-debug.h:114
PacketGetFromQueueOrAlloc
Packet * PacketGetFromQueueOrAlloc(void)
Get a packet. We try to get a packet from the packetpool first, but if that is empty we alloc a packe...
Definition: decode.c:298
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
TmModule_::flags
uint8_t flags
Definition: tm-modules.h:80
threading_detect_ratio
float threading_detect_ratio
Definition: runmodes.c:953
SC_ATOMIC_AND
#define SC_ATOMIC_AND(name, val)
Bitwise AND a value to our atomic variable.
Definition: util-atomic.h:359
Tmqh_
Definition: tm-queuehandlers.h:36
SCThreadFreeStorage
void SCThreadFreeStorage(ThreadVars *tv)
Definition: thread-storage.c:44
suricata_ctl_flags
volatile uint8_t suricata_ctl_flags
Definition: suricata.c:177
SC_ATOMIC_OR
#define SC_ATOMIC_OR(name, val)
Bitwise OR a value to our atomic variable.
Definition: util-atomic.h:350
f
Flow f
Definition: fuzz_dataset.c:32