Skip to content

Commit 4e0b254

Browse files
committed
os/posix: port of the posix implementation to macOS
1 parent 64ad0f5 commit 4e0b254

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1844
-33
lines changed

CMakeLists.txt

+31-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
cmake_minimum_required(VERSION 2.6.4)
22
project(OSAL C)
33

4+
# TODO-MAC:
5+
# This enforces the cwd() to be in the ${CMAKE_BINARY_DIR}. This needed for
6+
# deterministic calculation of full path to MODULE*.dylib libraries when running
7+
# from CLion.
8+
# https://stackoverflow.com/a/38166227/598057
9+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
10+
11+
# TODO/MAC: Quick fix to resolve the error:
12+
# In file included from /sandbox/cFS/osal/src/bsp/pc-linux/ut-src/bsp_ut_voltab.c:21:
13+
#/sandbox/cFS/osal/src/os/inc/osapi.h:89:10: fatal error: 'osconfig.h' file not found
14+
##include "osconfig.h"
15+
# ^~~~~~~~~~~~
16+
include_directories(
17+
src/bsp/pc-linux/config
18+
)
19+
20+
# TODO-MAC: Defining this globally but can be made more focused.
21+
# In file included from /sandbox/cFS/osal/src/os/posix/osloader.c:32:
22+
#/sandbox/cFS/osal/src/os/posix/../portable/os-impl-posix-dl.c:130:30: error: use of undeclared identifier 'RTLD_DEFAULT'
23+
# Function = dlsym((void *)RTLD_DEFAULT, SymbolName);
24+
# ^
25+
# 1 error generated.
26+
add_definitions("-D_DARWIN_C_SOURCE")
27+
428
enable_testing()
529

630
# Generic function for consistent definition of a unit testing target
@@ -16,7 +40,10 @@ function(add_osal_ut_exe TGTNAME)
1640
# It is not an issue for UT builds that use OSAL stubs or no OSAL at all.
1741
set_target_properties(${TGTNAME} PROPERTIES COMPILE_DEFINITIONS "_UNIT_TEST_")
1842
set_target_properties(${TGTNAME} PROPERTIES COMPILE_FLAGS "${UT_C_FLAGS}")
19-
set_target_properties(${TGTNAME} PROPERTIES LINK_FLAGS "${UT_C_FLAGS} -u OS_VolumeTable -u OS_Application_Startup")
43+
44+
# TODO-MAC
45+
# set_target_properties(${TGTNAME} PROPERTIES LINK_FLAGS "${UT_C_FLAGS} -u OS_VolumeTable -u OS_Application_Startup")
46+
2047
target_link_libraries(${TGTNAME} ut_assert osal)
2148
add_test(${TGTNAME} ${TGTNAME})
2249
foreach(TGT ${INSTALL_TARGET_LIST})
@@ -152,8 +179,10 @@ if (OSAL_SELECTED_BSPTYPE)
152179
aux_source_directory(src/bsp/${OSAL_SELECTED_BSPTYPE}/src BSPFILES)
153180
endif (OSAL_SELECTED_BSPTYPE)
154181

182+
# TODO-MAC
183+
add_subdirectory(posix-mac-addons)
155184
add_library(osal STATIC ${OSALFILES} ${BSPFILES})
156-
target_link_libraries(osal ${OSAL_LINK_LIBS})
185+
target_link_libraries(osal ${OSAL_LINK_LIBS} posix-mac-addons)
157186

158187
# Determine if this build is standalone or part of a larger build
159188
# If this is part of a larger build, certain key values will be exported to the parent

