From 7c166e73a385e02d18593bb5376e32836719e4d5 Mon Sep 17 00:00:00 2001 From: Aldegheri Alessandro Date: Mon, 3 Apr 2023 21:27:49 +0200 Subject: [PATCH] First implementation of semget function with multiple flags working (see comments inside) --- libc/inc/ipc/ipc.h | 8 ++ libc/inc/ipc/sem.h | 19 ++++- mentos/inc/sys/ipc.h | 2 + mentos/src/ipc/sem.c | 158 +++++++++++++++++++++++++++----------- programs/tests/t_semget.c | 24 ++++-- 5 files changed, 161 insertions(+), 50 deletions(-) diff --git a/libc/inc/ipc/ipc.h b/libc/inc/ipc/ipc.h index ce0ad4c..cab5dd4 100644 --- a/libc/inc/ipc/ipc.h +++ b/libc/inc/ipc/ipc.h @@ -6,6 +6,14 @@ #pragma once +#define IPC_CREAT 01000 ///< Create key if key does not exist. +#define IPC_EXCL 02000 ///< Fail if key exists. +#define IPC_NOWAIT 04000 ///< Return error on wait. +#define IPC_RMID 0 ///< Remove identifier. +#define IPC_SET 1 ///< Set `ipc_perm' options. +#define IPC_STAT 2 ///< Get `ipc_perm' options. +#define IPC_INFO 3 ///< See ipcs. +#define IPC_PRIVATE 4 ///< assures getting a new ipc_key. /// @brief Permission details of an IPC object. struct ipc_perm { diff --git a/libc/inc/ipc/sem.h b/libc/inc/ipc/sem.h index 3c01a3e..c166b23 100644 --- a/libc/inc/ipc/sem.h +++ b/libc/inc/ipc/sem.h @@ -12,6 +12,9 @@ + + + /// @brief flags for semop #define SEM_UNDO 0x1000 /* undo the operation on exit */ @@ -29,6 +32,7 @@ + /// @brief Optional argument for semctl() function union semun { int val; /* value for SETVAL */ @@ -37,15 +41,28 @@ union semun { struct seminfo *__buf; /* buffer for IPC_INFO */ }; +/// @brief Single Semaphore +struct sem{ + unsigned short sem_val; /*Semaphore Value*/ + pid_t sem_pid; /*Process ID of the last operation*/ + //unsigned short semncnt; /*Number of processes waiting of semaphore*/ + unsigned short sem_zcnt; /*Number of processes waiting for the value to become 0*/ +}; + /// @brief Semaphore set struct semid_ds { - struct ipc_perm sem_perm; /* Ownership and permissions */ + pid_t owner; /* Ownership and permissions */ + key_t key; /*IPC_KEY associated to the semaphore set*/ + int semid; /*semid associated to the semaphore set*/ time_t sem_otime; /* Last semop time */ time_t sem_ctime; /* Last change time */ unsigned long sem_nsems; /* No. of semaphores in set */ + struct sem *sems; /*all the semaphores*/ }; + + /// @brief Buffer to use with the semaphore IPC. struct sembuf { /// Semaphore index in array. diff --git a/mentos/inc/sys/ipc.h b/mentos/inc/sys/ipc.h index 6c0c2ff..9290540 100644 --- a/mentos/inc/sys/ipc.h +++ b/mentos/inc/sys/ipc.h @@ -8,12 +8,14 @@ #include "stddef.h" #define IPC_CREAT 01000 ///< Create key if key does not exist. + #define IPC_EXCL 02000 ///< Fail if key exists. #define IPC_NOWAIT 04000 ///< Return error on wait. #define IPC_RMID 0 ///< Remove identifier. #define IPC_SET 1 ///< Set `ipc_perm' options. #define IPC_STAT 2 ///< Get `ipc_perm' options. #define IPC_INFO 3 ///< See ipcs. +#define IPC_PRIVATE 4 ///< assures getting a new ipc_key. /// @brief Holds details about IPCs. typedef struct ipc_perm_t { diff --git a/mentos/src/ipc/sem.c b/mentos/src/ipc/sem.c index 1c1c547..733759b 100644 --- a/mentos/src/ipc/sem.c +++ b/mentos/src/ipc/sem.c @@ -9,58 +9,130 @@ #define __DEBUG_HEADER__ "[IPCsem]" ///< Change header. #define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level. #include "io/debug.h" // Include debugging functions. -#include //test -#include "ipc/sem.h" //test +#include "klib/list.h" +#include +#include "ipc/sem.h" +#include "mem/slab.h" +#include "system/signal.h" +#include "sys/errno.h" #include "system/panic.h" +/* + 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 +*/ + +/// @brief to initialize a single semaphore +/// @param temp the pointer to the struct of the semaphore +void sem_init(struct sem * temp){ + temp -> sem_val = 0; /*default*/ + temp -> sem_pid = sys_getpid(); + temp -> sem_zcnt = 0; /*default*/ +} + +/// @brief to initialize a semid struct (set of semaphores) +/// @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 +void semid_init(struct semid_ds * temp, key_t key, int nsems){ + temp -> owner = sys_getpid(); + temp -> key = key; + temp -> semid = key+1; //temporary -> gonna need a way to compute IPCKEY -> semid + 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; isems[i])); + } +} + +///@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){ + 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); + printf("value: %d\n", temp->sems[i].sem_val); + printf("pid of last op: %d\n", temp->sems[i].sem_pid); + printf("process waiting: %d\n", temp->sems[i].sem_zcnt); + } +} + +int count = 0; //temporary + +/// @brief list of all current active semaphores +list_t *current_semaphores; + +int count_ipc_private = 2; //temporary -> to implement the IPC_PRIVATE mechanism -//test long sys_semget(key_t key, int nsems, int semflg) { - /*PSEUDOCODE (todo)*/ + struct semid_ds *temp = NULL; + //check if nsems is a valid value + if(nsems<=0){ + printf("Errore NSEMS\n"); //debuggin purposes + errno = EINVAL; + return -1; + } + if (count == 0){ //first ever to call semget + current_semaphores = list_create(); //init the list + temp = (struct semid_ds *)kmalloc(sizeof(struct semid_ds)); //create the first one + semid_init(temp, key, nsems); + list_insert_front(current_semaphores, temp); + count++; + return temp->semid; + } + if (key == IPC_PRIVATE){ // need to find a unique key + int flag = 1; + while (1){ //exit when i find a unique key + listnode_foreach(listnode, current_semaphores){ + if (((struct semid_ds *)listnode->value)->key == count_ipc_private) + flag = 0; + } + if (flag==1)break; + flag = 1; + count_ipc_private*=3; //multiply to try to find a unique key + } + //we have the key + temp = (struct semid_ds *)kmalloc(sizeof(struct semid_ds)); + semid_init(temp, count_ipc_private, nsems); + list_insert_front(current_semaphores, temp); + return temp -> semid; + } + int flag = 0; + int temp_semid = -1; + listnode_foreach(listnode, current_semaphores){ //iterate through the list + if (((struct semid_ds *)listnode->value)->key == key){ //if we find a semid with the given key + temp_semid = ((struct semid_ds *)listnode->value)->semid; //saving the semid + flag = 1; //found + } + } + if (flag==0){ //unique key - /* - Check if num_sems is a valid value - */ - /* .... */ + if (semflg & IPC_CREAT){ //and i want to create a semaphore set with it + temp = (struct semid_ds *)kmalloc(sizeof(struct semid_ds)); + semid_init(temp, key, nsems); + list_insert_front(current_semaphores, temp); + return temp -> semid; + } + errno = EINVAL; //invalid argument bc it is a unique key but with no IPC_CREAT + return -1; + } + if(semflg & IPC_EXCL){ //error, the sem set already exist + errno = EEXIST; + return -1; + } + return temp_semid; //return the correspondent semid - - /* - Compute the IPC id using key. (Hashing Algorithm?) - */ - /* .... */ - - - /* - Check if a semaphore set with the ID already exists (and then check for IPC_EXCL flag) - */ - /* .... */ - - /* - If the semaphore does not exist, create a new semaphore set with the specified number of sems - (allocation, initialization...) - */ - /* .... */ - - /* - Set the semaphore set permissions (default 0666) - */ - /* .... */ - - - /* - Return the new semaphore set ID - */ - /* .... */ - - - - - - //printf("qui"); test //TODO("Not implemented"); - return 0; } long sys_semop(int semid, struct sembuf *sops, unsigned nsops) diff --git a/programs/tests/t_semget.c b/programs/tests/t_semget.c index ac221e3..4110753 100644 --- a/programs/tests/t_semget.c +++ b/programs/tests/t_semget.c @@ -1,17 +1,29 @@ //test #include "ipc/sem.h" #include "stdio.h" +#include "ipc/ipc.h" int main() { - key_t i = ftok("/test80.txt", 5); //checking if the syscalls are already linked - //long i = semget(0,0,0); - - if (i == -1){ + //key_t i = ftok("/test1.txt", 5); //checking ftok + long id = semget(2,2,0); //first semaphores + + 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 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); + /*if (i == -1){ printf("Error with IPC_KEY\n"); return -1; - } + }*/ + - printf("IPC_KEY: %d\n", i); return 0; } \ No newline at end of file