Fix permission management for IPC and also for EXT2.

This commit is contained in:
Enrico Fraccaroli (Galfurian)
2023-05-23 13:40:02 -04:00
parent e7c0334ac0
commit 3ae9258347
12 changed files with 394 additions and 400 deletions
+18 -13
View File
@@ -17,14 +17,15 @@
/// @brief List of commands for semctl function.
/// @{
#define GETPID 11 ///< Get sempid.
#define GETVAL 12 ///< Get semval.
#define GETALL 13 ///< Get all semval's.
#define GETNCNT 14 ///< Get semncnt.
#define GETZCNT 15 ///< Get semzcnt.
#define SETVAL 16 ///< Set semval.
#define SETALL 17 ///< Set all semval's.
#define GETNSEMS 19 ///< Get sem_nsems
#define GETPID 11 ///< Get sempid.
#define GETVAL 12 ///< Get semval.
#define GETALL 13 ///< Get all semval's.
#define GETNCNT 14 ///< Get semncnt.
#define GETZCNT 15 ///< Get semzcnt.
#define SETVAL 16 ///< Set semval.
#define SETALL 17 ///< Set all semval's.
#define SEM_STAT 18 ///< Return a semid_ds structure.
#define SEM_INFO 19 ///< Return a seminfo structure.
/// }@
@@ -44,12 +45,12 @@ union semun {
/// @brief Single Semaphore.
struct sem {
/// @brief Semaphore Value.
unsigned short sem_val;
/// @brief Process ID of the last operation.
pid_t sem_pid;
/// @brief Number of processes waiting of semaphore.
//unsigned short semncnt;
/// @brief Semaphore Value.
unsigned short sem_val;
/// @brief Number of processes waiting for the semaphore.
unsigned short sem_ncnt;
/// @brief Number of processes waiting for the value to become 0
unsigned short sem_zcnt;
};
@@ -63,7 +64,7 @@ struct semid_ds {
/// @brief Last change time.
time_t sem_ctime;
/// @brief Number of semaphores in set.
unsigned long sem_nsems;
unsigned short sem_nsems;
};
/// @brief Buffer to use with the semaphore IPC.
@@ -78,6 +79,10 @@ struct sembuf {
#ifdef __KERNEL__
/// @brief Initializes the semaphore system.
/// @return int
int sem_init();
/// @brief Get a System V semaphore set identifier.
/// @param key can be used either to obtain the identifier of a previously
/// created semaphore set, or to create a new set.
+69 -59
View File
@@ -4,10 +4,10 @@
/// See LICENSE.md for details.
// Setup the logging for this file (do this before any other include).
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[EXT2 ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[EXT2 ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "fs/ext2.h"
#include "process/scheduler.h"
@@ -478,46 +478,52 @@ static const char *time_to_string(uint32_t time)
return s;
}
static inline int __ext2_valid_permissions(
const task_struct *task,
const mode_t mask,
const uid_t uid,
const gid_t gid,
const int usr,
const int grp,
const int oth)
{
// The task is the owner.
if ((mask & usr) && (task->uid == uid))
return 1;
// The task belongs to the correct group.
if ((mask & grp) && (task->gid == gid))
return 1;
// The task is not the owner and does not belong to the correct group.
if ((mask & oth) && (task->uid != uid) && (task->gid != gid))
return 1;
return 0;
}
/// @brief Checks if the requests in flags are valid.
/// @param flags the flags to check.
/// @param mask the mask to check against.
/// @param uid the uid of the owner.
/// @param gid the gid of the owner.
/// @return true on success, false otherwise.
static bool_t ext2_valid_permissions(int flags, mode_t mask, uid_t uid, gid_t gid)
/// @return 1 on success, 0 otherwise.
static int ext2_valid_permissions(int flags, mode_t mask, uid_t uid, gid_t gid)
{
// Check the permissions.
task_struct *task = scheduler_get_current_process();
if (task == NULL) {
pr_warning("Failed to get the current running process, assuming we are booting.\n");
return true;
return 1;
}
// The current task is the owner.
if (task->uid == uid) {
if (!bitmask_check(mask, S_IRUSR))
return false;
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(mask, S_IWUSR))
return false;
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(mask, S_IRUSR) || !bitmask_check(mask, S_IWUSR)))
return false;
}
if (task->gid == gid) {
if (!bitmask_check(mask, S_IRGRP))
return false;
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(mask, S_IWGRP))
return false;
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(mask, S_IRGRP) || !bitmask_check(mask, S_IWGRP)))
return false;
}
if ((task->uid != uid) && (task->gid != gid)) {
if (!bitmask_check(mask, S_IROTH))
return false;
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(mask, S_IWOTH))
return false;
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(mask, S_IROTH) || !bitmask_check(mask, S_IWOTH)))
return false;
}
return true;
// Init, and all root processes have full permissions.
if ((task->pid == 0) || (task->uid == 0) || (task->gid == 0))
return 1;
if (((flags & O_RDONLY) == O_RDONLY) && __ext2_valid_permissions(task, mask, uid, gid, S_IRUSR, S_IRGRP, S_IROTH))
return 1;
if (((flags & O_WRONLY) == O_WRONLY) && __ext2_valid_permissions(task, mask, uid, gid, S_IWUSR, S_IWGRP, S_IWOTH))
return 1;
if (((flags & O_RDWR) == O_RDWR) && __ext2_valid_permissions(task, mask, uid, gid, S_IRUSR | S_IWUSR, S_IRGRP | S_IWGRP, S_IROTH | S_IWOTH))
return 1;
return 0;
}
/// @brief Dumps on debugging output the superblock.
@@ -756,12 +762,12 @@ static void ext2_set_bitmap_bit(uint8_t *buffer, uint32_t linear_index, ext2_blo
/// @param fs the ext2 filesystem structure.
/// @param cache the cache from which we read the bgdt data.
/// @param linear_index the output variable where we store the linear indes to the free inode.
/// @return true if we found a free inode, false otherwise.
static inline bool_t ext2_find_free_inode_in_group(
/// @return 1 if we found a free inode, 0 otherwise.
static inline int ext2_find_free_inode_in_group(
ext2_filesystem_t *fs,
uint8_t *cache,
uint32_t *linear_index,
bool_t skip_reserved)
int skip_reserved)
{
for ((*linear_index) = 0; (*linear_index) < fs->superblock.inodes_per_group; ++(*linear_index)) {
// If we need to skip the reserved inodes, we skip the round if the
@@ -770,9 +776,9 @@ static inline bool_t ext2_find_free_inode_in_group(
continue;
// Check if the entry is free.
if (!ext2_check_bitmap_bit(cache, *linear_index))
return true;
return 1;
}
return false;
return 0;
}
/// @brief Searches for a free inode inside the Block Group Descriptor Table (BGDT).
@@ -780,8 +786,8 @@ static inline bool_t ext2_find_free_inode_in_group(
/// @param cache the cache from which we read the bgdt data.
/// @param group_index the output variable where we store the group index.
/// @param linear_index the output variable where we store the linear indes to the free inode.
/// @return true if we found a free inode, false otherwise.
static inline bool_t ext2_find_free_inode(
/// @return 1 if we found a free inode, 0 otherwise.
static inline int ext2_find_free_inode(
ext2_filesystem_t *fs,
uint8_t *cache,
uint32_t *group_index,
@@ -795,7 +801,7 @@ static inline bool_t ext2_find_free_inode(
// Find the first free inode. We need to ask to skip reserved inodes,
// only if we are in group 0.
if (ext2_find_free_inode_in_group(fs, cache, linear_index, (*group_index) == 0))
return true;
return 1;
}
// Get the group and bit index of the first free block.
for ((*group_index) = 0; (*group_index) < fs->block_groups_count; ++(*group_index)) {
@@ -804,15 +810,15 @@ static inline bool_t ext2_find_free_inode(
// Read the block bitmap.
if (ext2_read_block(fs, fs->block_groups[(*group_index)].inode_bitmap, cache) < 0) {
pr_err("Failed to read the inode bitmap for group `%d`.\n", (*group_index));
return false;
return 0;
}
// Find the first free inode. We need to ask to skip reserved
// inodes, only if we are in group 0.
if (ext2_find_free_inode_in_group(fs, cache, linear_index, (*group_index) == 0))
return true;
return 1;
}
}
return false;
return 0;
}
/// @brief Searches for a free block inside the group data loaded inside the cache.
@@ -820,23 +826,23 @@ static inline bool_t ext2_find_free_inode(
/// @param cache the cache from which we read the bgdt data.
/// @param group_index the output variable where we store the group index.
/// @param linear_index the output variable where we store the linear indes to the free block.
/// @return true if we found a free block, false otherwise.
static inline bool_t ext2_find_free_block_in_group(ext2_filesystem_t *fs, uint8_t *cache, uint32_t *linear_index)
/// @return 1 if we found a free block, 0 otherwise.
static inline int ext2_find_free_block_in_group(ext2_filesystem_t *fs, uint8_t *cache, uint32_t *linear_index)
{
for ((*linear_index) = 0; (*linear_index) < fs->superblock.blocks_per_group; ++(*linear_index)) {
// Check if the entry is free.
if (!ext2_check_bitmap_bit(cache, *linear_index))
return true;
return 1;
}
return false;
return 0;
}
/// @brief Searches for a free block.
/// @param fs the ext2 filesystem structure.
/// @param cache the cache from which we read the bgdt data.
/// @param linear_index the output variable where we store the linear indes to the free block.
/// @return true if we found a free block, false otherwise.
static inline bool_t ext2_find_free_block(
/// @return 1 if we found a free block, 0 otherwise.
static inline int ext2_find_free_block(
ext2_filesystem_t *fs,
uint8_t *cache,
uint32_t *group_index,
@@ -849,14 +855,14 @@ static inline bool_t ext2_find_free_block(
// Read the block bitmap.
if (ext2_read_block(fs, fs->block_groups[(*group_index)].block_bitmap, cache) < 0) {
pr_err("Failed to read the block bitmap for group `%d`.\n", (*group_index));
return false;
return 0;
}
// Find the first free block.
if (ext2_find_free_block_in_group(fs, cache, linear_index))
return true;
return 1;
}
}
return false;
return 0;
}
/// @brief Reads the superblock from the block device associated with this filesystem.
@@ -1614,8 +1620,8 @@ ext2_dirent_t *ext2_direntry_iterator_get(ext2_direntry_iterator_t *iterator)
/// @brief Check if the iterator is valid.
/// @param iterator the iterator to check.
/// @return true if valid, false otherwise.
bool_t ext2_direntry_iterator_valid(ext2_direntry_iterator_t *iterator)
/// @return 1 if valid, 0 otherwise.
int ext2_direntry_iterator_valid(ext2_direntry_iterator_t *iterator)
{
return iterator->direntry != NULL;
}
@@ -1679,14 +1685,14 @@ void ext2_direntry_iterator_next(ext2_direntry_iterator_t *iterator)
iterator->direntry = ext2_direntry_iterator_get(iterator);
}
static inline bool_t ext2_directory_is_empty(ext2_filesystem_t *fs, uint8_t *cache, ext2_inode_t *inode)
static inline int ext2_directory_is_empty(ext2_filesystem_t *fs, uint8_t *cache, ext2_inode_t *inode)
{
ext2_direntry_iterator_t it = ext2_direntry_iterator_begin(fs, cache, inode);
for (; ext2_direntry_iterator_valid(&it); ext2_direntry_iterator_next(&it)) {
if (it.direntry->inode != 0)
return false;
return 0;
}
return true;
return 1;
}
// ============================================================================
@@ -2344,6 +2350,7 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode)
pr_err("A file or directory already exists at `%s` (O_CREAT | O_EXCL).\n", absolute_path);
return NULL;
} else if (bitmask_check(flags, O_DIRECTORY) && (direntry.file_type != ext2_file_type_directory)) {
pr_err("That is not a directory.");
errno = ENOTDIR;
return NULL;
}
@@ -2366,7 +2373,10 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode)
return NULL;
}
ext2_dump_inode(&inode);
if (!ext2_valid_permissions(flags, inode.mode, inode.uid, inode.gid)) {
pr_err("Task does not have access permission.\n");
errno = EACCES;
return NULL;
}
@@ -2664,7 +2674,7 @@ static ssize_t ext2_getdents(vfs_file_t *file, dirent_t *dirp, off_t doff, size_
return -ENOENT;
}
uint32_t current = 0;
ssize_t written = 0;
ssize_t written = 0;
// Allocate the cache.
uint8_t *cache = kmem_cache_alloc(fs->ext2_buffer_cache, GFP_KERNEL);
// Clean the cache.
+4 -4
View File
@@ -4,10 +4,10 @@
/// See LICENSE.md for details.
// Setup the logging for this file (do this before any other include).
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[VFS ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[VFS ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "fs/vfs.h"
#include "process/scheduler.h"
+18 -16
View File
@@ -11,35 +11,31 @@
#include "fcntl.h"
int ipc_check_perm(
task_struct *task,
struct ipc_perm *perm,
int usr,
int grp,
int oth)
{
// Get the calling task.
task_struct *task = scheduler_get_current_process();
assert(task && "Failed to get the current running process.");
assert(perm && "Received a NULL ipc_perm.");
// Init process has unlimited power.
if (task->pid == 0)
return 1;
assert(task && "Received a NULL task.");
assert(perm && "Received a NULL perm.");
int check_parent = (perm->key < 0) && task->parent && (task->parent->pid != 0);
if ((perm->mode & usr)) {
if (perm->mode & usr) {
if ((perm->uid == task->uid) || (perm->cuid == task->uid))
return 1;
if (check_parent && ((perm->uid == task->parent->uid) || (perm->cuid == task->parent->uid)))
return 1;
}
if ((perm->mode & grp)) {
if (perm->mode & grp) {
if ((perm->gid == task->gid) || (perm->cgid == task->gid))
return 1;
if (check_parent && ((perm->gid == task->parent->gid) || (perm->cgid == task->parent->gid)))
return 1;
}
if ((perm->mode & oth)) {
if (check_parent && ((perm->uid == task->parent->uid) || (perm->cuid == task->parent->uid)))
if (perm->mode & oth) {
if (check_parent && ((perm->uid != task->parent->uid) || (perm->cuid != task->parent->uid)))
return 1;
if (check_parent && ((perm->gid == task->parent->gid) || (perm->cgid == task->parent->gid)))
if (check_parent && ((perm->gid != task->parent->gid) || (perm->cgid != task->parent->gid)))
return 1;
}
return 0;
@@ -47,12 +43,18 @@ int ipc_check_perm(
int ipc_valid_permissions(int flags, struct ipc_perm *perm)
{
// If the key is negative, it means it was a private key.
if ((flags & O_RDONLY) && ipc_check_perm(perm, S_IRUSR, S_IRGRP, S_IROTH))
// Get the calling task.
task_struct *task = scheduler_get_current_process();
assert(task && "Failed to get the current running process.");
// Init, and all root processes have full permissions.
if ((task->pid == 0) || (task->uid == 0) || (task->gid == 0))
return 1;
if ((flags & O_WRONLY) && ipc_check_perm(perm, S_IWUSR, S_IWGRP, S_IWOTH))
// Check permissions.
if (((flags & O_RDONLY) == O_RDONLY) && ipc_check_perm(task, perm, S_IRUSR, S_IRGRP, S_IROTH))
return 1;
if ((flags & O_RDWR) && ipc_check_perm(perm, S_IRUSR | S_IWUSR, S_IRGRP | S_IWGRP, S_IROTH | S_IWOTH))
if (((flags & O_WRONLY) == O_WRONLY) && ipc_check_perm(task, perm, S_IWUSR, S_IWGRP, S_IWOTH))
return 1;
if (((flags & O_RDWR) == O_RDWR) && ipc_check_perm(task, perm, S_IRUSR | S_IWUSR, S_IRGRP | S_IWGRP, S_IROTH | S_IWOTH))
return 1;
return 0;
}
+242 -251
View File
@@ -52,8 +52,9 @@
#include "fcntl.h"
///@brief A value to compute the semid value.
int semid_assign = 0;
int __sem_id = 0;
/// @brief Semaphore management structure.
typedef struct {
/// @brief Semaphore ID associated to the semaphore set.
int id;
@@ -61,14 +62,12 @@ typedef struct {
struct semid_ds semid;
/// @brief List of all the semaphores.
struct sem *sems;
/// Reference inside the list of semaphore management structures.
list_head list;
} sem_info_t;
/// @brief List of all current active semaphores.
list_t semaphores_list = {
.head = NULL,
.tail = NULL,
.size = 0
};
list_head semaphores_list;
// ============================================================================
// KEY GENERATION (Private)
@@ -93,83 +92,50 @@ static inline int ipc_sem_rand()
// MEMORY MANAGEMENT (Private)
// ============================================================================
/// @brief Allocates the memory for an array of semaphores.
/// @param nsems number of semaphores in the array.
/// @return a pointer to the allocated array of semaphores.
static inline struct sem *__sem_set_alloc(int nsems)
/// @brief Allocates the memory for semaphore management structure.
/// @param key IPC_KEY associated with the set of semaphores.
/// @param nsems number of semaphores to initialize.
/// @param semflg flags used to create the set of semaphores.
/// @return a pointer to the allocated semaphore management structure.
static inline sem_info_t *__sem_info_alloc(key_t key, int nsems, int semflg)
{
// Allocate the memory.
struct sem *ptr = (struct sem *)kmalloc(sizeof(struct sem) * nsems);
sem_info_t *sem_info = (sem_info_t *)kmalloc(sizeof(sem_info_t));
// Check the allocated memory.
assert(ptr && "Failed to allocate memory for the array of semaphores.");
assert(sem_info && "Failed to allocate memory for a semaphore management structure.");
// Clean the memory.
memset(ptr, 0, sizeof(struct sem));
return ptr;
}
/// @brief Frees the memory of an array of semaphores.
/// @param ptr the pointer to the array of semaphores.
static inline void __sem_set_dealloc(struct sem *ptr)
{
assert(ptr && "Received a NULL pointer.");
kfree(ptr);
}
/// @brief Initializes a single semaphore.
/// @param ptr the pointer to the single semaphore.
static inline void __sem_init(struct sem *ptr)
{
ptr->sem_val = 0;
ptr->sem_pid = sys_getpid();
ptr->sem_zcnt = 0;
}
/// @brief Allocates the memory for a semid structure.
/// @return a pointer to the allocated semid structure.
static inline struct sem_info_t *__sem_info_alloc(int nsems)
{
// Allocate the memory.
sem_info_t *ptr = (sem_info_t *)kmalloc(sizeof(sem_info_t));
// Check the allocated memory.
assert(ptr && "Failed to allocate memory for a semid structure.");
// Clean the memory.
memset(ptr, 0, sizeof(sem_info_t));
memset(sem_info, 0, sizeof(sem_info_t));
// Allocate the memory for semaphores.
ptr->sems = (struct sem *)kmalloc(sizeof(struct sem) * nsems);
sem_info->sems = (struct sem *)kmalloc(sizeof(struct sem) * nsems);
// Check the allocated memory.
assert(ptr && "Failed to allocate memory for a semid structure.");
assert(sem_info->sems && "Failed to allocate memory for a set of semaphores.");
// Clean the memory.
memset(ptr, 0, sizeof(sem_info_t));
return ptr;
}
/// @brief Frees the memory of a semid structure.
/// @param ptr pointer to the semid structure.
static inline void __sem_info_dealloc(struct semid_ds *ptr)
{
assert(ptr && "Received a NULL pointer.");
// Deallocate the array of semaphores.
__sem_set_dealloc(ptr->sems);
// Deallocate the semid memory.
kfree(ptr);
}
/// @brief Initializes a semid struct.
/// @param ptr 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 __sem_info_init(struct semid_ds *ptr, key_t key, int nsems, int semflg)
{
assert(ptr && "Received a NULL pointer.");
ptr->sem_perm = register_ipc(key, semflg & 0x1FF);
ptr->sem_otime = 0;
ptr->sem_ctime = 0;
ptr->sem_nsems = nsems;
ptr->sems = __sem_set_alloc(nsems);
memset(sem_info->sems, 0, sizeof(struct sem) * nsems);
// Initialize its values.
sem_info->id = ++__sem_id;
sem_info->semid.sem_perm = register_ipc(key, semflg & 0x1FF);
sem_info->semid.sem_otime = 0;
sem_info->semid.sem_ctime = 0;
sem_info->semid.sem_nsems = nsems;
for (int i = 0; i < nsems; i++) {
__sem_init(&ptr->sems[i]);
sem_info->sems[i].sem_pid = sys_getpid();
sem_info->sems[i].sem_val = 0;
sem_info->sems[i].sem_ncnt = 0;
sem_info->sems[i].sem_zcnt = 0;
}
// Return the semaphore management structure.
return sem_info;
}
/// @brief Frees the memory of a semaphore management structure.
/// @param sem_info pointer to the semaphore management structure.
static inline void __sem_info_dealloc(sem_info_t *sem_info)
{
assert(sem_info && "Received a NULL pointer.");
// Deallocate the array of semaphores.
kfree(sem_info->sems);
// Deallocate the semid memory.
kfree(sem_info);
}
// ============================================================================
@@ -179,17 +145,17 @@ static inline void __sem_info_init(struct semid_ds *ptr, key_t key, int nsems, i
/// @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_by_id(int semid)
static inline sem_info_t *__list_find_sem_info_by_id(int semid)
{
struct semid_ds *sem_set;
sem_info_t *sem_info;
// Iterate through the list of semaphore set.
listnode_foreach(listnode, &semaphores_list)
list_for_each_decl(it, &semaphores_list)
{
// Get the current list of semaphore set.
sem_set = (struct semid_ds *)listnode->value;
// Get the current entry.
sem_info = list_entry(it, sem_info_t, list);
// If semaphore set is valid, check the id.
if (sem_set && (sem_set->semid == semid))
return sem_set;
if (sem_info && (sem_info->id == semid))
return sem_info;
}
return NULL;
}
@@ -197,101 +163,110 @@ static inline struct semid_ds *__find_semaphore_by_id(int semid)
/// @brief Searches for the semaphore with the given key.
/// @param key the key we are searching.
/// @return the semaphore with the given key.
static inline struct semid_ds *__find_semaphore_by_key(key_t key)
static inline sem_info_t *__list_find_sem_info_by_key(key_t key)
{
struct semid_ds *sem_set;
sem_info_t *sem_info;
// Iterate through the list of semaphore set.
listnode_foreach(listnode, &semaphores_list)
list_for_each_decl(it, &semaphores_list)
{
// Get the current list of semaphore set.
sem_set = (struct semid_ds *)listnode->value;
// Get the current entry.
sem_info = list_entry(it, sem_info_t, list);
// If semaphore set is valid, check the id.
if (sem_set && (sem_set->sem_perm.key == key))
return sem_set;
if (sem_info && (sem_info->semid.sem_perm.key == key))
return sem_info;
}
return NULL;
}
static inline void __list_add_sem_info(sem_info_t *sem_info)
{
assert(sem_info && "Received a NULL pointer.");
// Add the new sem_info at the end.
list_head_insert_before(&sem_info->list, &semaphores_list);
}
static inline void __list_remove_sem_info(sem_info_t *sem_info)
{
assert(sem_info && "Received a NULL pointer.");
// Delete the sem_info from the list.
list_head_remove(&sem_info->list);
}
// ============================================================================
// SYSTEM FUNCTIONS
// ============================================================================
int sem_init()
{
list_head_init(&semaphores_list);
return 0;
}
long sys_semget(key_t key, int nsems, int semflg)
{
struct semid_ds *sem_set = NULL;
sem_info_t *sem_info = NULL;
// Check if nsems is less than 0 or greater than the maximum number of
// semaphores per semaphore set.
if ((nsems < 0) || (nsems > SEM_SET_MAX)) {
pr_err("Wrong number of semaphores for semaphore set.\n");
return -EINVAL;
}
// Need to find a unique key.
if (key == IPC_PRIVATE) {
// Exit when i find a unique key.
do {
key = -ipc_sem_rand();
} while (__find_semaphore_by_key(key));
} while (__list_find_sem_info_by_key(key));
// We have a unique key, create the semaphore set.
sem_set = __semid_alloc();
// Initialize the semaphore set.
__semid_init(sem_set, key, nsems, semflg);
sem_info = __sem_info_alloc(key, nsems, semflg);
// Add the semaphore set to the list.
list_insert_front(&semaphores_list, sem_set);
// Return the id of the semaphore set.
return sem_set->semid;
}
__list_add_sem_info(sem_info);
} else {
// Get the semaphore set if it exists.
sem_info = __list_find_sem_info_by_key(key);
// Get the semaphore set if it exists.
sem_set = __find_semaphore_by_key(key);
// Check if a semaphore set with the given key already exists, but nsems is
// larger than the number of semaphores in that set.
if (sem_info && (nsems > sem_info->semid.sem_nsems)) {
pr_err("Wrong number of semaphores for and existing semaphore set.\n");
return -EINVAL;
}
// Check if a semaphore set with the given key already exists, but nsems is
// larger than the number of semaphores in that set.
if (sem_set && (nsems > sem_set->sem_nsems)) {
pr_err("Wrong number of semaphores for and existing semaphore set.\n");
return -EINVAL;
}
// Check if no semaphore set exists for the given key and semflg did not
// specify IPC_CREAT.
if (!sem_info && !(semflg & IPC_CREAT)) {
pr_err("No semaphore set exists for the given key and semflg did not specify IPC_CREAT.\n");
return -ENOENT;
}
// Check if no semaphore set exists for the given key and semflg did not
// specify IPC_CREAT.
if (!sem_set && !(semflg & IPC_CREAT)) {
pr_err("No semaphore set exists for the given key and semflg did not specify IPC_CREAT.\n");
return -ENOENT;
}
// Check if IPC_CREAT and IPC_EXCL were specified in semflg, but a semaphore
// set already exists for key.
if (sem_info && (semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
pr_err("IPC_CREAT and IPC_EXCL were specified in semflg, but a semaphore set already exists for key.\n");
return -EEXIST;
}
// Check if IPC_CREAT and IPC_EXCL were specified in semflg, but a semaphore
// set already exists for key.
if (sem_set && (semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
pr_err("IPC_CREAT and IPC_EXCL were specified in semflg, but a semaphore set already exists for key.\n");
return -EEXIST;
}
// Check if the semaphore set exists for the given key, but the calling
// process does not have permission to access the set.
if (sem_set && !ipc_valid_permissions(semflg, &sem_set->sem_perm)) {
pr_err("The semaphore set exists for the given key, but the calling process does not have permission to access the set.\n");
return -EACCES;
}
// If the semaphore set does not exist we need to create a new one.
if (sem_set == NULL) {
// Create the semaphore set.
sem_set = __semid_alloc();
// Initialize the semaphore set.
__semid_init(sem_set, key, nsems, semflg);
// Add the semaphore set to the list.
list_insert_front(&semaphores_list, sem_set);
// Check if the semaphore set exists for the given key, but the calling
// process does not have permission to access the set.
if (sem_info && !ipc_valid_permissions(semflg, &sem_info->semid.sem_perm)) {
pr_err("The semaphore set exists for the given key, but the calling process does not have permission to access the set.\n");
return -EACCES;
}
// If the semaphore set does not exist we need to create a new one.
if (sem_info == NULL) {
// Create the semaphore set.
sem_info = __sem_info_alloc(key, nsems, semflg);
// Add the semaphore set to the list.
__list_add_sem_info(sem_info);
}
}
// Return the id of the semaphore set.
return sem_set->semid;
return sem_info->id;
}
long sys_semop(int semid, struct sembuf *sops, unsigned nsops)
{
struct semid_ds *sem_set;
unsigned short sem_num;
struct sem *semaphore;
sem_info_t *sem_info = NULL;
// The semid is less than zero.
if (semid < 0) {
pr_err("The semid is less than zero.\n");
@@ -307,58 +282,49 @@ long sys_semop(int semid, struct sembuf *sops, unsigned nsops)
pr_err("The value of nsops is negative.\n");
return -EINVAL;
}
// Search for the semaphore.
sem_set = __find_semaphore_by_id(semid);
sem_info = __list_find_sem_info_by_id(semid);
// The semaphore set doesn't exist.
if (!sem_set) {
if (!sem_info) {
pr_err("The semaphore set doesn't exist.\n");
return -EINVAL;
}
// Get the semaphore number.
sem_num = sops->sem_num;
// The value of sem_num is less than 0 or greater than or equal to the number of semaphores in the set.
if ((sem_num < 0) || (sem_num >= sem_set->sem_nsems)) {
if ((sops->sem_num < 0) || (sops->sem_num >= sem_info->semid.sem_nsems)) {
pr_err("The value of sem_num is less than 0 or greater than or equal to the number of semaphores in the set.\n");
return -EFBIG;
}
// Check if the semaphore set exists for the given key, but the calling
// process does not have permission to access the set.
if (sem_set && !ipc_valid_permissions(O_RDWR, &sem_set->sem_perm)) {
if (sem_info && !ipc_valid_permissions(O_RDWR, &sem_info->semid.sem_perm)) {
pr_err("The semaphore set exists for the given key, but the calling process does not have permission to access the set.\n");
return -EACCES;
}
// Update semop time.
sem_set->sem_otime = sys_time(NULL);
// Get the specific semaphore.
semaphore = &sem_set->sems[sem_num];
sem_info->semid.sem_otime = sys_time(NULL);
// If the operation is negative then we need to check for possible blocking
// operation. If the value of the sem were to become negative then we return
// a special value.
if (((int)semaphore->sem_val + (int)sops->sem_op) < 0) {
if (((int)sem_info->sems[sops->sem_num].sem_val + (int)sops->sem_op) < 0) {
// The value would become negative, we cannot perform the operation.
return -EAGAIN;
}
// Update the semaphore value.
semaphore->sem_val += sops->sem_op;
sem_info->sems[sops->sem_num].sem_val += sops->sem_op;
// Update the pid of the process that did last op.
semaphore->sem_pid = sys_getpid();
sem_info->sems[sops->sem_num].sem_pid = sys_getpid();
// Update the time.
sem_set->sem_ctime = sys_time(NULL);
sem_info->semid.sem_ctime = sys_time(NULL);
return 0;
}
long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
{
struct semid_ds *sem_set;
sem_info_t *sem_info = NULL;
// Search for the semaphore.
sem_set = __find_semaphore_by_id(semid);
sem_info = __list_find_sem_info_by_id(semid);
// The semaphore set doesn't exist.
if (!sem_set) {
if (!sem_info) {
pr_err("The semaphore set doesn't exist.\n");
return -EINVAL;
}
@@ -371,50 +337,43 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
// Remove the semaphore set; any processes blocked is awakened (errno set to
// EIDRM); no argument required.
case IPC_RMID:
if ((sem_set->sem_perm.uid != task->uid) && (sem_set->sem_perm.cuid != task->uid)) {
if ((sem_info->semid.sem_perm.uid != task->uid) && (sem_info->semid.sem_perm.cuid != task->uid)) {
pr_err("The calling process is not the creator or the owner of the semaphore set.\n");
return -EPERM;
}
// Remove the set from the list.
list_remove_node(&semaphores_list, list_find(&semaphores_list, sem_set));
__list_remove_sem_info(sem_info);
// Delete the set.
__semid_dealloc(sem_set);
__sem_info_dealloc(sem_info);
break;
// Place a copy of the semid_ds data structure in the buffer pointed to by
// arg.buf.
case IPC_STAT:
// The value of the semnum-th semaphore in the set is initialized to the
// value specified in arg.val.
case SETVAL:
// Check if the index is valid.
if ((semnum < 0) || (semnum >= (sem_info->semid.sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_info->semid.sem_nsems);
return -EINVAL;
}
// Check if the argument is a null pointer.
if (!arg) {
pr_err("The argument is NULL.\n");
return -EINVAL;
}
// Check if the buffer is a null pointer.
if (!arg->buf) {
pr_err("The buffer is NULL.\n");
return -EINVAL;
}
// Check if the array of semaphores inside the buffer is a null pointer.
if (!arg->buf->sems) {
pr_err("The array of semaphores inside the buffer is NULL.\n");
// Checking if the value is valid.
if (arg->val < 0) {
pr_err("The value to set is not valid %d.\n", arg->val);
return -EINVAL;
}
// Check permissions.
if (!ipc_valid_permissions(O_RDONLY, sem_set->sem_perm)) {
if (!ipc_valid_permissions(O_WRONLY, &sem_info->semid.sem_perm)) {
pr_err("The calling process does not have read permission to access the set.\n");
return -EACCES;
}
// Copying all the data.
arg->buf->sem_perm = sem_set->sem_perm;
arg->buf->semid = sem_set->semid;
arg->buf->sem_otime = sem_set->sem_otime;
arg->buf->sem_ctime = sem_set->sem_ctime;
arg->buf->sem_nsems = sem_set->sem_nsems;
for (int i = 0; i < sem_set->sem_nsems; i++) {
arg->buf->sems[i].sem_val = sem_set->sems[i].sem_val;
arg->buf->sems[i].sem_pid = sem_set->sems[i].sem_pid;
arg->buf->sems[i].sem_zcnt = sem_set->sems[i].sem_zcnt;
}
// Setting the value.
sem_info->sems[semnum].sem_val = arg->val;
// Update the last change time.
sem_info->semid.sem_ctime = sys_time(NULL);
return 0;
// Initialize all semaphore in the set referred to by semid, using the
@@ -430,12 +389,39 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
pr_err("The array is NULL.\n");
return -EINVAL;
}
// Check permissions.
if (!ipc_valid_permissions(O_WRONLY, &sem_info->semid.sem_perm)) {
pr_err("The calling process does not have read permission to access the set.\n");
return -EACCES;
}
// Setting the values.
for (unsigned i = 0; i < sem_set->sem_nsems; ++i) {
sem_set->sems[i].sem_val = arg->array[i];
for (unsigned i = 0; i < sem_info->semid.sem_nsems; ++i) {
sem_info->sems[i].sem_val = arg->array[i];
}
// Update the last change time.
sem_set->sem_ctime = sys_time(NULL);
sem_info->semid.sem_ctime = sys_time(NULL);
return 0;
// Place a copy of the semid_ds data structure in the buffer pointed to by
// arg.buf.
case IPC_STAT:
// Check if the argument is a null pointer.
if (!arg) {
pr_err("The argument is NULL.\n");
return -EINVAL;
}
// Check if the buffer is a null pointer.
if (!arg->buf) {
pr_err("The buffer is NULL.\n");
return -EINVAL;
}
// Check permissions.
if (!ipc_valid_permissions(O_RDONLY, &sem_info->semid.sem_perm)) {
pr_err("The calling process does not have read permission to access the set.\n");
return -EACCES;
}
// Copying all the data.
memcpy(arg->buf, &sem_info->semid, sizeof(struct semid_ds));
return 0;
// Retrieve the values of all of the semaphores in the set referred to by
@@ -451,70 +437,76 @@ long sys_semctl(int semid, int semnum, int cmd, union semun *arg)
pr_err("The array is NULL.\n");
return -EINVAL;
}
for (unsigned i = 0; i < sem_set->sem_nsems; ++i) {
arg->array[i] = sem_set->sems[i].sem_val;
for (unsigned i = 0; i < sem_info->semid.sem_nsems; ++i) {
arg->array[i] = sem_info->sems[i].sem_val;
}
return 0;
// The value of the semnum-th semaphore in the set is initialized to the
// value specified in arg.val.
case SETVAL:
// Check if the index is valid.
if ((semnum < 0) || (semnum >= (sem_set->sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_set->sem_nsems);
return -EINVAL;
}
// Check if the argument is a null pointer.
if (!arg) {
pr_err("The argument is NULL.\n");
return -EINVAL;
}
// Checking if the value is valid.
if (arg->val < 0) {
pr_err("The value to set is not valid %d.\n", arg->val);
return -EINVAL;
}
// Setting the value.
sem_set->sems[semnum].sem_val = arg->val;
// Update the last change time.
sem_set->sem_ctime = sys_time(NULL);
return 0;
// Returns the value of the semnum-th semaphore in the set specified by
// semid; no argument required.
case GETVAL:
// Check if the index is valid.
if ((semnum < 0) || (semnum >= (sem_set->sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_set->sem_nsems);
if ((semnum < 0) || (semnum >= (sem_info->semid.sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_info->semid.sem_nsems);
return -EINVAL;
}
return sem_set->sems[semnum].sem_val;
// Check permissions.
if (!ipc_valid_permissions(O_RDONLY, &sem_info->semid.sem_perm)) {
pr_err("The calling process does not have read permission to access the set.\n");
return -EACCES;
}
return sem_info->sems[semnum].sem_val;
// Return the process ID of the last process to perform a semop on the
// semnum-th semaphore.
case GETPID:
// Check if the index is valid.
if ((semnum < 0) || (semnum >= (sem_set->sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_set->sem_nsems);
if ((semnum < 0) || (semnum >= (sem_info->semid.sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_info->semid.sem_nsems);
return -EINVAL;
}
return sem_set->sems[semnum].sem_pid;
// Check permissions.
if (!ipc_valid_permissions(O_RDONLY, &sem_info->semid.sem_perm)) {
pr_err("The calling process does not have read permission to access the set.\n");
return -EACCES;
}
return sem_info->sems[semnum].sem_pid;
// Return the number of processes currently waiting for the resources to
// become available.
case GETNCNT:
// Check if the index is valid.
if ((semnum < 0) || (semnum >= (sem_info->semid.sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_info->semid.sem_nsems);
return -EINVAL;
}
// Check permissions.
if (!ipc_valid_permissions(O_RDONLY, &sem_info->semid.sem_perm)) {
pr_err("The calling process does not have read permission to access the set.\n");
return -EACCES;
}
return sem_info->sems[semnum].sem_ncnt;
// Return the number of processes currently waiting for the value of the
// semnum-th semaphore to become 0.
case GETZCNT:
// Check if the index is valid.
if ((semnum < 0) || (semnum >= (sem_set->sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_set->sem_nsems);
if ((semnum < 0) || (semnum >= (sem_info->semid.sem_nsems))) {
pr_err("Semaphore number out of bound (%d not in [%d, %d])\n", semnum, 0, sem_info->semid.sem_nsems);
return -EINVAL;
}
return sem_set->sems[semnum].sem_zcnt;
// Check permissions.
if (!ipc_valid_permissions(O_RDONLY, &sem_info->semid.sem_perm)) {
pr_err("The calling process does not have read permission to access the set.\n");
return -EACCES;
}
return sem_info->sems[semnum].sem_zcnt;
// Return the number of semaphores in the set.
case GETNSEMS:
return sem_set->sem_nsems;
case SEM_STAT:
pr_err("Not implemented.\n");
return -ENOSYS;
//not a valid argument.
case SEM_INFO:
pr_err("Not implemented.\n");
return -ENOSYS;
// Not a valid argument.
default:
return -EINVAL;
}
@@ -533,7 +525,7 @@ ssize_t procipc_sem_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyte
return -ENOENT;
}
size_t buffer_len = 0, read_pos = 0, write_count = 0, ret = 0;
struct semid_ds *entry = NULL;
sem_info_t *sem_info = NULL;
char buffer[BUFSIZ];
// Prepare a buffer.
@@ -541,25 +533,24 @@ ssize_t procipc_sem_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyte
// Prepare the header.
ret = sprintf(buffer, "key semid perms nsems uid gid cuid cgid otime ctime\n");
// Iterate through the list.
if (semaphores_list.size > 0) {
listnode_foreach(listnode, &semaphores_list)
{
// Get the entry.
entry = ((struct semid_ds *)listnode->value);
ret += sprintf(
buffer + ret, "%8d %5d %10d %7d %5d %4d %5d %9d %10d %d\n",
abs(entry->sem_perm.key),
entry->semid,
entry->sem_perm.mode,
entry->sem_nsems,
entry->sem_perm.uid,
entry->sem_perm.gid,
entry->sem_perm.cuid,
entry->sem_perm.cgid,
entry->sem_otime,
entry->sem_ctime);
}
// Iterate through the list of semaphore set.
list_for_each_decl(it, &semaphores_list)
{
// Get the current entry.
sem_info = list_entry(it, sem_info_t, list);
// Add the line.
ret += sprintf(
buffer + ret, "%8d %5d %10d %7d %5d %4d %5d %9d %10d %d\n",
abs(sem_info->semid.sem_perm.key),
sem_info->id,
sem_info->semid.sem_perm.mode,
sem_info->semid.sem_nsems,
sem_info->semid.sem_perm.uid,
sem_info->semid.sem_perm.gid,
sem_info->semid.sem_perm.cuid,
sem_info->semid.sem_perm.cgid,
sem_info->semid.sem_otime,
sem_info->semid.sem_ctime);
}
sprintf(buffer + ret, "\n");
+12
View File
@@ -35,6 +35,7 @@
#include "devices/fpu.h"
#include "system/printk.h"
#include "sys/module.h"
#include "sys/sem.h"
#include "drivers/rtc.h"
#include "stdio.h"
#include "assert.h"
@@ -307,6 +308,17 @@ int kmain(boot_info_t *boot_informations)
return 1;
}
print_ok();
//==========================================================================
pr_notice("Initialize IPC/SEM system...\n");
printf("Initialize IPC/SEM system...");
if (sem_init()) {
print_fail();
pr_emerg("Failed to initialize the IPC/SEM system!\n");
return 1;
}
print_ok();
//==========================================================================
pr_notice("Setting up PS/2 driver...\n");
+4 -4
View File
@@ -4,10 +4,10 @@
/// See LICENSE.md for details.
// Setup the logging for this file (do this before any other include).
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[PROC ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "sys/kernel_levels.h" // Include kernel log levels.
#define __DEBUG_HEADER__ "[PROC ]" ///< Change header.
#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG ///< Set log level.
#include "io/debug.h" // Include debugging functions.
#include "process/process.h"
#include "process/scheduler.h"
+5 -2
View File
@@ -64,17 +64,20 @@ int main(int argc, char **argv)
if (!strcmp(argv[3], "-s")) {
struct semid_ds sem;
union semun temp;
int semid;
long ret;
// Prepare the data structure.
temp.buf = &sem;
// Initialize the semid.
semid = atoi(argv[2]);
// Retrive the statistics.
ret = semctl(atoi(argv[2]), 0, IPC_STAT, &temp);
ret = semctl(semid, 0, IPC_STAT, &temp);
// Check if we succeded.
if (!ret) {
//ret = semctl(atoi(argv[2]), 0, GETNSEMS, NULL);
//temp.buf->sems = (struct sem *)malloc(sizeof(struct sem) * ret);
printf("key semid owner perms nsems\n");
printf("%10d %10d %10d %10d %d\n", sem.sem_perm.key, sem.semid, sem.sem_perm.uid, sem.sem_perm.mode, sem.sem_nsems);
printf("%10d %10d %10d %10d %d\n", sem.sem_perm.key, semid, sem.sem_perm.uid, sem.sem_perm.mode, sem.sem_nsems);
return 0;
}
return 1;
+1 -1
View File
@@ -87,8 +87,8 @@ set(TESTS
t_gid.c
# Test semaphores.
t_semget.c
t_sem1.c
t_semflg.c
t_semop.c
# Test scheduling feedback tests.
t_schedfb.c
)
+6 -15
View File
@@ -1,4 +1,8 @@
//test
/// @file t_semflg.c
/// @brief Tests some of the IPC flags.
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include "sys/unistd.h"
#include "sys/errno.h"
#include "sys/sem.h"
@@ -7,20 +11,7 @@
#include "fcntl.h"
#include "stdio.h"
/*
Testing IPC_NOWAIT flag.
*/
void semid_print(struct semid_ds *temp)
{
printf("pid, IPC_KEY, Semid, semop, change: %d, %d, %d, %d, %d\n", temp->sem_perm.uid, temp->sem_perm.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, pid %d, process waiting %d\n", temp->sems[i].sem_val, temp->sems[i].sem_pid, temp->sems[i].sem_zcnt);
}
}
int main()
int main(int argc, char *argv[])
{
struct sembuf op[2];
union semun arg;
+8 -18
View File
@@ -1,4 +1,10 @@
//test
/// @file t_semget.c
/// @brief This program creates a son and then performs a blocking operation on
/// a semaphore. The son sleeps for five seconds and then it wakes up his
/// father and then it deletes the semaphore.
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include "sys/unistd.h"
#include "sys/errno.h"
#include "sys/sem.h"
@@ -7,23 +13,7 @@
#include "fcntl.h"
#include "stdio.h"
/*
Testing Semaphores.
This program creates a son and then performs a blocking operation on a semaphore. The son sleeps for
five seconds and then it wakes up his father and then it deletes the semaphore.
*/
void semid_print(struct semid_ds *temp)
{
printf("pid, IPC_KEY, Semid, semop, change: %d, %d, %d, %d, %d\n", temp->sem_perm.uid, temp->sem_perm.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, pid %d, process waiting %d\n", temp->sems[i].sem_val, temp->sems[i].sem_pid, temp->sems[i].sem_zcnt);
}
}
int main()
int main(int argc, char *argv[])
{
struct sembuf op_child;
struct sembuf op_father[3];
@@ -1,4 +1,8 @@
//test
/// @file t_semop.c
/// @brief Tests semop between processes.
/// @copyright (c) 2014-2023 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include "sys/sem.h"
#include "stdio.h"
#include "sys/ipc.h"
@@ -8,21 +12,7 @@
#include "sys/unistd.h"
#include "fcntl.h"
/*
First test of System V Semaphores.
Correct output should be: Corso di Sistemi Operativi.
*/
void semid_print(struct semid_ds *temp)
{
printf("pid, IPC_KEY, Semid, semop, change: %d, %d, %d, %d, %d\n", temp->sem_perm.uid, temp->sem_perm.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, pid %d, process waiting %d\n", temp->sems[i].sem_val, temp->sems[i].sem_pid, temp->sems[i].sem_zcnt);
}
}
int main()
int main(int argc, char *argv[])
{
struct sembuf sops[6];
sops[0].sem_num = 0;
@@ -52,7 +42,7 @@ int main()
int status;
//create a semaphore set
int semid = semget(IPC_PRIVATE, 4, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
int semid = semget(17, 4, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
//set the values of the semaphores
unsigned short values[] = { 0, 0, 0, 1 };