Makefile

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
3+
test: test.unit test.integration
4+
5+
test.unit: build.cmake
6+
cd build.commandline.dir && ./osal_core_UT
7+
cd build.commandline.dir && ./osal_file_UT
8+
cd build.commandline.dir && ./osal_filesys_UT
9+
cd build.commandline.dir && ./osal_loader_UT
10+
cd build.commandline.dir && ./osal_timer_UT
11+
cd build.commandline.dir && ./osal_network_UT
12+
13+
test.integration: build.cmake
14+
cd build.commandline.dir && ./bin-sem-flush-test
15+
cd build.commandline.dir && ./bin-sem-test
16+
cd build.commandline.dir && ./bin-sem-timeout-test
17+
cd build.commandline.dir && ./count-sem-test
18+
cd build.commandline.dir && ./file-api-test
19+
cd build.commandline.dir && ./mutex-test
20+
cd build.commandline.dir && ./osal-core-test
21+
cd build.commandline.dir && ./queue-timeout-test
22+
cd build.commandline.dir && ./sem-speed-test
23+
cd build.commandline.dir && ./symbol-api-test
24+
cd build.commandline.dir && ./timer-test
25+
26+
build.cmake:
27+
mkdir -p build.commandline.dir
28+
cd build.commandline.dir && cmake -G Ninja \
29+
-DENABLE_UNIT_TESTS=1 \
30+
-DOSAL_SYSTEM_OSTYPE=posix \
31+
-DOSAL_SYSTEM_BSPTYPE=pc-linux \
32+
..
33+
cd build.commandline.dir && ninja
34+

posix-mac-addons/CMakeLists.txt

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
cmake_minimum_required(VERSION 3.13)
2+
3+
project(POSIX-Mac-Addons C)
4+
5+
set (CMAKE_CXX_STANDARD 11)
6+
7+
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
8+
option(NO_FLAGS "Disable usual compilation flags" OFF)
9+
if(NOT NO_FLAGS)
10+
set(CMAKE_C_FLAGS "-Werror -Wall -Wunused -Wpedantic -fsanitize=address")
11+
set(CMAKE_CXX_FLAGS "-Werror -Wall -Wunused -Wpedantic -fsanitize=address")
12+
set(CMAKE_LINKER_FLAGS_DEBUG "-fsanitize=address")
13+
else()
14+
message("NO_FLAGS is provided: skipping strict compilation flags.")
15+
endif()
16+
endif()
17+
18+
add_subdirectory(src)
19+
20+
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
21+
add_subdirectory(tests)
22+
endif()

