diff --git a/petersons-linux/build.sh b/petersons-linux/build.sh new file mode 100644 index 0000000..fe0c25d --- /dev/null +++ b/petersons-linux/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +gcc -o main -pthread main.c +./main \ No newline at end of file diff --git a/petersons-linux/main.c b/petersons-linux/main.c new file mode 100644 index 0000000..6627021 --- /dev/null +++ b/petersons-linux/main.c @@ -0,0 +1,82 @@ +#include +#include +#include + +#define BUFFER_SIZE 10 + +#if !defined(true) && !defined(false) + #define true 1 + #define false 0 +#endif + +volatile int counter = -1; +volatile int buffer[BUFFER_SIZE]; + +volatile int turn; +volatile int flag[2]; + +void * produce(void* data) { + srand (time(NULL)); + while (true) + { + flag[0] = true; + turn = 1; + while (flag[1] && turn == 1); + if (counter == BUFFER_SIZE - 1) // make sure the buffer doesn't overflow + { + flag[0] = false; + sleep(5); + continue; + } + + + buffer[counter + 1] = rand() % 20 + 1; // yes I know rand is not thread safe - I just need a way to demonstrate a producing/consuming problem - using the same number doesn't help. + printf("PRODUCER value = %i counter = %i\n", buffer[counter + 1], counter + 1); + counter++; + flag[0] = false; + + } +} + +void * consume(void* data) { + int i = 0; + while(true) + { + flag[1] = true; + turn = 0; + while (flag[0] && turn == 0); + if (counter == -1) // producer hasn't produced - make sure there is content to consume + { + flag[1] = false; + continue; + } + if (buffer[counter] == 0) + { + for(i = 0; i < BUFFER_SIZE; i++) + printf("%i\n", buffer[i]); + printf("Attempting to consume an element that was already consumed counter = %i\n", counter); + exit(1); + } + printf("CONSUMER value = %i counter = %i\n", buffer[counter], counter); + buffer[counter] = 0; + counter--; + flag[1] = false; + sleep(1); + } +} + +int main() { + int i; + pthread_t thread1, thread2; + int iret1, iret2; + for(i = 0; i < BUFFER_SIZE; i++) + buffer[i] = -1; + flag[0] = true; + flag[1] = true; + + iret1 = pthread_create( &thread1, NULL, produce, NULL); + iret2 = pthread_create( &thread2, NULL, consume, NULL); + + pthread_join( thread1, NULL); + pthread_join( thread2, NULL); +} \ No newline at end of file diff --git a/petersons-windows/main.c b/petersons-windows/main.c index 148b674..09fc8b0 100644 --- a/petersons-windows/main.c +++ b/petersons-windows/main.c @@ -25,8 +25,9 @@ DWORD WINAPI produce(void* data) { while (flag[1] && turn == 1); if (counter == BUFFER_SIZE - 1) // make sure the buffer doesn't overflow { - continue; flag[0] = false; + Sleep(500); // Let the producer catch up + continue; } @@ -39,6 +40,7 @@ DWORD WINAPI produce(void* data) { } DWORD WINAPI consume(void* data) { + int i = 0; while(true) { flag[1] = true; @@ -51,14 +53,16 @@ DWORD WINAPI consume(void* data) { } if (buffer[counter] == 0) { - printf("%i\n", buffer[counter]); + for(i = 0; i < BUFFER_SIZE; i++) + printf("%i\n", buffer[i]); printf("Attempting to consume an element that was already consumed counter = %i\n", counter); exit(1); } printf("CONSUMER value = %i counter = %i\n", buffer[counter], counter); - counter--; buffer[counter] = 0; + counter--; flag[1] = false; + Sleep(50); } } @@ -72,6 +76,6 @@ int main() { thread1 = CreateThread(NULL, 0, produce, NULL, 0, NULL); thread2 = CreateThread(NULL, 0, consume, NULL, 0, NULL); - WaitForSingleObject(thread1, 50); - WaitForSingleObject(thread2, 50); + WaitForSingleObject(thread1, INFINITE ); + WaitForSingleObject(thread2, INFINITE ); } \ No newline at end of file diff --git a/racecondition-linux/build.sh b/racecondition-linux/build.sh index e2164d8..fe0c25d 100644 --- a/racecondition-linux/build.sh +++ b/racecondition-linux/build.sh @@ -1,4 +1,4 @@ #!/bin/bash -gcc -o main main.c +gcc -o main -pthread main.c ./main \ No newline at end of file diff --git a/racecondition-windows/main.c b/racecondition-windows/main.c index dee3711..d26343d 100644 --- a/racecondition-windows/main.c +++ b/racecondition-windows/main.c @@ -21,12 +21,14 @@ DWORD WINAPI produce(void* data) { } DWORD WINAPI consume(void* data) { + int i = 0; while(1) { while (counter == -1); if (buffer[counter] == 0) { - printf("%i\n", buffer[counter]); + for(i = 0; i < BUFFER_SIZE; i++) + printf("%i\n", buffer[i]); printf("Attempting to consume an element that was already consumed counter = %i\n", counter); exit(1); } diff --git a/thread-linux/build.sh b/thread-linux/build.sh index e2164d8..fe0c25d 100644 --- a/thread-linux/build.sh +++ b/thread-linux/build.sh @@ -1,4 +1,4 @@ #!/bin/bash -gcc -o main main.c +gcc -o main -pthread main.c ./main \ No newline at end of file diff --git a/vcbuild.bat b/vcbuild.bat index de94548..6259e33 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -13,5 +13,5 @@ if exist "c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" ( goto compile ) :compile -cl.exe %1.c +cl.exe /D "WIN32" /D "_WINDOWS" %1.c kernel32.lib user32.lib del %1.obj \ No newline at end of file