Skip to content

Commit

Permalink
os/posix: port of the posix implementation to macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
stanislaw committed Apr 21, 2020
1 parent a66eb2d commit 6011517
Show file tree
Hide file tree
Showing 49 changed files with 1,822 additions and 29 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ target_include_directories(osal_${OSAL_SYSTEM_OSTYPE}_impl PRIVATE
# Define the external "osal" static library target
# This is a combination of the generic parts with the low level
# system-specific parts
add_subdirectory(posix-mac-addons)

add_library(osal STATIC
src/os/shared/osapi-binsem.c
src/os/shared/osapi-clock.c
Expand Down Expand Up @@ -190,6 +192,8 @@ target_include_directories(osal INTERFACE
${OSAL_API_INCLUDE_DIRECTORIES}
)

target_link_libraries(osal posix-mac-addons)

# Link the OSAL with the BSP
target_link_libraries(osal osal_bsp)

Expand Down
34 changes: 34 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@


test: test.unit test.integration

test.unit: build.cmake
cd build.commandline.dir && ./osal_core_UT
cd build.commandline.dir && ./osal_file_UT
cd build.commandline.dir && ./osal_filesys_UT
cd build.commandline.dir && ./osal_loader_UT
cd build.commandline.dir && ./osal_timer_UT
cd build.commandline.dir && ./osal_network_UT

test.integration: build.cmake
cd build.commandline.dir && ./bin-sem-flush-test
cd build.commandline.dir && ./bin-sem-test
cd build.commandline.dir && ./bin-sem-timeout-test
cd build.commandline.dir && ./count-sem-test
cd build.commandline.dir && ./file-api-test
cd build.commandline.dir && ./mutex-test
cd build.commandline.dir && ./osal-core-test
cd build.commandline.dir && ./queue-timeout-test
cd build.commandline.dir && ./sem-speed-test
cd build.commandline.dir && ./symbol-api-test
cd build.commandline.dir && ./timer-test

build.cmake:
mkdir -p build.commandline.dir
cd build.commandline.dir && cmake -G Ninja \
-DENABLE_UNIT_TESTS=1 \
-DOSAL_SYSTEM_OSTYPE=posix \
-DOSAL_SYSTEM_BSPTYPE=pc-linux \
-DOSAL_INCLUDEDIR=src/bsp/pc-linux/config \
..
cd build.commandline.dir && ninja
22 changes: 22 additions & 0 deletions posix-mac-addons/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.13)

project(POSIX-Mac-Addons C)

set (CMAKE_CXX_STANDARD 11)

if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
option(NO_FLAGS "Disable usual compilation flags" OFF)
if(NOT NO_FLAGS)
set(CMAKE_C_FLAGS "-Werror -Wall -Wunused -Wpedantic -fsanitize=address")
set(CMAKE_CXX_FLAGS "-Werror -Wall -Wunused -Wpedantic -fsanitize=address")
set(CMAKE_LINKER_FLAGS_DEBUG "-fsanitize=address")
else()
message("NO_FLAGS is provided: skipping strict compilation flags.")
endif()
endif()

add_subdirectory(src)

if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
add_subdirectory(tests)
endif()
19 changes: 19 additions & 0 deletions posix-mac-addons/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
add_subdirectory(mqueue)
add_subdirectory(pthread)
add_subdirectory(semaphore)
add_subdirectory(time)
add_subdirectory(timer)
add_subdirectory(stubs)

add_library(posix-mac-addons INTERFACE)

target_link_libraries(posix-mac-addons
INTERFACE
mqueue
posix-mac-pthread
posix-mac-semaphore
posix-mac-stubs
posix-mac-time
posix-mac-timer
rt
)
17 changes: 17 additions & 0 deletions posix-mac-addons/src/mqueue/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
set(SOURCES
src/mq_close.c
src/mq_getattr.c
src/mq_internal_fs.c
src/mq_notify.c
src/mq_open.c
src/mq_receive.c
src/mq_send.c
src/mq_setattr.c
src/mq_timedreceive.c
src/mq_timedsend.c
src/mq_unlink.c
)

add_library(mqueue ${SOURCES})
target_include_directories(mqueue PUBLIC include include/mqueue)
target_link_libraries(mqueue rt)
13 changes: 13 additions & 0 deletions posix-mac-addons/src/mqueue/include/mqueue/mqueue-internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

extern const size_t MQ_FS_NAME_MAX;
int mq_get_fs_pathname(const char *const pathname,
char *const out_pathname);

#ifdef __cplusplus
}
#endif
74 changes: 74 additions & 0 deletions posix-mac-addons/src/mqueue/include/mqueue/mqueue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>

