/* pokemontest.c Test for correct working of the pokemon problem The functions in this file are helper functions to help you identify problems in your pokemon solutions. This is a debug tool. If there are special cases that you would want to add to test your solution you could add them here. The pokemon tester uses a huge buffer with a sliding window with checks done at places - end of buffer and end of window. The solution uses the window size to be exactly half the buffer size. Usage: 1. Replace the printfs in your consumer code by calls to consume_pokemon_card(). 2. Replace the printfs in your producer code by calls to pokemon_card_production_alert(). Why: Printf's have to be removed to test pre-emption for your solution. With printfs' lying around in your code NT will not let application level pre-emption. Output: 1. If everything is working fine then you will see 'Test in progress...' message periodically. 2. If things are not working fine then the code will give you the reason for failure and exit. */ #include #include "synch.h" #define empty -1 #define full 1 #define consumed 0 /*Global variable initializations done here */ int bufsize = 10*10000; /*NOTE: window size should be atleast half of the buffer size*/ int windowsize = 5*10000; short int bufferfull = 0; char buf[10*10000]; semaphore_t semb; short int initbuff = 0; /* New functions to check pokemon correctness */ void initialize_pokemon_buffer() { int i; for(i = 0; i < bufsize; i++) buf[i] = empty; //initialize semaphore on buf semb = semaphore_create(); semaphore_initialize(semb, 1); } void window_test(int checkpoint, int num) { int pos = 0; int i; /* have to skip the test the first time the buf is being filled*/ if(checkpoint == bufsize - 1) bufferfull = 1; if(bufferfull == 0) return; /*check values in the window and reset slot values to -1 as you move ahead The window size here is set to half the buf size. You can go to the global variables and change it to suit your need*/ for(i = 1; i <= windowsize; i++) { pos = (checkpoint + i) % bufsize; if(buf[pos] == full) { printf("Illegal: Card number %d at position %d was not consumed\n", num, pos); exit(0); } buf[pos] = -1; } return; } /*takes 2 arguments : the card number of the card generated and the position in the store which is being filled. the function will exit if any faulty behavior is found giving the reason for failure. Usage: Call this function just before printing the card consumption message in your pokemon consumer function. If possible avoid printing a lot of your own messages and use this function.*/ void consume_pokemon_card(int cardnum, int store_pos) { int pos = cardnum % bufsize; if(initbuff == 0) { initialize_pokemon_buffer(); initbuff = 1; } //to synchronize access to buf semaphore_P(semb); if(buf[pos] == 0) { printf("Illegal: Trying to consume already consumed Card %d from buffer position %d\n", cardnum, store_pos); exit(0); } if(buf[pos] == -1) { printf("Illegal: Trying to consume Card %d from empty store front %d\n", cardnum, store_pos); exit(0); } if((pos % 5000) == 0) printf("Test in progress....\n"); buf[pos] = 0; semaphore_V(semb); } /*takes 2 arguments : the card number of the card generated and the position in the store which is being filled. the function will exit if any faulty behavior is found giving the reason for failure. Usage: Call this function just before printing the card production message in your pokemon producer function. If possible avoid printing a lot of your own messages and use this function.*/ void pokemon_card_production_alert(int cardnum, int store_pos) { int pos = cardnum % bufsize; //window test is done at 2 positions in the buf if(initbuff == 0) { initialize_pokemon_buffer(); initbuff = 1; } semaphore_P(semb); if(pos == bufsize-1 || pos == windowsize-1) window_test(pos, cardnum); if(buf[pos] == 1) { printf("Illegal: Trying to generate same Card %d and place it in an occupied store front %d\n", cardnum, store_pos); exit(1); } else buf[pos] = 1; if((pos % 5000) == 0) printf("Test in progress....\n"); semaphore_V(semb); }