posix-mac-addons/src/CMakeLists.txt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
add_subdirectory(mqueue)
2+
add_subdirectory(pthread)
3+
add_subdirectory(semaphore)
4+
add_subdirectory(time)
5+
add_subdirectory(timer)
6+
add_subdirectory(stubs)
7+
8+
add_library(posix-mac-addons INTERFACE)
9+
10+
target_link_libraries(posix-mac-addons
11+
INTERFACE
12+
mqueue
13+
posix-mac-pthread
14+
posix-mac-semaphore
15+
posix-mac-stubs
16+
posix-mac-time
17+
posix-mac-timer
18+
rt
19+
)
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
set(SOURCES
2+
src/mq_close.c
3+
src/mq_getattr.c
4+
src/mq_internal_fs.c
5+
src/mq_notify.c
6+
src/mq_open.c
7+
src/mq_receive.c
8+
src/mq_send.c
9+
src/mq_setattr.c
10+
src/mq_timedreceive.c
11+
src/mq_timedsend.c
12+
src/mq_unlink.c
13+
)
14+
15+
add_library(mqueue ${SOURCES})
16+
target_include_directories(mqueue PUBLIC include include/mqueue)
17+
target_link_libraries(mqueue rt)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <stddef.h>
2+
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
extern const size_t MQ_FS_NAME_MAX;
8+
int mq_get_fs_pathname(const char *const pathname,
9+
char *const out_pathname);
10+
11+
#ifdef __cplusplus
12+
}
13+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include <fcntl.h>
2+
#include <pthread.h>
3+
#include <signal.h>
4+
#include <unistd.h>
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
/// TODO: macOS should have this defined
11+
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
12+
13+
typedef struct mq_info *mqd_t; /* opaque datatype */
14+
15+
struct mq_attr {
16+
long mq_flags; /* message queue flag: O_NONBLOCK */
17+
long mq_maxmsg; /* max number of messages allowed on queue */
18+
long mq_msgsize; /* max size of a message (in bytes) */
19+
long mq_curmsgs; /* number of messages currently on queue */
20+
};
21+
22+
/* one mq_hdr{} per queue, at beginning of mapped file */
23+
struct mq_hdr {
24+
struct mq_attr mqh_attr; /* the queue's attributes */
25+
long mqh_head; /* index of first message */
26+
long mqh_free; /* index of first free message */
27+
long mqh_nwait; /* #threads blocked in mq_receive() */
28+
pid_t mqh_pid; /* nonzero PID if mqh_event set */
29+
struct sigevent mqh_event; /* for mq_notify() */
30+
pthread_mutex_t mqh_lock; /* mutex lock */
31+
pthread_cond_t mqh_wait; /* and condition variable */
32+
};
33+
34+
/* one mymsg_hdr{} at the front of each message in the mapped file */
35+
struct mymsg_hdr {
36+
long msg_next; /* index of next on linked list */
37+
/* msg_next must be first member in struct */
38+
ssize_t msg_len; /* actual length */
39+
unsigned int msg_prio; /* priority */
40+
};
41+
42+
/* one mq_info{} malloc'ed per process per mq_open() */
43+
struct mq_info {
44+
struct mq_hdr *mqi_hdr; /* start of mmap'ed region */
45+
long mqi_magic; /* magic number if open */
46+
int mqi_flags; /* flags for this process */
47+
};
48+
#define MQI_MAGIC 0x98765432
49+
50+
/* size of message in file is rounded up for alignment */
51+
#define MSGSIZE(i) ((((i) + sizeof(long) - 1) / sizeof(long)) * sizeof(long))
52+
53+
int mq_close(mqd_t);
54+
int mq_getattr(mqd_t, struct mq_attr *);
55+
int mq_notify(mqd_t, const struct sigevent *);
56+
mqd_t mq_open(const char *, int, ...);
57+
ssize_t mq_receive(mqd_t, char *, size_t, unsigned int *);
58+
int mq_send(mqd_t, const char *, size_t, unsigned int);
59+
int mq_setattr(mqd_t, const struct mq_attr *, struct mq_attr *);
60+
int mq_unlink(const char *name);
61+
int mq_timedsend(mqd_t mqdes,
62+
const char *msg_ptr,
63+
size_t msg_len,
64+
unsigned msg_prio,
65+
const struct timespec *abs_timeout);
66+
ssize_t mq_timedreceive(mqd_t mqdes,
67+
char *msg_ptr,
68+
size_t msg_len,
69+
unsigned *msg_prio,
70+
const struct timespec *abs_timeout);
71+
72+
#ifdef __cplusplus
73+
}
74+
#endif
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#include "mqueue.h"
2+
3+
#include <errno.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <sys/mman.h>
7+
8+
int mq_close(mqd_t mqd) {
9+
long msgsize, filesize;
10+
struct mq_hdr *mqhdr;
11+
struct mq_attr *attr;
12+
struct mq_info *mqinfo;
13+
14+
mqinfo = mqd;
15+
if (mqinfo->mqi_magic != MQI_MAGIC) {
16+
errno = EBADF;
17+
return (-1);
18+
}
19+
mqhdr = mqinfo->mqi_hdr;
20+
attr = &mqhdr->mqh_attr;
21+
22+
if (mq_notify(mqd, NULL) != 0) /* unregister calling process */
23+
return (-1);
24+
25+
msgsize = MSGSIZE(attr->mq_msgsize);
26+
filesize = sizeof(struct mq_hdr) +
27+
(attr->mq_maxmsg * (sizeof(struct mymsg_hdr) + msgsize));
28+
if (munmap(mqinfo->mqi_hdr, filesize) == -1)
29+
return (-1);
30+
31+
mqinfo->mqi_magic = 0; /* just in case */
32+
free(mqinfo);
33+
return (0);
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "mqueue.h"
2+
3+
#include <errno.h>
4+
#include <stdio.h>
5+
6+
int
7+
mq_getattr(mqd_t mqd, struct mq_attr *mqstat)
8+
{
9+
int n;
10+
struct mq_hdr *mqhdr;
11+
struct mq_attr *attr;
12+
struct mq_info *mqinfo;
13+
14+
mqinfo = mqd;
15+
if (mqinfo->mqi_magic != MQI_MAGIC) {
16+
errno = EBADF;
17+
return(-1);
18+
}
19+
mqhdr = mqinfo->mqi_hdr;
20+
attr = &mqhdr->mqh_attr;
21+
if ( (n = pthread_mutex_lock(&mqhdr->mqh_lock)) != 0) {
22+
errno = n;
23+
return(-1);
24+
}
25+
26+
mqstat->mq_flags = mqinfo->mqi_flags; /* per-open */
27+
mqstat->mq_maxmsg = attr->mq_maxmsg; /* remaining three per-queue */
28+
mqstat->mq_msgsize = attr->mq_msgsize;
29+
mqstat->mq_curmsgs = attr->mq_curmsgs;
30+
31+
pthread_mutex_unlock(&mqhdr->mqh_lock);
32+
return(0);
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "mqueue-internal.h"
2+
3+
#include <assert.h>
4+
#include <errno.h>
5+
#include <stdio.h>
6+
#include <string.h>
7+
8+
const size_t MQ_FS_NAME_MAX = 64;
9+
10+
static const char prefix[] = "/tmp";
11+
12+
static const size_t MQ_NAME_MAX = 32;
13+
14+
static size_t safe_strlen(const char *str, size_t max_len) {
15+
const char *end = (const char *)memchr(str, '\0', max_len);
16+
if (end == NULL) {
17+
return max_len;
18+
} else {
19+
return end - str;
20+
}
21+
}
22+
23+
int mq_get_fs_pathname(const char *const pathname, char *const out_pathname) {
24+
if (pathname[0] != '/') {
25+
return EINVAL;
26+
}
27+
28+
size_t pathname_len = safe_strlen(pathname, MQ_NAME_MAX);
29+
assert(pathname_len < MQ_NAME_MAX);
30+
31+
size_t internal_len = strlen(prefix) + pathname_len + 1; // +1 for ending '\0'
32+
assert(internal_len < MQ_FS_NAME_MAX);
33+
34+
snprintf(out_pathname, internal_len, "%s%s", prefix, pathname);
35+
return 0;
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include "mqueue.h"
2+
3+
#include <errno.h>
4+
#include <stdio.h>
5+
6+
int mq_notify(mqd_t mqd, const struct sigevent *notification) {
7+
int n;
8+
pid_t pid;
9+
struct mq_hdr *mqhdr;
10+
struct mq_info *mqinfo;
11+
12+
mqinfo = mqd;
13+
if (mqinfo->mqi_magic != MQI_MAGIC) {
14+
errno = EBADF;
15+
return (-1);
16+
}
17+
mqhdr = mqinfo->mqi_hdr;
18+
if ((n = pthread_mutex_lock(&mqhdr->mqh_lock)) != 0) {
19+
errno = n;
20+
return (-1);
21+
}
22+
23+
pid = getpid();
24+
if (notification == NULL) {
25+
if (mqhdr->mqh_pid == pid) {
26+
mqhdr->mqh_pid = 0; /* unregister calling process */
27+
} /* no error if caller not registered */
28+
} else {
29+
if (mqhdr->mqh_pid != 0) {
30+
if (kill(mqhdr->mqh_pid, 0) != -1 || errno != ESRCH) {
31+
errno = EBUSY;
32+
goto err;
33+
}
34+
}
35+
mqhdr->mqh_pid = pid;
36+
mqhdr->mqh_event = *notification;
37+
}
38+
pthread_mutex_unlock(&mqhdr->mqh_lock);
39+
return (0);
40+
41+
err:
42+
pthread_mutex_unlock(&mqhdr->mqh_lock);
43+
return (-1);
44+
}

0 commit comments

Comments
 (0)