#ifdef __cplusplus
extern "C" {
#endif

/// TODO: macOS should have this defined
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

typedef struct mq_info *mqd_t; /* opaque datatype */

struct mq_attr {
long mq_flags; /* message queue flag: O_NONBLOCK */
long mq_maxmsg; /* max number of messages allowed on queue */
long mq_msgsize; /* max size of a message (in bytes) */
long mq_curmsgs; /* number of messages currently on queue */
};

/* one mq_hdr{} per queue, at beginning of mapped file */
struct mq_hdr {
struct mq_attr mqh_attr; /* the queue's attributes */
long mqh_head; /* index of first message */
long mqh_free; /* index of first free message */
long mqh_nwait; /* #threads blocked in mq_receive() */
pid_t mqh_pid; /* nonzero PID if mqh_event set */
struct sigevent mqh_event; /* for mq_notify() */
pthread_mutex_t mqh_lock; /* mutex lock */
pthread_cond_t mqh_wait; /* and condition variable */
};

/* one mymsg_hdr{} at the front of each message in the mapped file */
struct mymsg_hdr {
long msg_next; /* index of next on linked list */
/* msg_next must be first member in struct */
ssize_t msg_len; /* actual length */
unsigned int msg_prio; /* priority */
};

/* one mq_info{} malloc'ed per process per mq_open() */
struct mq_info {
struct mq_hdr *mqi_hdr; /* start of mmap'ed region */
long mqi_magic; /* magic number if open */
int mqi_flags; /* flags for this process */
};
#define MQI_MAGIC 0x98765432

/* size of message in file is rounded up for alignment */
#define MSGSIZE(i) ((((i) + sizeof(long) - 1) / sizeof(long)) * sizeof(long))

int mq_close(mqd_t);
int mq_getattr(mqd_t, struct mq_attr *);
int mq_notify(mqd_t, const struct sigevent *);
mqd_t mq_open(const char *, int, ...);
ssize_t mq_receive(mqd_t, char *, size_t, unsigned int *);
int mq_send(mqd_t, const char *, size_t, unsigned int);
int mq_setattr(mqd_t, const struct mq_attr *, struct mq_attr *);
int mq_unlink(const char *name);
int mq_timedsend(mqd_t mqdes,
const char *msg_ptr,
size_t msg_len,
unsigned msg_prio,
const struct timespec *abs_timeout);
ssize_t mq_timedreceive(mqd_t mqdes,
char *msg_ptr,
size_t msg_len,
unsigned *msg_prio,
const struct timespec *abs_timeout);

#ifdef __cplusplus
}
#endif
34 changes: 34 additions & 0 deletions posix-mac-addons/src/mqueue/src/mq_close.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "mqueue.h"

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>

int mq_close(mqd_t mqd) {
long msgsize, filesize;
struct mq_hdr *mqhdr;
struct mq_attr *attr;
struct mq_info *mqinfo;

mqinfo = mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) {
errno = EBADF;
return (-1);
}
mqhdr = mqinfo->mqi_hdr;
attr = &mqhdr->mqh_attr;

if (mq_notify(mqd, NULL) != 0) /* unregister calling process */
return (-1);

