Add some more comments. Implement sempahore search function. Check correctness of the current semaphore code, and it works as expected.
This commit is contained in:
+4
-4
@@ -34,8 +34,8 @@ struct ipc_perm {
|
||||
unsigned short __seq;
|
||||
};
|
||||
|
||||
/// @brief Returns a possible key
|
||||
/// @param path file path
|
||||
/// @param id integer
|
||||
/// @return IPC key
|
||||
/// @brief Returns a possible IPC key based upon the filepath and the id.
|
||||
/// @param path The file path.
|
||||
/// @param id the project id.
|
||||
/// @return the IPC key.
|
||||
key_t ftok(char *path, int id);
|
||||
|
||||
+2
-3
@@ -7,12 +7,11 @@
|
||||
#include "system/syscall_types.h"
|
||||
#include "sys/errno.h"
|
||||
#include "stddef.h"
|
||||
|
||||
#include "ipc/sem.h"
|
||||
#include "ipc/shm.h"
|
||||
#include "ipc/msg.h"
|
||||
|
||||
#include "sys/stat.h"
|
||||
#include "io/debug.h"
|
||||
|
||||
_syscall3(void *, shmat, int, shmid, const void *, shmaddr, int, shmflg)
|
||||
|
||||
@@ -62,7 +61,7 @@ key_t ftok(char *path, int id)
|
||||
struct stat_t st;
|
||||
if (stat(path, &st) < 0) {
|
||||
errno = ENOENT;
|
||||
//printf("Error finding the serial number, check Errno...\n");
|
||||
pr_debug("Error finding the serial number, check Errno...\n");
|
||||
return -1;
|
||||
}
|
||||
// Taking the upper 8 bits from the lower 8 bits of id, the second upper 8
|
||||
|
||||
+89
-85
@@ -2,12 +2,33 @@
|
||||
/// @brief
|
||||
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
///! @cond Doxygen_Suppress
|
||||
|
||||
#include "ipc/sem.h"
|
||||
#include "klib/list.h"
|
||||
#include "process/process.h"
|
||||
#include "sys/errno.h"
|
||||
/// @details
|
||||
/// # 03/04/2023
|
||||
/// At the moment we have various functions with their description (see
|
||||
/// comments). The first time that the function semget is called, we are going
|
||||
/// to generate the list and the first semaphore set with the assumption that we
|
||||
/// are not given a IPC_PRIVATE key (temporary ofc).
|
||||
/// We are able to create new semaphores set and generate unique keys
|
||||
/// (IPC_PRIVATE) with a counter that searches for the first possible key to
|
||||
/// assign.
|
||||
/// Temporary idea:
|
||||
/// - IPC_CREAT flag, it should be working properly, it creates a semaphore set
|
||||
/// with the given key.
|
||||
/// - IPC_EXCL flag, it should be working properly, it returns -1 and sets the
|
||||
/// errno if the key is already used.
|
||||
///
|
||||
/// # 11/04/2023
|
||||
/// Right now we have a first version of working semaphores in MentOS.
|
||||
/// We have completed the semctl function and we have implemented the first
|
||||
/// version of the semop function both user and kernel side.
|
||||
/// The way it works is pretty straightforward, the user tries to perform an
|
||||
/// operation and based on the value of the semaphore the kernel returns certain
|
||||
/// values. If the operation cannot be performed then the user will stay in a
|
||||
/// while loop. The cycle ends with a positive return value (the operation has
|
||||
/// been taken care of) or in case of errors.
|
||||
/// For testing purposes -> you can try the t_semget and the t_sem1 tests. They
|
||||
/// both use semaphores and blocking / non blocking operations. t_sem1 is also
|
||||
/// an exercise that was assingned by Professor Drago in the OS course.
|
||||
|
||||
// ============================================================================
|
||||
// Setup the logging for this file (do this before any other include).
|
||||
@@ -17,49 +38,43 @@
|
||||
#include "io/debug.h" // Include debugging functions.
|
||||
// ============================================================================
|
||||
|
||||
/*
|
||||
03/04 : at the moment we have various functions with their description (see comments).
|
||||
The first time that the function semget is called, we are going to generate the list and the first semaphore set
|
||||
with the assumption that we are not given a IPC_PRIVATE key (temporary ofc).
|
||||
We are able to create new semaphores set and generate unique keys (IPC_PRIVATE) with
|
||||
a counter that searches for the first possible key to assign. -> temporary idea
|
||||
IPC_CREAT flag, it should be working properly, it creates a semaphore set with the given key.
|
||||
IPC_EXCL flag, it should be working properly, it returns -1 and sets the errno if the
|
||||
key is already used
|
||||
#include "ipc/sem.h"
|
||||
#include "klib/list.h"
|
||||
#include "process/process.h"
|
||||
#include "sys/errno.h"
|
||||
#include "assert.h"
|
||||
|
||||
11/04 : right now we have a first version of working semaphores in MentOS.
|
||||
We have completed the semctl function and we have implemented the first version of the semop function
|
||||
both user and kernel side. The way it works is pretty straightforward, the user tries to perform an operation
|
||||
and based on the value of the semaphore the kernel returns certain values. If the operation cannot be performed
|
||||
then the user will stay in a while loop. The cycle ends with a positive return value (the operation has been taken care of)
|
||||
or in case of errors.
|
||||
For testing purposes -> you can try the t_semget and the t_sem1 tests. They both use semaphores and blocking / non blocking operations.
|
||||
t_sem1 is also an exercise that was assingned by Professor Drago in the OS course.
|
||||
*/
|
||||
|
||||
///@brief a value to compute the semid value
|
||||
///@brief A value to compute the semid value.
|
||||
int semid_assign = 0;
|
||||
|
||||
/// @brief to initialize a single semaphore
|
||||
/// @param temp the pointer to the struct of the semaphore
|
||||
/// @brief list of all current active semaphores
|
||||
list_t *current_semaphores;
|
||||
|
||||
/// @brief [temporary] To implement the IPC_PRIVATE mechanism.
|
||||
int count_ipc_private = 2;
|
||||
|
||||
/// @brief Initializes a single semaphore.
|
||||
/// @param temp the pointer to the struct of the semaphore.
|
||||
static inline void __sem_init(struct sem *temp)
|
||||
{
|
||||
temp->sem_val = 0; /*default*/
|
||||
temp->sem_val = 0;
|
||||
temp->sem_pid = sys_getpid();
|
||||
temp->sem_zcnt = 0; /*default*/
|
||||
temp->sem_zcnt = 0;
|
||||
}
|
||||
|
||||
/// @brief Initializes a semid struct (set of semaphores).
|
||||
/// @param temp the pointer to the semid struct
|
||||
/// @param temp the pointer to the semid struct.
|
||||
/// @param key IPC_KEY associated with the set of semaphores
|
||||
/// @param nsems number of semaphores to initialize
|
||||
/// @todo The way we compute the semid is a temporary solution.
|
||||
static inline void __semid_init(struct semid_ds *temp, key_t key, int nsems)
|
||||
{
|
||||
assert(temp && "Received NULL semid data structure.");
|
||||
temp->owner = sys_getpid();
|
||||
temp->key = key;
|
||||
temp->semid = ++semid_assign; //temporary -> gonna need a way to compute IPCKEY -> semid
|
||||
temp->sem_otime = 0; /*default*/
|
||||
temp->sem_ctime = 0; /*default*/
|
||||
temp->semid = ++semid_assign;
|
||||
temp->sem_otime = 0;
|
||||
temp->sem_ctime = 0;
|
||||
temp->sem_nsems = nsems;
|
||||
temp->sems = (struct sem *)kmalloc(sizeof(struct sem) * nsems);
|
||||
for (int i = 0; i < nsems; i++) {
|
||||
@@ -67,10 +82,30 @@ static inline void __semid_init(struct semid_ds *temp, key_t key, int nsems)
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Searches for the semaphore with the given id.
|
||||
/// @param semid the id we are searching.
|
||||
/// @return the semaphore with the given id.
|
||||
static inline struct semid_ds *__find_semaphore(int semid)
|
||||
{
|
||||
struct semid_ds *semaphore, *entry;
|
||||
// Iterate through the list of semaphores.
|
||||
listnode_foreach(listnode, current_semaphores)
|
||||
{
|
||||
// Get the current entry.
|
||||
entry = (struct semid_ds *)listnode->value;
|
||||
// If the entry is valid, check the id.
|
||||
if (entry && (entry->semid == semid))
|
||||
return entry;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// @brief for debugging purposes, print all the stats of the semid_ds
|
||||
/// @param temp the pointer to the semid struct
|
||||
void semid_print(struct semid_ds *temp)
|
||||
{
|
||||
assert(temp && "Received NULL semid data structure.");
|
||||
|
||||
pr_debug("pid, IPC_KEY, Semid, semop, change: %d, %d, %d, %d, %d\n", temp->owner, temp->key, temp->semid, temp->sem_otime, temp->sem_ctime);
|
||||
for (int i = 0; i < (temp->sem_nsems); i++) {
|
||||
pr_debug("%d semaphore:\n", i + 1);
|
||||
@@ -80,11 +115,6 @@ void semid_print(struct semid_ds *temp)
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief list of all current active semaphores
|
||||
list_t *current_semaphores;
|
||||
|
||||
int count_ipc_private = 2; //temporary -> to implement the IPC_PRIVATE mechanism
|
||||
|
||||
long sys_semget(key_t key, int nsems, int semflg)
|
||||
{
|
||||
struct semid_ds *temp = NULL;
|
||||
@@ -157,25 +187,16 @@ long sys_semget(key_t key, int nsems, int semflg)
|
||||
|
||||
long sys_semop(int semid, struct sembuf *sops, unsigned nsops)
|
||||
{
|
||||
int flag = 0;
|
||||
struct semid_ds *temp;
|
||||
listnode_foreach(listnode, current_semaphores)
|
||||
{ //iterate through the list
|
||||
if (((struct semid_ds *)listnode->value)->semid == semid) { //if we find a semid with the given key
|
||||
flag = 1;
|
||||
temp = ((struct semid_ds *)listnode->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag) { /*if the semid does not find a match then we set the errno and return -1*/
|
||||
errno = EINVAL;
|
||||
return errno;
|
||||
// Search for the semaphore.
|
||||
temp = __find_semaphore(semid);
|
||||
// If the semaphore is NULL, stop.
|
||||
if (!temp) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sops->sem_num < 0 || sops->sem_num >= temp->sem_nsems) { //checking parameters
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
temp->sem_otime = sys_time(NULL);
|
||||
@@ -206,20 +227,12 @@ long sys_semop(int semid, struct sembuf *sops, unsigned nsops)
|
||||
|
||||
long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
|
||||
{
|
||||
int flag = 0;
|
||||
struct semid_ds *temp;
|
||||
listnode_foreach(listnode, current_semaphores)
|
||||
{ //iterate through the list
|
||||
if (((struct semid_ds *)listnode->value)->semid == semid) { //if we find a semid with the given key
|
||||
flag = 1;
|
||||
temp = ((struct semid_ds *)listnode->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag) { /*if the semid does not find a match then we set the errno and return -1*/
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
// Search for the semaphore.
|
||||
temp = __find_semaphore(semid);
|
||||
// If the semaphore is NULL, stop.
|
||||
if (!temp) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
@@ -235,8 +248,7 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
|
||||
//place a copy of the semid_ds data structure in the buffer pointed to by arg.buf.
|
||||
case IPC_STAT:
|
||||
if (arg->buf == NULL || arg->buf->sems == NULL) { /*checking the parameters*/
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
//copying all the data
|
||||
@@ -262,13 +274,11 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
|
||||
//the value of the semnum-th semaphore in the set is initialized to the value specified in arg.val.
|
||||
case SETVAL:
|
||||
if (semnum < 0 || semnum >= (temp->sem_nsems)) { //if the index is valid
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg->val < 0) { //checking if the value is valid
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
//setting the values
|
||||
temp->sem_ctime = sys_time(NULL);
|
||||
@@ -278,8 +288,7 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
|
||||
//returns the value of the semnum-th semaphore in the set specified by semid; no argument required.
|
||||
case GETVAL:
|
||||
if (semnum < 0 || semnum >= (temp->sem_nsems)) { //if the index is valid
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return temp->sems[semnum].sem_val;
|
||||
@@ -287,8 +296,7 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
|
||||
//initialize all semaphore in the set referred to by semid, using the values supplied in the array pointed to by arg.array.
|
||||
case SETALL:
|
||||
if (arg->array == NULL) { /*checking parameters*/
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
for (int i = 0; i < temp->sem_nsems; i++) { //setting all the values
|
||||
temp->sems[i].sem_val = arg->array[i];
|
||||
@@ -299,8 +307,7 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
|
||||
//retrieve the values of all of the semaphores in the set referred to by semid, placing them in the array pointed to by arg.array.
|
||||
case GETALL:
|
||||
if (arg->array == NULL) { //checking if the argument passed is valid
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
for (int i = 0; i < temp->sem_nsems; i++) {
|
||||
arg->array[i] = temp->sems[i].sem_val;
|
||||
@@ -310,8 +317,7 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
|
||||
//return the process ID of the last process to perform a semop on the semnum-th semaphore.
|
||||
case GETPID:
|
||||
if (semnum < 0 || semnum >= (temp->sem_nsems)) { //if the index is valid
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return temp->sems[semnum].sem_pid;
|
||||
@@ -319,16 +325,14 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
|
||||
//return the number of processes currently waiting for the value of the semnum-th semaphore to become 0.
|
||||
case GETZCNT:
|
||||
if (semnum < 0 || semnum >= (temp->sem_nsems)) { //if the index is valid
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return temp->sems[semnum].sem_zcnt;
|
||||
|
||||
//not a valid argument.
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+61
-36
@@ -6,7 +6,6 @@
|
||||
#include "stdlib.h"
|
||||
#include "sys/unistd.h"
|
||||
|
||||
|
||||
/*
|
||||
Testing Semaphores.
|
||||
This program creates a son and then performs a blocking operation on a semaphore. The son sleeps for
|
||||
@@ -14,68 +13,95 @@ five seconds and then it wakes up his father and then it deletes the semaphore.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
void semid_print(struct semid_ds *temp){
|
||||
void semid_print(struct semid_ds *temp)
|
||||
{
|
||||
printf("pid, IPC_KEY, Semid, semop, change: %d, %d, %d, %d, %d\n", temp->owner, temp->key, temp->semid, temp->sem_otime, temp->sem_ctime);
|
||||
for(int i=0; i<(temp->sem_nsems); i++){
|
||||
printf("%d semaphore:\n", i+1);
|
||||
for (int i = 0; i < (temp->sem_nsems); i++) {
|
||||
printf("%d semaphore:\n", i + 1);
|
||||
printf("value: %d, pid %d, process waiting %d\n", temp->sems[i].sem_val, temp->sems[i].sem_pid, temp->sems[i].sem_zcnt);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
struct sembuf op;
|
||||
union semun arg;
|
||||
arg.val = 1;
|
||||
//key_t i = ftok("/test1.txt", 5); //checking ftok
|
||||
long id = semget(2,1,IPC_CREAT); //first semaphores
|
||||
long ret, id;
|
||||
key_t key;
|
||||
|
||||
// Checking if ftok works.
|
||||
key = ftok("/home/user/test7.txt", 5);
|
||||
printf("Key : %d\n", key);
|
||||
|
||||
// Create the first semaphore.
|
||||
id = semget(2, 1, IPC_CREAT);
|
||||
printf("Id: %d\n", id);
|
||||
|
||||
//long id2 = semget(IPC_PRIVATE, 1, IPC_CREAT);
|
||||
//long id2 = semget(2, 2, IPC_EXCL); //need to return -1 bc already exists
|
||||
|
||||
//long id3 = semget(2, 2, 0); //need to return 3 (semid of the first)
|
||||
|
||||
//long id4 = semget(100, 2, IPC_CREAT | IPC_EXCL); //need to return 101 (new semaphore)
|
||||
long value;
|
||||
printf("ID: %d\n", id);
|
||||
if ((value = semctl(id, 0, SETVAL, &arg)) == -1){
|
||||
printf("ERRORE\n");
|
||||
}else{
|
||||
//semid_print(arg.v);
|
||||
printf("valore sem 0: %d \n", semctl(id, 0, GETVAL, &arg));
|
||||
|
||||
// Set the value of the semaphore in the structure.
|
||||
arg.val = 1;
|
||||
// Setting the semaphore value.
|
||||
printf("Set Value (%d): %d\n", id, arg.val);
|
||||
ret = semctl(id, 0, SETVAL, &arg);
|
||||
if (ret == -1) {
|
||||
perror("Failed to set value of semaphore.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check if we successfully set the value of the semaphore.
|
||||
ret = semctl(id, 0, GETVAL, &arg);
|
||||
printf("Check Value (%d): %d\n", id, ret);
|
||||
|
||||
|
||||
if (!fork()){
|
||||
// Create child process.
|
||||
if (!fork()) {
|
||||
// Make the child process sleep.
|
||||
sleep(5);
|
||||
struct sembuf op2;
|
||||
op2.sem_num = 0;
|
||||
op2.sem_op = 150;
|
||||
op2.sem_flg = 0;
|
||||
semop(id, &op2, 1);
|
||||
|
||||
// Initialize the operation structure.
|
||||
op.sem_num = 0; // Operate on semaphore 0.
|
||||
op.sem_op = 1; // Increment value by 1.
|
||||
op.sem_flg = 0; // No flags.
|
||||
|
||||
// This should allow the father process to decrement the semaphore by 2.
|
||||
|
||||
// Perform the operation.
|
||||
semop(id, &op, 1);
|
||||
|
||||
// Remove the semaphore.
|
||||
semctl(id, 0, IPC_RMID, NULL);
|
||||
|
||||
exit(0);
|
||||
// Exit with the child process.
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sembuf op;
|
||||
op.sem_num = 0;
|
||||
op.sem_op = -1;
|
||||
op.sem_flg = 0;
|
||||
if (semop(id, &op, 2) < 0){
|
||||
// Initialize the operation structure.
|
||||
op.sem_num = 0; // Operate on semaphore 0.
|
||||
op.sem_op = -2; // Decrement value by 2.
|
||||
op.sem_flg = 0; // No flags.
|
||||
|
||||
// We set the semaphore at the beginning at 1, and the child process will
|
||||
// increment the semaphore by 1, allowing us to decrement the semaphore by
|
||||
// 2.
|
||||
|
||||
// Perform the operation.
|
||||
if (semop(id, &op, 1) < 0) {
|
||||
printf("ERRORE\n");
|
||||
}
|
||||
printf("valore sem 0: %d \n", semctl(id, 0, GETVAL, &arg));
|
||||
|
||||
|
||||
// Check if we successfully set the value of the semaphore.
|
||||
ret = semctl(id, 0, GETVAL, &arg);
|
||||
printf("Check Value (%d): %d\n", id, ret);
|
||||
|
||||
/*if ((semid = semctl(id, 0, IPC_RMID, 0)) == -1){
|
||||
printf("%d\n", errno);
|
||||
}else{
|
||||
printf("found %d\n", semid);
|
||||
}*/
|
||||
|
||||
|
||||
//long id2 = semget(IPC_PRIVATE, 2, 0);
|
||||
//long id3 = semget(IPC_PRIVATE, 2, 0);
|
||||
//printf("id %d id2 %d id3 %d id4 %d\n", id, id2, id3, id4);
|
||||
@@ -83,7 +109,6 @@ int main()
|
||||
printf("Error with IPC_KEY\n");
|
||||
return -1;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user