16db8c59fSFangrui Song // Check that when forking in basic logging mode, we get the different tids for child and parent
26db8c59fSFangrui Song // RUN: %clangxx_xray -g -std=c++11 %s -o %t
36db8c59fSFangrui Song // RUN: rm -f fork-basic-logging-test-*
46db8c59fSFangrui Song // RUN: XRAY_OPTIONS="patch_premain=true xray_logfile_base=fork-basic-logging-test- \
56db8c59fSFangrui Song // RUN:     xray_mode=xray-basic verbosity=1 xray_naive_log_func_duration_threshold_us=0" \
66db8c59fSFangrui Song // RUN:     %run %t 2>&1 | FileCheck %s
76db8c59fSFangrui Song // RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
86db8c59fSFangrui Song // RUN:     "`ls -S fork-basic-logging-test-* | head -1`" \
96db8c59fSFangrui Song // RUN:     | FileCheck %s --check-prefix=TRACE
106db8c59fSFangrui Song 
116db8c59fSFangrui Song // REQUIRES: x86_64-target-arch
126db8c59fSFangrui Song // REQUIRES: built-in-llvm-tree
136db8c59fSFangrui Song 
146db8c59fSFangrui Song // Not ported.
156db8c59fSFangrui Song // UNSUPPORTED: netbsd
166db8c59fSFangrui Song 
176db8c59fSFangrui Song #include "xray/xray_log_interface.h"
186db8c59fSFangrui Song #include <stdio.h>
196db8c59fSFangrui Song #include <unistd.h>
206db8c59fSFangrui Song #include <stdint.h>
21*72cb9db5SDavid Carlier #if defined(__linux__)
226db8c59fSFangrui Song #include <sys/syscall.h>
23*72cb9db5SDavid Carlier #elif defined(__FreeBSD__)
24*72cb9db5SDavid Carlier #include <sys/thr.h>
25*72cb9db5SDavid Carlier #endif
266db8c59fSFangrui Song 
276db8c59fSFangrui Song //modified from sanitizer
286db8c59fSFangrui Song 
syscall_gettid()296db8c59fSFangrui Song static uintptr_t syscall_gettid() {
306db8c59fSFangrui Song   uint64_t retval;
31*72cb9db5SDavid Carlier #ifdef __linux__
326db8c59fSFangrui Song   asm volatile("syscall" : "=a"(retval) : "a"(__NR_gettid) : "rcx", "r11",
336db8c59fSFangrui Song                "memory", "cc");
34*72cb9db5SDavid Carlier #else
35*72cb9db5SDavid Carlier   long t;
36*72cb9db5SDavid Carlier   thr_self(&t);
37*72cb9db5SDavid Carlier   retval = static_cast<uint64_t>(t);
38*72cb9db5SDavid Carlier #endif
396db8c59fSFangrui Song   return retval;
406db8c59fSFangrui Song }
416db8c59fSFangrui Song 
426db8c59fSFangrui Song /////////////
436db8c59fSFangrui Song 
446db8c59fSFangrui Song static uint64_t parent_tid;
456db8c59fSFangrui Song 
466db8c59fSFangrui Song [[clang::xray_always_instrument]]
log_syscall_gettid()476db8c59fSFangrui Song uint64_t __attribute__((noinline)) log_syscall_gettid()
486db8c59fSFangrui Song {
496db8c59fSFangrui Song 	//don't optimize this function away
506db8c59fSFangrui Song 	uint64_t tid = syscall_gettid();
516db8c59fSFangrui Song 	printf("Logging tid %lu\n", tid);
526db8c59fSFangrui Song 	return tid;
536db8c59fSFangrui Song }
546db8c59fSFangrui Song 
556db8c59fSFangrui Song [[clang::xray_always_instrument, clang::xray_log_args(1)]]
print_parent_tid(uint64_t tid)566db8c59fSFangrui Song void __attribute__((noinline)) print_parent_tid(uint64_t tid)
576db8c59fSFangrui Song {
586db8c59fSFangrui Song 	printf("Parent with tid %lu", tid);
596db8c59fSFangrui Song }
606db8c59fSFangrui Song 
616db8c59fSFangrui Song [[clang::xray_always_instrument, clang::xray_log_args(1)]]
print_child_tid(uint64_t tid)626db8c59fSFangrui Song void __attribute__((noinline)) print_child_tid(uint64_t tid)
636db8c59fSFangrui Song {
646db8c59fSFangrui Song 	printf("Child with tid %lu", tid);
656db8c59fSFangrui Song }
666db8c59fSFangrui Song 
print_parent_or_child()676db8c59fSFangrui Song [[clang::xray_always_instrument]] void __attribute__((noinline)) print_parent_or_child()
686db8c59fSFangrui Song {
696db8c59fSFangrui Song 	uint64_t tid = syscall_gettid();
706db8c59fSFangrui Song 	if(tid == parent_tid)
716db8c59fSFangrui Song 	{
726db8c59fSFangrui Song 		print_parent_tid(tid);
736db8c59fSFangrui Song 	}
746db8c59fSFangrui Song 	else
756db8c59fSFangrui Song 	{
766db8c59fSFangrui Song 		print_child_tid(tid);
776db8c59fSFangrui Song 	}
786db8c59fSFangrui Song }
796db8c59fSFangrui Song 
main()806db8c59fSFangrui Song int main()
816db8c59fSFangrui Song {
826db8c59fSFangrui Song 	parent_tid = log_syscall_gettid();
836db8c59fSFangrui Song 	if(fork())
846db8c59fSFangrui Song 	{
856db8c59fSFangrui Song 		print_parent_or_child();
866db8c59fSFangrui Song   		// CHECK-DAG: Parent with tid
876db8c59fSFangrui Song 	}
886db8c59fSFangrui Song 	else
896db8c59fSFangrui Song 	{
906db8c59fSFangrui Song 		print_parent_or_child();
916db8c59fSFangrui Song   		// CHECK-DAG: Child with tid
926db8c59fSFangrui Song 	}
936db8c59fSFangrui Song 	return 0;
946db8c59fSFangrui Song }
956db8c59fSFangrui Song 
966db8c59fSFangrui Song // Make sure we know which thread is the parent process
976db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[LSGT:[0-9]+]], function: {{.*log_syscall_gettid.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS1:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
986db8c59fSFangrui Song 
996db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[PPOC:[0-9]+]], function: {{.*print_parent_or_child.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS1]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
1006db8c59fSFangrui Song //
1016db8c59fSFangrui Song // The parent will print its pid
1026db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[PPTARG:[0-9]+]], function: {{.*print_parent_tid.*}}, args: [ [[THREAD1]] ], cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS1]], kind: function-enter-arg, tsc: {{[0-9]+}}, data: '' }
1036db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[PPTARG]], function: {{.*print_parent_tid.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS1]], kind: function-exit, tsc: {{[0-9]+}}, data: '' }
1046db8c59fSFangrui Song //
1056db8c59fSFangrui Song // TRACE-DAG  - { type: 0, func-id: [[PPOC]], function: {{.*print_parent_or_child.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS1]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}}, data: '' }
1066db8c59fSFangrui Song 
1076db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[PPOC]], function: {{.*print_parent_or_child.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS2:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
1086db8c59fSFangrui Song //
1096db8c59fSFangrui Song // The child will print its pid
1106db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[PCTARG:[0-9]+]], function: {{.*print_child_tid.*}}, args: [ [[THREAD2]] ], cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS2]], kind: function-enter-arg, tsc: {{[0-9]+}}, data: '' }
1116db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[PCTARG]], function: {{.*print_child_tid.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS2]], kind: function-exit, tsc: {{[0-9]+}}, data: '' }
1126db8c59fSFangrui Song //
1136db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[PPOC]], function: {{.*print_parent_or_child.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS2]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}}, data: '' }
114