msgsize = MSGSIZE(attr->mq_msgsize);
filesize = sizeof(struct mq_hdr) +
(attr->mq_maxmsg * (sizeof(struct mymsg_hdr) + msgsize));
if (munmap(mqinfo->mqi_hdr, filesize) == -1)
return (-1);

mqinfo->mqi_magic = 0; /* just in case */
free(mqinfo);
return (0);
}
33 changes: 33 additions & 0 deletions posix-mac-addons/src/mqueue/src/mq_getattr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "mqueue.h"

#include <errno.h>
#include <stdio.h>

int
mq_getattr(mqd_t mqd, struct mq_attr *mqstat)
{
int n;
struct mq_hdr *mqhdr;
struct mq_attr *attr;
struct mq_info *mqinfo;

mqinfo = mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) {
errno = EBADF;
return(-1);
}
mqhdr = mqinfo->mqi_hdr;
attr = &mqhdr->mqh_attr;
if ( (n = pthread_mutex_lock(&mqhdr->mqh_lock)) != 0) {
errno = n;
return(-1);
}

mqstat->mq_flags = mqinfo->mqi_flags; /* per-open */
mqstat->mq_maxmsg = attr->mq_maxmsg; /* remaining three per-queue */
mqstat->mq_msgsize = attr->mq_msgsize;
mqstat->mq_curmsgs = attr->mq_curmsgs;

pthread_mutex_unlock(&mqhdr->mqh_lock);
return(0);
}
36 changes: 36 additions & 0 deletions posix-mac-addons/src/mqueue/src/mq_internal_fs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "mqueue-internal.h"

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

const size_t MQ_FS_NAME_MAX = 64;

static const char prefix[] = "/tmp";

static const size_t MQ_NAME_MAX = 32;

static size_t safe_strlen(const char *str, size_t max_len) {
const char *end = (const char *)memchr(str, '\0', max_len);
if (end == NULL) {
return max_len;
} else {
return end - str;
}
}

int mq_get_fs_pathname(const char *const pathname, char *const out_pathname) {
if (pathname[0] != '/') {
return EINVAL;
}

size_t pathname_len = safe_strlen(pathname, MQ_NAME_MAX);
assert(pathname_len < MQ_NAME_MAX);

size_t internal_len = strlen(prefix) + pathname_len + 1; // +1 for ending '\0'
assert(internal_len < MQ_FS_NAME_MAX);

snprintf(out_pathname, internal_len, "%s%s", prefix, pathname);
return 0;
}
44 changes: 44 additions & 0 deletions posix-mac-addons/src/mqueue/src/mq_notify.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "mqueue.h"

#include <errno.h>
#include <stdio.h>

int mq_notify(mqd_t mqd, const struct sigevent *notification) {
int n;
pid_t pid;
struct mq_hdr *mqhdr;
struct mq_info *mqinfo;

mqinfo = mqd;
if (mqinfo->mqi_magic != MQI_MAGIC) {
errno = EBADF;
return (-1);
}
mqhdr = mqinfo->mqi_hdr;
if ((n = pthread_mutex_lock(&mqhdr->mqh_lock)) != 0) {
errno = n;
return (-1);
}

pid = getpid();
if (notification == NULL) {
if (mqhdr->mqh_pid == pid) {
mqhdr->mqh_pid = 0; /* unregister calling process */
} /* no error if caller not registered */
} else {
if (mqhdr->mqh_pid != 0) {
if (kill(mqhdr->mqh_pid, 0) != -1 || errno != ESRCH) {
errno = EBUSY;
goto err;
}
}
mqhdr->mqh_pid = pid;
mqhdr->mqh_event = *notification;
}
pthread_mutex_unlock(&mqhdr->mqh_lock);
return (0);

err:
pthread_mutex_unlock(&mqhdr->mqh_lock);
return (-1);
}
Loading

0 comments on commit 6011517

Please sign in to comment.