From f2df4ead519c00cf2205a4ee8ead2fb5a7e19b5c Mon Sep 17 00:00:00 2001 From: staszekm Date: Fri, 13 May 2022 10:50:23 +0000 Subject: [PATCH] Full Project --- .codio | 19 ++ AssemblyGuessingGame/main.asm | 533 +++++++++++++++++++++++++++++++++ AssemblyGuessingGame/main.o | Bin 0 -> 6592 bytes MultiprogrammingInC/clinic.db | Bin 0 -> 8192 bytes MultiprogrammingInC/main | Bin 0 -> 17784 bytes MultiprogrammingInC/main.c | 221 ++++++++++++++ MultiprogrammingInC/ops_sems.h | 99 ++++++ 7 files changed, 872 insertions(+) create mode 100644 .codio create mode 100644 AssemblyGuessingGame/main.asm create mode 100644 AssemblyGuessingGame/main.o create mode 100644 MultiprogrammingInC/clinic.db create mode 100644 MultiprogrammingInC/main create mode 100644 MultiprogrammingInC/main.c create mode 100644 MultiprogrammingInC/ops_sems.h diff --git a/.codio b/.codio new file mode 100644 index 0000000..7232506 --- /dev/null +++ b/.codio @@ -0,0 +1,19 @@ +{ + // This file is used to configure the three buttons along Codio's top menu. + + // Run button configuration + "commands": { + "Compile & Run": "gcc {{filename}} -o {{filename_no_ext}} && ./{{filename_no_ext}}", + "Compile": "gcc {{filename}} -o {{filename_no_ext}}", + "Run": "./{{filename_no_ext}}" + }, + // Preview button configuration + "preview": { + "Project Index (static)": "https://{{domain}}/{{index}}", + "Current File (static)": "https://{{domain}}/{{filepath}}", + "Box URL": "http://{{domain3000}}/", + "Box URL SSL": "https://{{domain3000}}/" + }, + // Debugger target button configuration + "debugger": [{"type":"GDB","command":"/tmp/program67e2dee2135748e7c1ba01f45b46ceda ","before":"gcc -std=c11 -g -lm {{filepath}} -o /tmp/program67e2dee2135748e7c1ba01f45b46ceda","single":true,"lang":"c","additionalCompilerFlags":"","sourcePath":"{{filepath}}","args":"","uuid":"4713985f-ec53-ca5c-71b4-b8615ec23995","name":"Debug Current File"}] +} \ No newline at end of file diff --git a/AssemblyGuessingGame/main.asm b/AssemblyGuessingGame/main.asm new file mode 100644 index 0000000..e5765de --- /dev/null +++ b/AssemblyGuessingGame/main.asm @@ -0,0 +1,533 @@ +;From GuessingGame.asm I used: +;array with answers +;function to end the program +;function for the player to input the answer +;comparison between player input and the answer +;printing messages function, which is adapted into other print functions ;throughout the code + +;Additional features: +;swap system +;answer confidence system + +;If the player guesses correctly: if he is sure, he gets 2 points, if not, ;he gets 1 +;If the player guesses incorrectly: if he is sure, he looses 1 point, ;unless he already has 0, if he is not sure, he looses 0 points + +section .data +welcome db "Welcome to higher or lower game, collect 10 points to win the game, score 5 right answers in a row to win a prize", 10 ;Welcome message + ;for game +welcomeLen equ $-welcome ;Size of the message + +samemsg db 10,"Correct, ";Message that the guess is correct +samelen equ $-samemsg ;Size of the message + +notsamemsg db 10,"Incorrect, ";Message that the guess is incorrect +notsamelen equ $-notsamemsg ;Size of the message + +inputMsg db "User: " ;Message after which player puts their input +inputMsglen equ $-inputMsg ;Size of the message + +streakMsg1 db "Your streak is " ;first segment of message about the streak +streakMsg1len equ $-streakMsg1 ;Size of the message + +streakMsg2 db " out of 5", 10 ;third segment of message about the streak, + ;the second segment being the streak itself +streakMsg2len equ $-streakMsg2 ;Size of the message + +prizeMsg db "Congratulations! You win a prize", 10 ;Message that tells the + ;player that they won a prize +prizeMsglen equ $-prizeMsg ;Size of the message + +exitMsg db " .Press 'e' to exit the game",10; Message that informs the + ;player about the ability to close the game +exitMsglen equ $-exitMsg ;Size of the message + +swapQuestion db "Press 's' to swap question. Swaps left: " ;Message that + ;informs the player about the ability to swap + ;questions, as well as the first part of swaps + ;left message +swapQuestionlen equ $-swapQuestion ;Size of the message + +noSwap db "You have no swaps left", 10 ;message that informs player that + ;they have no swaps left +noSwaplen equ $-noSwap ;Size of the message + +sureMsg db "Are you sure? Y/N",10 ;message asking the user if they are sure + ;of their answer +sureMsglen equ $-sureMsg ;Size of the message + +invalidMsg db "invalid Input, no win points granted",10 ;message informing + ;player that they put invalid input on YES/NO segment +invalidMsglen equ $-invalidMsg ;Size of the message + +winMsg db "Congratulations, you have 10 points, you win!!",10 ;message + ;informing the player that he won the game +winMsglen equ $-winMsg ;Size of the message + +yesInput dq "Y" ;input required from player to say he is sure of the answer +noInput dq "N" ;input required from player to say he is not sure of the + ;answer +;Same as endl in C++ +cr db 10 +exitInput dq "e" ;input required from player to exit the game +swapInput dq "s" ;input required from player to swap the question + +;the array we are using to store the answers +global listAnswers +listAnswers: + dq 'H' ; the answer letters are stores in 8 bytes to aid the comparison + dq 'L' + dq 'H' + dq 'L' + dq 'L' +letter: + dq 0 ; where we store each of the answers one at a time + +Question1 db "Is mount Everest higher or lower than 7000m?(H/L)" +Question1len equ $-Question1 +Question2 db "Is the age of Don Cheadle Higher or Lower than 60?(H/L)" +Question2len equ $-Question2 +Question3 db "Distance from Paris to Berlin is Higher or Lower than 1000km" +Question3len equ $-Question3 +Question4 db "Is the population of Brazil Higher or Lower than 250 milion?" +Question4len equ $-Question4 +Question5 db "Is average reading speed Higher or Lower than 300 words per minute?(H/L)" +Question5len equ $-Question5 + +;array storing quiz questions +questionList: + dq Question1 + dq Question2 + dq Question3 + dq Question4 + dq Question5 +;array storing quiz questions length +questionLenList: + dq Question1len + dq Question2len + dq Question3len + dq Question4len + dq Question5len + +Response1 db "Mount Everest height is 8849 m" +Response1len equ $-Response1 +Response2 db "Don Cheadle is 57 years old" +Response2len equ $-Response2 +Response3 db "Distance from Paris to Berlin is 1054 km" +Response3len equ $-Response3 +Response4 db "The population of Brazil is 212,6 million" +Response4len equ $-Response4 +Response5 db "Average reading speed is 250 words per minute" +Response5len equ $-Response5 + +;array storing quiz answers +responseList: + dq Response1 + dq Response2 + dq Response3 + dq Response4 + dq Response5 +;array for storing quiz answers length +responseLenList: + dq Response1len + dq Response2len + dq Response3len + dq Response4len + dq Response5len + +segment .bss +pointNum: resb 8 ;store number of points +swapNum: resb 8 ;store number of swaps left +winPoints: resb 8;store second punctation system needed to win the game +guess resb 1 ; store the users guess + + +section .text + global _start ;must be declared for linker (ld) +_start: +call displayWelcome +call newLine +mov esi, 0 ;move 0 to esi register +mov [pointNum], esi ;set 0 as the number of points +mov [winPoints], esi ;set 0 as the number of win points +mov esi, 3 ;move 3 to esi register +mov [swapNum], esi ;set 3 as number of guesses left +call loopQuestions + +;Main function that calls other functions +top: + mov rbx, [rcx] ; put the current letter being guessed in rbx + mov [letter],rbx ; move rbx into a variable letter that stores the + ;current guess + push rax ; push rax on stack + push rcx ; push rax on stack + call displayQuestion ; display the question + call displayExitMsg ;display exit message + call displaySwapMsg ;display swap message + call newLine + call reading ; call reading to get the users guess + call displayCorrectAnswer ; print the letter they should have guessed + call newLine + call displayStreak ;display user streak + call newLine ; new line like endl in C++ + pop rcx ; get back from stack + pop rax ; get back from stack + add rcx,8 ;move pointer to next element as 8 bits for each move on by 8 + add r8,8 ; add on 8 bytes as using dq data type + add r9,8 ; add on 8 bytes as using dq data type + add r10,8 ; add on 8 bytes as using dq data type + add r11,8 ; add on 8 bytes as using dq data type + dec rax ;decrement counter so going down + jnz top ;if counter not 0, then loop again + call loopQuestions ;go to the beggining of question array + jmp top + +;function for displaying the correct answer for the current question +displayCorrectAnswer: + mov edx, [r11] ;message length content of register r9 + mov ecx, [r10];message to write content of register r8 + mov ebx, 1 ;file descriptor (stdout) + mov eax, 4 ;system call number (sys_write) + int 0x80 ;call kernel + ret + + ;function to read the user guess and do comparison with the answer +reading: + mov ecx,inputMsg ; input message + mov edx, inputMsglen ; length of input message + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 80h ;call kernel + mov eax, 3 ; read from keyboard + mov ebx, 2; + mov ecx, guess ; move guess into ecx + mov edx, 1 ; As single letter using 1 byte + int 80h ; call interrupt + mov rax, [guess] ;mov players guess to rax register + cmp rax, [exitInput] ;compare rax and value of exitInput + je done ;if they are same jump to function to end the program + cmp rax, [swapInput] ;else, compare rax to value of swapInput + je swap ;if they are same, jump to swap function + cmp rax, [letter] ;else, compare correct answer with what in rax + je same ; if guess was correct jump to same function + call Notsame ; if the guess is incorrect then go to Notsame function + ret + +; function to show message that answer was not correct answer +Notsame: + ;call all the functions checking if player is sure of their answer first + call clearInput + call displaySure + call sureRead + call nSameSure + call clearInput + mov edx, notsamelen ; length of same message + mov ecx,notsamemsg ; Not same message + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 80h ;call kernel + mov esi, 0 ;move 0 to esi register + mov [pointNum], esi ;set 0 as the number of points, since not getting the + ;answer right looses the point streak + ret + +; function to show message answer was correct +same: + ;call all the functions checking if player is sure of their answer first + call clearInput ;call function to clear input + call displaySure ;call function to display question if player is sure + call sureRead ;call function for player to input if they are sure + call sameSure ;call function to check effect on points from player + ;sureness + call clearInput ;call function to clear input + call winCheck ;call function to check if player won + mov edx, samelen ; length of same message + mov ecx,samemsg ;same message + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 80h ;call kernel + mov dx, [pointNum] ;move value of pointNum to dx register + inc dx ;decrease value of integer inside dx register + mov [pointNum], dx ;set contents of dx register as a value of pointNum + ret + +;function for checking whether player has any swaps left and if yes, ;swapping the question +swap: + call clearInput ;call function to clear input + mov rax, 0 ;move 0 into rax register + cmp rax, [swapNum] ;compare value in swapNum variable to value of rax + ;register + je zeroSwap ;if swapNum is equal to zero, jump to zeroSwap function + mov dx, [swapNum] ;else, move value of swapNum to dx register + dec dx ;decrease value of integer inside dx register + mov [swapNum], dx ;set contents of dx register as a value of swapNum + call newLine ; new line like endl in C++ + pop rcx ; get back from stack + pop rax ; get back from stack + add rcx,8 ;move pointer to next element as 8 bits for each move on by 8 + add r8,8 ; add on 8 bytes as using dq data type + add r9,8 ; add on 8 bytes as using dq data type + add r10,8 ;add on 8 bytes as using dq data type + add r11,8 ;add on 8 bytes as using dq data type + dec rax ;decrement counter so going down + jnz top ;if counter not 0, then loop again + call loopQuestions ;go to the beginning of question array + jmp top + +;function for printing a message informing the player that they have zero ;swaps left +zeroSwap: + mov edx, noSwaplen ;message length + mov ecx, noSwap ;message to write + mov ebx, 1 ;file descriptor (stdout) + mov eax, 4 ;system call number (sys_write) + int 0x80 ;call kernel + jmp reading + +; Function to create a New line like endl in C++ +newLine: + mov eax,4 ; Put 4 in eax register into which is system + ;call for write (sys_write) + mov ebx,1 ; Put 1 in ebx register which is the standard + ; output to the screen + mov ecx, cr ; Put the newline value into ecx register + mov edx, 1 ; Put the length of the newline value into edx + ; register + int 80h ; Call the kernel with interrupt to check the + ; registers and perform the action of moving to + ; the next line like endl in c++ + ret ; return to previous position in code + +;Function to display welcome to game message +displayWelcome: + mov edx,welcomeLen ;message length + mov ecx, welcome ;message to write + mov ebx, 1 ;file descriptor (stdout) + mov eax, 4 ;system call number (sys_write) + int 0x80 ;call kernel + ret + +;Function to display question for quiz +displayQuestion: + mov edx, [r9] ;message length from content of register r9 + mov ecx, [r8];message to write from content of register r8 + mov ebx, 1 ;file descriptor (stdout) + mov eax, 4 ;system call number (sys_write) + int 0x80 ;call kernel + ret + +; Function to display the correct answer sentence +displayExitMsg: + mov edx,exitMsglen ;message length + mov ecx, exitMsg ;message to write + mov ebx, 1 ;file descriptor (stdout) + mov eax, 4 ;system call number (sys_write) + int 0x80 ;call kernel + ret +;Function for displaying swaps left message, and the number of swaps left +displaySwapMsg: + mov edx,swapQuestionlen ;message length + mov ecx, swapQuestion ;message to write + mov ebx, 1 ;file descriptor (stdout) + mov eax, 4 ;system call number (sys_write) + int 0x80 ;call kernel + call printSwapNum ;call function to print number of swaps left + ret +;Function for displaying players streak +displayStreak: + mov edx, streakMsg1len ; length of same message + mov ecx,streakMsg1 ; same message + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 80h ;call kernel + call printStreak ;call function to print current streak + mov edx, streakMsg2len ; length of same message + mov ecx,streakMsg2 ; same message + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 80h ;call kernel + call prize ;call function to display prize + ret +;function for converting integer streak to ascii and displaying it on the ;screen +printStreak: + mov esi, [pointNum] ;move value of pointNum variable to esi register + add esi, 48 ;add 48 to esi register to convert number in there into ascii + ;character + mov [pointNum], esi ;set value inside esi register as value of pointNum + ;variable + mov eax, 4 ;system call number (sys_write) + mov ebx, 1 ;file descriptor (stdout) + mov ecx , pointNum ;move number of points to ecx register + mov edx, 8 ;set length of pointNum to 8 bytes + int 80h ;call kernel + mov esi, [pointNum] ;move value of pointNum variable to esi register + sub esi, 48 ;subtract 48 from esi register to convert ascii character + ;back to integer + mov [pointNum], esi ;set value inside esi register as value of pointNum + ;variable + ret + +;function for converting integer swap number to ascii and displaying it on ;the screen +printSwapNum: + mov esi, [swapNum] ;move value of swapNum variable to esi register + add esi, 48 ;add 48 to esi register to convert number in there into ascii + ;character + mov [swapNum], esi ;set value inside esi register as value of swapNum + ;variable + mov eax, 4 ;system call number (sys_write) + mov ebx, 1 ;file descriptor (stdout) + mov ecx , swapNum ;move number of swaps left to ecx register + mov edx, 8 ;set length of swapNum to 8 byte + int 80h ;call kernel + mov esi, [swapNum] ;move value of swapNum variable to esi register + sub esi, 48 ;subtract 48 from esi register to conver ascii character back + ;to integer + mov [swapNum], esi ;set value inside esi register as value of swapNum + ;variable + ret + +;function for checking if player got 5 questions right in a row +prize: + mov rax, 5 ;mov 5 into rax register + cmp rax, [pointNum] ;compare value in rax register to pointNum + je displayPrize ;if they are equal, jump to displayPrizefunction + ret ;else, return + +;function for displaying prize message to the player, and restarting ;punctation system from 0 +displayPrize: + mov edx,prizeMsglen ;move length of prize message to edx register + mov ecx,prizeMsg ; move prize message to ecx register + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 80h ;call kernel + mov esi,0 ;move 0 to esi register + mov [pointNum],esi ;restart the punctation system by moving value of esi + ;register to pointNum + ret + +;function for displaying message to player if they are sure of their answer +displaySure: + mov edx,sureMsglen ;message length + mov ecx, sureMsg ;message to write + mov ebx, 1 ;file descriptor (stdout) + mov eax, 4 ;system call number (sys_write) + int 0x80 ;call kernel + ret + +;function for getting input from the user if they are sure of their answer +sureRead: + mov ecx,inputMsg ; input message + mov edx, inputMsglen ; length of input message + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 80h ;call kernel + mov eax, 3 ; read from keyboard + mov ebx, 2; + mov ecx, guess ; move guess into ecx + mov edx, 1 ; As single letter using 1 byte + int 80h ; call interrupt + ret + +;function to process input if player was sure of their answer, when their ;answer was right +sameSure: + mov rax, [guess] ;move players guess to rax registery + cmp rax, [yesInput] ;compare value of rax with value of yesInput variable + je sameYes ;if they are the same, go to sameYes function + cmp rax, [noInput] ;else, compare value of rax with value of noInput + ;variable + jne invalidInput ;if they are not the same, go to invalidInput function + mov dx, [winPoints] ;else, move value of winPoints to dx register + inc dx ;decrease value of integer inside dx register + mov [winPoints], dx ;set contents of dx register as a value of winPoints + ret + +;function that is called when player has answered right, and were confident ;in their answer, increases their winPoints by 2 +sameYes: + mov esi, [winPoints] ;move value of winPoints to esi register + add esi, 2 ;add 2 to esi registery + mov [winPoints], esi ;set contents of esi register as a value of + ;winPoints + ret + +;function to process input if player was sure of their answer, when their ;answer was wrong +nSameSure: + mov rax, [guess] ;mov value of guess to rax register + cmp rax, [yesInput] ;compare value of yesInput variable to rax + je nSameYes1 ;if they are the same, jump to nSameYes1 function + cmp rax, [noInput] ;else, compare value of noInput variable to rax + jne invalidInput ;if they are not the same, call invalidInput function + ret ;else, if the player was not sure in their answer and it was wrong, + ;there is no change in points, which means we can just return + +;funtion that is called when the player has answered wrong and was ;confident, first checks if current number of win points is 0 and if no, ;calls function to decrease points +nSameYes1: + mov rax, 0 ;move 0 to rax registery + cmp rax, [winPoints] ;compare number of win points to rax registery + jne nSameYes2 ;if not equal, jump to nSameYes2 function + ret ;else return + +;funtion to decrease current number of win points by 1 +nSameYes2: + mov dx, [winPoints] ;else, move value of winPoints to dx register + dec dx ;decrease value of integer inside dx register + mov [winPoints], dx ;set contents of dx register as a value of winPoints + ret + +;function for displaying to user that their input was invalid +invalidInput: + mov edx,invalidMsglen ;move length of prize message to edx register + mov ecx,invalidMsg ; move prize message to ecx register + mov ebx,1 ;file descriptor (stdout) + mov eax,4 ;system call number (sys_write) + int 80h + ret + +;function to check if the player has enough points to win the game +winCheck: + mov rax, 10 ;move 10 to rax registery + cmp rax, [winPoints] ;compare current number of win points to rax + ;registry + jle winGame ;if rax registery is lesser or equal to current number of win + ;points, jump to winGame function + ret ;else return + +;function for printing message about winning the game, and then calling done function to quit program +winGame: + mov edx,winMsglen ;message length + mov ecx, winMsg ;message to write + mov ebx, 1 ;file descriptor (stdout) + mov eax, 4 ;system call number (sys_write) + int 0x80 ;call kernel + call done + +;function for going to the beginning of question array, called when program stars, +;and when it reaches the end of question array +loopQuestions: + mov rax,5 ;number of answers + mov rcx,0 ;RBX will store the letter + mov rcx, listAnswers ;RCX will point to the current element array to + ;be guessed + mov r8, questionList ;move into r9 register the beginning of array with + ;questions + mov r9, questionLenList ;move into r9 register the beginning of array + ;with question lengths + mov r10, responseList ;move into r10 register the beginning of array + ;with answers + mov r11, responseLenList ;move into r11 register the beginning of array + ;with answer lengths + ret + +;function to deal with previous enter key +clearInput: + mov eax, 3 ; read previous enter key press + mov ebx, 2 + mov ecx, guess ; Deal with previous enter key press so it does not mess + ;up loop + mov edx, 1 ; As single letter using 1 byte + int 80h ;call kernel + ret + +;Function to end the program +done: + call clearInput + mov rax,0 ;move 0 to rax register + mov eax, 1 ;system call number (sys_exit) + int 0x80 ;call kernel diff --git a/AssemblyGuessingGame/main.o b/AssemblyGuessingGame/main.o new file mode 100644 index 0000000000000000000000000000000000000000..1447955b5a3769f2e9068f510ad14eb671c2866f GIT binary patch literal 6592 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 Wsti+eTNXA&kVzL}MdwT7=be8z>0*8W literal 0 HcmV?d00001 diff --git a/MultiprogrammingInC/main b/MultiprogrammingInC/main new file mode 100644 index 0000000000000000000000000000000000000000..43ed35edaf987bb9240877f65ca8f3933c4c5126 GIT binary patch literal 17784 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 Xj>~0Pdc7P +#include +#include +#include +#include +#include +#include +#include +#include +#include "ops_sems.h" +#include +#include +//aditional features: +//number of doctors administering the vaccine can be modified +//additionaly to ID, name and age are required from patients, and their personal data is placed in a database instead of text file + +int callback(void *count, int argc, char **argv, char **azColName) { + //callback function for getting number of rows in a database, code based on https://stackoverflow.com/questions/21692245/retrieve-sql-table-row-count-with-c + int *c = count; //initialise pointer to count variable + *c = atoi(argv[0]); //convert string number of rows to int and place it in c pointer + return 0; +} + +bool inputCheck(char name[50],int age){ + //function that checks if name and age inputs are valid + bool validInput = true; //initialise validInput boolean and set it to true + for(int i = 0; name[i]; i++){ //for each character in name string + if(isdigit(name[i]) && !isspace(name[i])){ //if it is a digit and + //not a whitespace + validInput = false;} } //set validInput boolean to false + if(age < 1 || age > 130){validInput = false;} //if age is smaller than 1 + //or bigger than 130, set + //validInput variable to false + return validInput; + +} +int main(int argc, char argv[]){ + char* err; //initialise a pointer to error message + int count; //initialise count integer + sqlite3* db; //initialise sqlite3 database + sqlite3_stmt* stmt; //initialise pointer to sqlite3 statement + sqlite3_open("clinic.db",&db); //open clinic database + int rc = sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS patients(ID INT,name varchar(14),age INT)",NULL,NULL,&err); //create patients table in clinic + //database if it does not exist, and + //place ID, name and age columns there + if(rc != SQLITE_OK) { //if there were errors in the sqlite operation + fprintf(stderr, "SQL error: %s\n", err); //print to stderr the + //error message + sqlite3_free(err); //free the query with the error + } + rc = sqlite3_exec(db, "select count(*) from patients", callback, &count, &err); //make sqlite query to count all the rows in patients table + if(rc != SQLITE_OK) { //if there were errors in the sqlite operation + fprintf(stderr, "SQL error: %s\n", err); //print to stderr the + //error message + sqlite3_free(err); //free the query with the error + } + int maxPatients = 120; //initialise maxPatients inside database int and + //set it to 120 + if(count >= maxPatients){printf("the database is full, no more vaccines can be administered \n");return 0;} //if the patient table in the clinic + //database is full, inform the user and + //end the program + int bufferlength = 1024; //set length of buffer to 1024 bytes + //FILE *f = fopen("patients.txt", "w+");//if we wanted to use txt file instead of database, it opens patients.txt in write mode, and creates the txt file if it does not exist + int id=ops_semget("main.c",1); //initialise int and setit to ops_semget + //function with current file and 1 as + //passed arguments + int status = 0; //initialise status int and set it to 0 + int shmid; //initialise shmid integer + char temp; //initialise character for temporary input + int doctorNum; //initialise number of doctors int + typedef struct{int id;char name[50];int age;}patient; //define patient + //structure with int id, name 50 + //characters string, and age int. + char nameStr[50]; //initialise nameStr 50 character string, where patients + //name input will be stored + int ageInt; //initialise ageInt int, where patients age input + //will be stored + int patientID = count + 1; //initialise patinentID int and set it to + //current number of rows inside database + 1 + int clinicSize = 10; //initialise size of clinic int and set it to 10 + patient (*data)[clinicSize]; //initialise pointer to shared data array + //where max clinic size number of patient + //structures can be stored + printf("Set number of doctors administering the vaccine -> "); + scanf("%d",&doctorNum); //input that sets doctorNum integer + if(doctorNum > clinicSize) doctorNum = clinicSize; //if there are more + //doctors than places in the + //clinic, set number of doctors to + //clinicSize + int pid=fork(); //fork the current process + shmid=shmget(ftok("main.c",2),bufferlength, 0644|IPC_CREAT); //set shmid of the + //current process + if(pid){ //if current process id is greater than 0 + //P1 + int patientNum = 0; //initialise patient number and set it to 0 + int written = 0; //initialise number of times written to shared memory + //int and set it to 0 + data = shmat(shmid, NULL, 0); //create shared memory + ops_wait(id); //process calls wait, so that it can go into its + //critical section if none other processes are in their + //critical section + while(written < clinicSize){ //fully fill the clinic with patients + printf("Patient %i add your name -> ",patientID); + scanf("%c",&temp); //temporary input stament to clear input buffer + scanf("%[^\n]",nameStr); //input with allowed whitespaces that + //sets nameStr string + printf("Patient %i add your age -> ",patientID); + scanf("%i",&ageInt); //input that sets ageInt integer + if(inputCheck(nameStr,ageInt) == false){printf("Please input real personal data\n");continue;} //if the inputCheck with name and age passed as + //arguments returns false, repeat the loop + //without increasing written and patientID + (*data)[written].id = patientID; //go to written integer index of + //shared data array, and set id in + //patient structure to patinentID + strcpy((*data)[written].name, nameStr); //go to written integer + //index of shared data array, and set + //name in patient structure to nameStr + (*data)[written].age = ageInt; //go to written integer index of + //shared data array, and set age in + //patient structure to ageInt + written++; //increase written integer by 1 + patientID++; //increase patientID integer by 1 + } + //this is part of process 1 that will be executed after initial clinic + //fill, until the end of the program + ops_signal(id); //process sends a signal that it had finished its + //critical section + while(patientID <= maxPatients){ //repeat until the patient table + //in the database is filled + ops_wait(id); //process calls wait, so that it can go into its + //critical section if none other processes are in + //their critical section + for(int i = 0;i= clinicSize) //if written is bigger or equal + //than clinic size + written = 0; //go to the beggining of shared memory + printf("Patient %i add your name -> ",patientID); + scanf("%c",&temp); //temporary input stament to clear input + //buffer + scanf("%[^\n]",nameStr); //input with allowed whitespaces + //that sets nameStr string + printf("Patient %i add your age ->",patientID); + scanf("%i",&ageInt); //input that sets ageInt integer + if(inputCheck(nameStr,ageInt) == false){printf("Please input real personal data\n");continue;} //if the inputCheck with name and age + //passed as arguments returns false, repeat the + //loop without increasing written and patientID + (*data)[written].id = patientID; //go to written integer index + //of shared data array, and set id in + //patient structure to patinentID + strcpy((*data)[written].name, nameStr); //go to written + //integer index of shared data + //array, and set age in patient + //structure to ageInt + (*data)[written].age = ageInt; //go to written integer index + //of shared data array, and set age in + //patient structure to ageInt + written++; //increase written integer by 1 + patientID++;}} //increase patientID integer by 1 + ops_signal(id); //process sends a signal that it had finished + //its critical section + } + wait(&status); //wait for the child process to end + } + else{ //if current process id is 0 + //P2 + int read = 0; //initialise number of times read from shared memory int + //and set it to 0 + data = shmat(shmid, (void *)0, 0); //create shared memory + sleep(1); //ensure that P2 will be executed after P1 + while(patientID <= maxPatients){ //repeat until the patient table in + //the database is filled + ops_wait(id); //process calls wait, so that it can go into its + //critical section if none other processes are in their + //critical section + for(int i = 0;i= clinicSize) //if read is bigger or equal than + //clinic size + read = 0; //go to the beggining of shared memory + char* query = sqlite3_mprintf("insert into patients values (%i,'%q',%i)",(*data)[read].id,(*data)[read].name,(*data)[read].age);//create + //sqlite query for inserting rows into database, + //and set inserted values to current vaccinated + //patients id, name and age + int rc = sqlite3_exec(db,query,NULL,NULL,&err); //execure + //sqlite query + if(rc != SQLITE_OK) { //if there were errors in the sqlite + //operation + fprintf(stderr, "SQL error: %s\n", err); //print to stderr + //the error message + sqlite3_free(err); //free the query with the error + } + //fprintf(f, "Patient name: %s, Patient ID: %i\n, Patient age: %i",(*data)[read].name,(*data)[read].id),(*data)[read].age; //line of code used if we wanted to use txt files insteas of database + printf("Patient %i leaving the clinic...\n",(*data)[read].id); //print string to console with current + //patients id inserted into it + read++; //increase read integer by 1 + patientID++; //increase patientID by 1 + }} + sleep(2); //patient leaving the clinic + ops_signal(id); //process sends a signal that it had finished its + //critical section + } + //fclose(f); //if the user wants to use txt file instead of database, close the txt file + sqlite3_close(db); //close the database + } +return 0; +} + diff --git a/MultiprogrammingInC/ops_sems.h b/MultiprogrammingInC/ops_sems.h new file mode 100644 index 0000000..14ce2ad --- /dev/null +++ b/MultiprogrammingInC/ops_sems.h @@ -0,0 +1,99 @@ +/* ops_sems.h */ +/* Simple functions to ease the use of semaphores */ +/* James Shuttleworth, 2012 */ +/*--------------------------------------------------------------------------------*/ +/* This program is free software: you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation, either version 3 of the License, or */ +/* (at your option) any later version. */ + +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ + +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see . */ + +#include +#include +#include +#include + +void rsleep(){ + //Random sleep function. Comes in handy demoing stuff. + int stime=2+(rand()/(float)(RAND_MAX))*4; + printf("Sleeping for %d secs\n",stime); + sleep(stime); +} + + +int ops_semget(char* path, int val){ + //Very simple semaphore "getting", + //always uses 1 as the project ID + //takes path to file and initial value of semaphore + + int id; /* Number by which the semaphore + is known within a program */ + + + union semun { + int val; + struct semid_ds *buf; + ushort * array; + } argument; + + argument.val = val; + + /* Create the semaphore with external key from + ftok if it doesn't already + exist. Give permissions to the world. */ + + id = semget(ftok(path,1), 1, 0666 | IPC_CREAT); + + /* Always check system returns. */ + + if(id < 0) + { + fprintf(stderr, "Unable to obtain semaphore.\n"); + exit(0); + } + + /* Set the value of the number 0 semaphore in semaphore array # id + to the value "val". */ + + if( semctl(id, 0, SETVAL, argument) < 0) + fprintf( stderr, "Cannot set semaphore value.\n"); + else + fprintf(stderr, "Semaphore %d initialized with path '%s'.\n", + ftok(path,1),path); + return id; +} + +void ops_semop(int id,int val){ + + + struct sembuf operations[1]; + int retval; /* Return value from semop() */ + + //simple wait on semaphore + operations[0].sem_num = 0; + /* Which operation? Subtract 1 from semaphore value to wait, add to + signal */ + operations[0].sem_op = val; + operations[0].sem_flg = 0; + + retval = semop(id, operations, 1); + +} + + +void ops_wait(int id){ + ops_semop(id,-1); +} + +void ops_signal(int id){ + ops_semop(id,1); +} + +