forked from OSchip/llvm-project
139 lines
2.9 KiB
C++
139 lines
2.9 KiB
C++
//===-- main.c --------------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import <pthread.h>
|
|
|
|
long my_global;
|
|
|
|
void *Thread1(void *arg) {
|
|
my_global = 42;
|
|
return NULL;
|
|
}
|
|
|
|
void *Thread2(void *arg) {
|
|
my_global = 144;
|
|
return NULL;
|
|
}
|
|
|
|
void TestDataRace1() {
|
|
pthread_t t1, t2;
|
|
pthread_create(&t1, NULL, Thread1, NULL);
|
|
pthread_create(&t2, NULL, Thread2, NULL);
|
|
|
|
pthread_join(t1, NULL);
|
|
pthread_join(t2, NULL);
|
|
}
|
|
|
|
void TestInvalidMutex() {
|
|
pthread_mutex_t m = {0};
|
|
pthread_mutex_lock(&m);
|
|
|
|
pthread_mutex_init(&m, NULL);
|
|
pthread_mutex_lock(&m);
|
|
pthread_mutex_unlock(&m);
|
|
pthread_mutex_destroy(&m);
|
|
pthread_mutex_lock(&m);
|
|
}
|
|
|
|
void TestMutexWrongLock() {
|
|
pthread_mutex_t m = {0};
|
|
pthread_mutex_init(&m, NULL);
|
|
pthread_mutex_unlock(&m);
|
|
}
|
|
|
|
long some_global;
|
|
|
|
void TestDataRaceBlocks1() {
|
|
dispatch_queue_t q = dispatch_queue_create("my.queue", DISPATCH_QUEUE_CONCURRENT);
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
dispatch_async(q, ^{
|
|
some_global++; // race 1
|
|
|
|
usleep(100000); // force the blocks to be on different threads
|
|
});
|
|
}
|
|
|
|
usleep(100000);
|
|
dispatch_barrier_sync(q, ^{ });
|
|
}
|
|
|
|
void TestDataRaceBlocks2() {
|
|
dispatch_queue_t q = dispatch_queue_create("my.queue2", DISPATCH_QUEUE_CONCURRENT);
|
|
|
|
char *c;
|
|
|
|
c = malloc((rand() % 1000) + 10);
|
|
for (int i = 0; i < 2; i++) {
|
|
dispatch_async(q, ^{
|
|
c[0] = 'x'; // race 2
|
|
fprintf(stderr, "tid: %p\n", pthread_self());
|
|
usleep(100000); // force the blocks to be on different threads
|
|
});
|
|
}
|
|
dispatch_barrier_sync(q, ^{ });
|
|
|
|
free(c);
|
|
}
|
|
|
|
void TestUseAfterFree() {
|
|
char *c;
|
|
|
|
c = malloc((rand() % 1000) + 10);
|
|
free(c);
|
|
c[0] = 'x';
|
|
}
|
|
|
|
void TestRacePipe() {
|
|
dispatch_queue_t q = dispatch_queue_create("my.queue3", DISPATCH_QUEUE_CONCURRENT);
|
|
|
|
int a[2];
|
|
pipe(a);
|
|
int fd = a[0];
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
dispatch_async(q, ^{
|
|
write(fd, "abc", 3);
|
|
usleep(100000); // force the blocks to be on different threads
|
|
});
|
|
dispatch_async(q, ^{
|
|
close(fd);
|
|
usleep(100000);
|
|
});
|
|
}
|
|
|
|
dispatch_barrier_sync(q, ^{ });
|
|
}
|
|
|
|
void TestThreadLeak() {
|
|
pthread_t t1;
|
|
pthread_create(&t1, NULL, Thread1, NULL);
|
|
}
|
|
|
|
int main(int argc, const char * argv[]) {
|
|
TestDataRace1();
|
|
|
|
TestInvalidMutex();
|
|
|
|
TestMutexWrongLock();
|
|
|
|
TestDataRaceBlocks1();
|
|
|
|
TestDataRaceBlocks2();
|
|
|
|
TestUseAfterFree();
|
|
|
|
TestRacePipe();
|
|
|
|
TestThreadLeak();
|
|
|
|
return 0;
|
|
}
|