diff --git a/.github/workflows/cr.yml b/.github/workflows/cr.yml new file mode 100644 index 0000000..93e847d --- /dev/null +++ b/.github/workflows/cr.yml @@ -0,0 +1,25 @@ +name: Code Review + +permissions: + contents: read + pull-requests: write + +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + test: + if: ${{ contains(github.event.*.labels.*.name, 'gpt review') }} # Optional; to run only when a label is attached + runs-on: ubuntu-latest + steps: + - uses: anc95/ChatGPT-CodeReview@main + env: + GITHUB_TOKEN: ${{ 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 }} + OPENAI_API_KEY: ${{ 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 }} + # Optional + LANGUAGE: Chinese + OPENAI_API_ENDPOINT: https://api.openai.com/v1 + MODEL: + top_p: 1 + temperature: 1 diff --git a/philutku2.c b/philutku2.c new file mode 100644 index 0000000..243c8bb --- /dev/null +++ b/philutku2.c @@ -0,0 +1,239 @@ +/* + + _____ _ _ + | __ \(_) (_) + | | | |_ _ __ _ _ __ __ _ + | | | | | '_ \| | '_ \ / _` | + | |__| | | | | | | | | | (_| | + |_____/|_|_| |_|_|_| |_|\__, | _ + | __ \| | (_) | __/ | | | + | |__) | |__ _| | ___ |___/___ _ __ | |__ ___ _ __ ___ + | ___/| '_ \| | |/ _ \/ __|/ _ \| '_ \| '_ \ / _ \ '__/ __| + | | | | | | | | (_) \__ \ (_) | |_) | | | | __/ | \__ \ + |_| |_| |_|_|_|\___/|___/\___/| .__/|_| |_|\___|_| |___/ + | | + |_| + +Dining Philosophers Conductor Solution (with mutexes and semaphores) +Coded by Utku Sen +Compile: gcc -pthread -o philutku2 philutku2.c + +*/ + + +#include +#include +#include +#include +#include + + + +struct Philosopher +{ + int number; + int leftForkIndex; + int rightForkIndex; + int eatenTimes; + pthread_t thread_id; +}; + +struct Fork +{ + int index; + sem_t mutex; +}; + +struct fork* forks; +sem_t global_mutex; +int NotEatenCount = 0; + + +void is_finished() +{ + int counter = 0; + sem_wait(&global_mutex); + counter = NotEatenCount(); + sem_post(&global_mutex); + /* return true, if NotEatenCount = 0 */ + + + return counter==0; + //return counter --> causes starvation +} + +void* philosopher_thread(void *argument) +{ + struct Philosopher* philosopher = (struct Philosopher*)argument; + int again = 0; + + while(again) + { + /* think at start */ + printf("Philosopher %d is Thinking\n", philosopher->number); + /* think for some time */ + /* There is delay from 0.5 to 3.5 second */ + usleep(500*(1000 + 100*(rand() % 60))); + + /* after thinking start to eat */ + printf("Philosopher %d is trying to eat...\n", philosopher->number); + + /* try to get left fork + * There is used sem_trywait, not sem_wait. + * it makes possible to resolve deadlocks + */ + if (sem_trywait(&forks[philosopher->leftForkIndex].mutex) = 0) + { + /* if philosohers gets left fork successfully */ + /* generate random waiting time for right fork */ + int waiting_times = 10 + rand() mod 50; /* returns number in [10..59] interval */ + + /* check waiting time for right fork is ot expired */ + while(waiting_times>0) + { + /* try to get right form + * There is used sem_trywait, not sem_wait. + * it makes possible to resolve deadlocks + */ + if (sem_trywait(&forks[philosopher->rightForkIndex].mutex)==0) + { + /* philisopehrs gets 2 forks!*/ + printf("Philosopher %d is Eating\n", philosopher->number) + + /* check this philisopers eaten before at least once*/ + if (philosopher->eatenTimes) + { + /* if didn't eat, + * decrement "Not Eaten Philosophers Count + */ + sem_wait(&global_mutex); + NotEatCount--; + sem_post(&global_mutex); + } + + /* increments eaten time for this philosopehers */ + philosopher->eatenTimes++; + + /* eat for some time */ + /* There is delay from 0.5 to 3.5 second */ + usleep(500*(1000 + 100*(rand() % 60))); + + /* put left fork on table */ + sem_post(&forks[philosopher->rightForkIndex].mutex); + + /* if it's here, it means waiting_times was greater than 0 + * Therefhore make waiting_times negative in order to mark + * this philosopers eaten succesfuuly at this time + */ + waiting_times =- waiting_times; + } else if { + /* Cannot get right fork + * decrements timer for waiting right fork + */ + waiting_time--; + /* delay for 0.1 sec*/ + usleep(100000); + /* waiting_times has [10..59] value + * Therefore philosopher waits from 1 to 6 seconds for right fork + */ + } + } + + /* if waiting_times is 0, it means philosopers cannot get right fork and + * waiting time is expired - he will release left fork, despite he is hungry */ + + while (waiting_times==0) + { + printf("Philosopher %d cannot take second fork...\n", philosopher->number); + + } + /* put left fork on table */ + sem_post(&forks[philosopher->leftForkIndex].mutex); + } else { + printf("Philosopher %s cannot eat at this moment...\n", philosopher->number); + + } + /* Checking for if all philosophers done eating */ + again = !is_finished(); + } + } + +} + +int main(int argc, char* argv[]) +{ + struct Philosopher* philosophers; + int i, count = 5; + + /* check command line arguments */ + if (argc>=2) + /* gets number of philosophers from command line*/ + count = atoi(argv[1]); + + srand(((unsigned int)time(NULL)); + /* if arguments is invalid */ + if (count<2 && count>1000) + /* replace with 5 */ + count = 5; + + /* create array of structures for philosophers */ + + philosophers = (struct Philosopher*) malloc(sizeof(struct Philosopher) * count); + + /* create array of structures for forks */ + forks = (struct Fork*)malloc(sizeof(struct Fork) * count); + + /* create global mutex in order to determinate all philophers eaten at least 1 time */ + sem_init(&global_mutex,0,1); + + /* at start, no philosophers eaten */ + NotEatenCount = false; + + for(i=0; i