blob: eb797e84c1369f9f76d356e6d051c2da35d164a3 [file] [log] [blame]
/*
* Copyright (c) 2012 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <assert.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
/* This is here so that we can set a breakpoint on it. */
void foo(void) {
}
/* This is here so that we can set a breakpoint on it. */
void bar(void) {
}
void *f1(void *arg) {
foo();
bar();
return NULL;
}
void *f2(void *arg) {
bar();
foo();
return NULL;
}
void test_break_continue_thread(void) {
pthread_t t1;
pthread_t t2;
int rc;
rc = pthread_create(&t1, NULL, f1, NULL);
assert(rc == 0);
rc = pthread_create(&t2, NULL, f2, NULL);
assert(rc == 0);
rc = pthread_join(t1, NULL);
assert(rc == 0);
rc = pthread_join(t2, NULL);
assert(rc == 0);
}
/* This is here so that we can set a breakpoint on it. */
void inside_f3(void) {
}
void *f3(void *arg) {
/*
* Wait until 'test_syscall_thread' thread runs 'pthread_join' and blocks
* inside a syscall, then give GDB a chance to break.
*/
int rc;
rc = usleep(100000); /* Sleep for 0.1 seconds */
assert(rc == 0);
inside_f3();
return NULL;
}
/*
* Test that we have a meaningful backtrace when stopped in syscall.
*
* The problem here is to stop while executing a syscall:
* - we can't set breakpoint inside a syscall, as we can't set breakpoints on
* trusted code;
* - we can't send interrupt (ctrl+c) using GDB/MI, as this requires support
* for background execution we don't have;
* Instead, we use an additional thread that waits until main thread is blocked
* in syscall and then calls a function to hit a breakpoint.
*/
void test_syscall_thread(void) {
pthread_t t;
int rc;
rc = pthread_create(&t, NULL, f3, NULL);
assert(rc == 0);
/* Run a syscall to be suspended by 'f3' thread. */
rc = pthread_join(t, NULL);
assert(rc == 0);
}
int main(int argc, char **argv) {
assert(argc >= 2);
if (strcmp(argv[1], "break_continue_thread") == 0) {
test_break_continue_thread();
return 0;
}
if (strcmp(argv[1], "syscall_thread") == 0) {
test_syscall_thread();
return 0;
}
return 1;
}