diff --git a/.github/workflows/github_ci.yml b/.github/workflows/github_ci.yml deleted file mode 100644 index bf84d636..00000000 --- a/.github/workflows/github_ci.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: GitHub CI - -on: - push: - branches: - - stable - - development - pull_request: - branches: - - stable - - development - -jobs: - build: - - runs-on: ubuntu-latest - env: - SONAR_SCANNER_VERSION: 4.4.0.2170 - SONAR_SERVER_URL: "https://sonarcloud.io" - BUILD_WRAPPER_OUT_DIR: bw-output # Directory where build-wrapper output will be placed - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - - name: Install Dependencies - run: sudo apt install cppcheck -y - - - name: Configure Git - env: - TOKEN: ${{ secrets.CI_PAT }} - run: git config --global url."https://${TOKEN}:x-oauth-basic@github.com/".insteadOf "https://github.com/" - - - name: Get Toolchains - run: | - make get_avr_tc AVR_TC_REPO=https://github.com/VisorFolks/avr-toolchain.git - make get_riscv_tc RISC_V_TC_REPO=https://github.com/VisorFolks/risc-v-toolchain.git - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - - name: Download and set up sonar-scanner - env: - SONAR_SCANNER_DOWNLOAD_URL: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip - run: | - mkdir -p $HOME/.sonar - curl -sSLo $HOME/.sonar/sonar-scanner.zip ${{ env.SONAR_SCANNER_DOWNLOAD_URL }} - unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/ - echo "$HOME/.sonar/sonar-scanner-${{ env.SONAR_SCANNER_VERSION }}-linux/bin" >> $GITHUB_PATH - - - name: Download and set up build-wrapper - env: - BUILD_WRAPPER_DOWNLOAD_URL: ${{ env.SONAR_SERVER_URL }}/static/cpp/build-wrapper-linux-x86.zip - run: | - curl -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip ${{ env.BUILD_WRAPPER_DOWNLOAD_URL }} - unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/ - echo "$HOME/.sonar/build-wrapper-linux-x86" >> $GITHUB_PATH - - - name: Run build-wrapper - run: | - build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all_projects - - - name: Run sonar-scanner - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: | - sonar-scanner \ - --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" \ - --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" \ - --define sonar.organization=cyancore \ - --define sonar.projectKey=VisorFolks_cyancore \ - --define sonar.sources=src \ - --define sonar.verbose=true diff --git a/README.md b/README.md index eb507e72..df72933a 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ For details about the framework, follow the README.md in each folder. Host system requirements: * Linux Machine (WSL/Dedicated machine) -* make utility and cppcheck installed; run +* make utility and cppcheck installed; run ```sh $ sudo apt install build-essential cppcheck -y ``` diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 00000000..e127fc2b --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,10 @@ +sonar.organization=cyancore +sonar.projectKey=VisorFolks_cyancore +sonar.sources=src +sonar.cfamily.build-wrapper-output=toolchain/bw-output +sonar.verbose=false +sonar.host.url=https://sonarcloud.io +sonar.verbose=true +sonar.cfamily.threads=8 +sonar.cfamily.cache.enabled=true +sonar.cfamily.cache.path=toolchain/bw-output/cfamily_cache diff --git a/src/include/status.h b/src/include/status.h index e84e2f4c..856a190e 100644 --- a/src/include/status.h +++ b/src/include/status.h @@ -15,34 +15,65 @@ typedef enum status { - success = 0x0000, + success = 0x0000, +/* Generic error */ error_generic = -0x0001, error_func_inval = -0x0002, error_func_inval_arg = -0x0003, + error_overflow = -0x0004, +/* Driver related error */ error_driver = -0x0100, error_driver_init_done = -0x0101, error_driver_init_failed = -0x0102, error_driver_busy = -0x0103, error_driver_data = -0x0104, +/* Device related error */ error_device = -0x0200, error_device_id_inval = -0x0201, error_device_inval = -0x0202, + error_device_busy = -0x0203, +/* Machine Call related error */ error_mcall = -0x0300, error_mcall_code_inval = -0x0301, +/* hcall related error */ error_hcall = -0x0400, +/* Syscall related error */ error_scall = -0x0500, + error_scall_code_inval = -0x0501, +/* Memory related error */ error_memory = -0x0600, + error_memory_low = -0x0601, +/* File related error */ error_file = -0x0700, + error_file_desc = -0x0701, + error_file_exist = -0x0702, + error_file_not_found = -0x0703, + error_file_no_space = -0x0704, + error_file_long_name = -0x0705, +/* String related error */ error_string = -0x0800, +/* Math related error */ error_math = -0x0900, error_math_inval_arg = -0x0901, + error_math_large_val = -0x0902, +/* Access related error */ error_access = -0x0a00, +/* System related error */ error_system = -0x0b00, error_system_irq_link_fail = -0x0b01, error_system_irq_unlink_fail = -0x0b02, - error_network = -0x0c00, +/* Network related error */ + error_net = -0x0c00, + error_net_con_timeout = -0x0c001, +/* User space related error */ error_user = -0x0d00, +/* IO related error */ error_io = -0x0e00, +/* OS related error */ error_os = -0x0f00, error_os_task_overfow = -0x0f01, + error_os_deadlock = -0x0f02, +/* Mesg related error */ + error_mesg = -0x1000, + error_mesg_long = -0x1001, } status_t; diff --git a/src/include/supervisor_call.h b/src/include/supervisor_call.h new file mode 100644 index 00000000..7bbb54b1 --- /dev/null +++ b/src/include/supervisor_call.h @@ -0,0 +1,95 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : supervisor_call.h + * Description : This file consists of supervisor call IDs and prototypes + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once +#define _SUPER_CALL_H_ + +#include +#include + +// Supervisor call IDs +typedef enum scall_id +{ + scall_id_generic = 0x0000, + scall_id_is_irq, +/* pthread related */ + scall_id_pthread_attr_destroy = 0x1000, + scall_id_pthread_attr_getdetachstate, + scall_id_pthread_attr_getschedparam, + scall_id_pthread_attr_getstacksize, + scall_id_pthread_attr_init, + scall_id_pthread_attr_setdetachstate, + scall_id_pthread_attr_setschedparam, + scall_id_pthread_attr_setschedpolicy, + scall_id_pthread_attr_setstacksize, + scall_id_pthread_barrier_destroy, + scall_id_pthread_barrier_init, + scall_id_pthread_barrier_wait, + scall_id_pthread_create, + scall_id_pthread_cond_broadcast, + scall_id_pthread_cond_destroy, + scall_id_pthread_cond_init, + scall_id_pthread_cond_signal, + scall_id_pthread_cond_timedwait, + scall_id_pthread_equal, + scall_id_pthread_exit, + scall_id_pthread_getschedparam, + scall_id_pthread_join, + scall_id_pthread_mutex_destroy, + scall_id_pthread_mutex_init, + scall_id_pthread_mutex_timedlock, + scall_id_pthread_mutex_unlock, + scall_id_pthread_mutexattr_destroy, + scall_id_pthread_mutexattr_gettype, + scall_id_pthread_mutexattr_init, + scall_id_pthread_mutexattr_settype, + scall_id_pthread_self, + scall_id_pthread_setschedparam, + scall_id_pthread_delay_ticks, +/* mqueue related */ + scall_id_mq_close, + scall_id_mq_setattr, + scall_id_mq_getattr, + scall_id_mq_open, + scall_id_mq_receive, + scall_id_mq_send, + scall_id_mq_unlink, +/* semaphore related */ + scall_id_sem_init, + scall_id_sem_destroy, + scall_id_sem_getvalue, + scall_id_sem_post, + scall_id_sem_wait, +/* scheduler related */ + scall_id_sched_get_max_priority, + scall_id_sched_get_min_priority, + scall_id_sched_yield, + +} scall_id_t; + +typedef struct sret +{ + uintptr_t p; + size_t size; + status_t status; +} sret_t; + +typedef struct scall +{ + scall_id_t id; + sret_t (*callback)(unsigned int a0, unsigned int a1, unsigned int a2); +} scall_t; + +#define INCLUDE_SCALL(_name, _id , _callback) \ + const scall_t _name _SECTION(".scall") = \ + { \ + .id = _id, \ + .callback = _callback \ + } diff --git a/src/include/visor/supervisor/workers.h b/src/include/visor/supervisor/workers.h new file mode 100644 index 00000000..e966d14d --- /dev/null +++ b/src/include/visor/supervisor/workers.h @@ -0,0 +1,16 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : worker.h + * Description : This file consists of supervisor-workers + * and related prototypes + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#include + +void super_call(scall_id_t id, unsigned int a0, unsigned int a1, unsigned int a2, sret_t *ret); diff --git a/src/lib/build.mk b/src/lib/build.mk index 131b6846..1ab699cc 100644 --- a/src/lib/build.mk +++ b/src/lib/build.mk @@ -14,6 +14,7 @@ LIB_DIR := $(GET_PATH) # Mandatory libraries include $(LIB_DIR)/libresource/build.mk include $(LIB_DIR)/libc/build.mk +include $(LIB_DIR)/libposix/build.mk #================================================== include $(LIB_DIR)/libnmath/build.mk diff --git a/src/lib/libc/printf.c b/src/lib/libc/printf.c index 570f72b7..efb48528 100644 --- a/src/lib/libc/printf.c +++ b/src/lib/libc/printf.c @@ -107,7 +107,7 @@ int vprintf(const char *fmt, va_list args) break; case 'c': str = va_arg(args, char *); - ret += console_putc((int)str); + ret += console_putc((int)str[0]); break; case 's': str = va_arg(args, char *); diff --git a/src/lib/libposix/build.mk b/src/lib/libposix/build.mk new file mode 100644 index 00000000..a77936fd --- /dev/null +++ b/src/lib/libposix/build.mk @@ -0,0 +1,22 @@ +# +# CYANCORE LICENSE +# Copyrights (C) 2019, Cyancore Team +# +# File Name : build.mk +# Descrption : This script accumulates sources and builds +# library +# Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] +# Organisation : Cyancore Core-Team +# + +POSIX_PATH := $(GET_PATH) +LIB_OBJS := + +LIB := libposix.a +LIB_INCLUDE += $(POSIX_PATH)/include/ +DEP_LIBS_ARG += -lposix + +include $(POSIX_PATH)/src/build.mk + +DIR := $(POSIX_PATH) +include mk/lib.mk diff --git a/src/lib/libposix/include/cc_posix_config.h b/src/lib/libposix/include/cc_posix_config.h new file mode 100644 index 00000000..c5d721d2 --- /dev/null +++ b/src/lib/libposix/include/cc_posix_config.h @@ -0,0 +1,47 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : cc_posix_config.h + * Description : POSIX user config + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#ifndef posixconfigTICK_RATE_HZ +#define posixconfigTICK_RATE_HZ (1000) +#endif + +/******************* + * MQUEUE configs + *******************/ + +/** + * @brief MQUEUE max name length in bytes + */ +#ifndef posixconfigMQ_NAME_LEN_MAX +#define posixconfigMQ_NAME_LEN_MAX (16) +#endif + +/** + * @brief MQUEUE max munber of queues allowed + */ +#ifndef posixconfigMQ_MAX_QUEUE +#define posixconfigMQ_MAX_QUEUE (5) +#endif + +/** + * @brief MQUEUE Maximum number of messages in an mq at one time + */ +#ifndef posixconfigMQ_MAX_MESSAGES +#define posixconfigMQ_MAX_MESSAGES (10) +#endif + +/** + * @brief MQUEUE Maximum size (in bytes) of each message + */ +#ifndef posixconfigMQ_MAX_SIZE +#define posixconfigMQ_MAX_SIZE (128) +#endif diff --git a/src/lib/libposix/include/cc_posix_internal.h b/src/lib/libposix/include/cc_posix_internal.h new file mode 100644 index 00000000..6e291224 --- /dev/null +++ b/src/lib/libposix/include/cc_posix_internal.h @@ -0,0 +1,111 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : cc_posix_internal.h + * Description : Internal typedefs + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#include +#include + +/** + * @file cc_posix_internal.h + * @brief Internal structs and initializers for CC+POSIX. + */ + +/** + * @brief Mutex attribute object. + */ +#if posixconfigENABLE_PTHREAD_MUTEXATTR_T == 1 + typedef struct pthread_mutexattr_internal + { + int iType; /**< Mutex type. */ + } pthread_mutexattr_internal_t; +#endif + +#if posixconfigENABLE_PTHREAD_MUTEX_T == 1 + +/** + * @brief Mutex. + */ + typedef struct pthread_mutex_internal + { + BaseType_t xIsInitialized; /**< Set to pdTRUE if this mutex is initialized, pdFALSE otherwise. */ + StaticSemaphore_t xMutex; /**< Kernel mutex. */ + TaskHandle_t xTaskOwner; /**< Owner; used for deadlock detection and permission checks. */ + pthread_mutexattr_internal_t xAttr; /**< Mutex attributes. */ + } pthread_mutex_internal_t; + +/** + * @brief Compile-time initializer of pthread_mutex_internal_t. + */ + #define FREERTOS_POSIX_MUTEX_INITIALIZER \ + ( ( ( pthread_mutex_internal_t ) \ + { \ + .xIsInitialized = pdFALSE, \ + .xMutex = { { 0 } }, \ + .xTaskOwner = NULL, \ + .xAttr = { .iType = 0 } \ + } \ + ) \ + ) +#endif /* if posixconfigENABLE_PTHREAD_MUTEX_T == 1 */ + +#if posixconfigENABLE_PTHREAD_COND_T == 1 + +/** + * @brief Condition variable. + */ + typedef struct pthread_cond_internal + { + BaseType_t xIsInitialized; /**< Set to pdTRUE if this condition variable is initialized, pdFALSE otherwise. */ + StaticSemaphore_t xCondWaitSemaphore; /**< Threads block on this semaphore in pthread_cond_wait. */ + unsigned iWaitingThreads; /**< The number of threads currently waiting on this condition variable. */ + } pthread_cond_internal_t; + +/** + * @brief Compile-time initializer of pthread_cond_internal_t. + */ + + #define FREERTOS_POSIX_COND_INITIALIZER \ + ( ( ( pthread_cond_internal_t ) \ + { \ + .xIsInitialized = pdFALSE, \ + .xCondWaitSemaphore = { { 0 } }, \ + .iWaitingThreads = 0 \ + } \ + ) \ + ) + +#endif /* if posixconfigENABLE_PTHREAD_COND_T == 1 */ + +#if posixconfigENABLE_SEM_T == 1 + +/** + * @brief Semaphore type. + */ + typedef struct + { + StaticSemaphore_t xSemaphore; /**< Kernel semaphore. */ + int value; /**< POSIX semaphore count. */ + } sem_internal_t; +#endif /* if posixconfigENABLE_SEM_T == 1 */ + +#if posixconfigENABLE_PTHREAD_BARRIER_T == 1 + +/** + * @brief Barrier object. + */ + typedef struct pthread_barrier_internal + { + unsigned uThreadCount; /**< Current number of threads that have entered barrier. */ + unsigned uThreshold; /**< The count argument of pthread_barrier_init. */ + StaticSemaphore_t xThreadCountSemaphore; /**< Prevents more than uThreshold threads from exiting pthread_barrier_wait at once. */ + StaticEventGroup_t xBarrierEventGroup; /**< Kernel event group that blocks to wait on threads entering barrier. */ + } pthread_barrier_internal_t; +#endif /* if posixconfigENABLE_PTHREAD_BARRIER_T == 1 */ diff --git a/src/lib/libposix/include/cc_posix_types.h b/src/lib/libposix/include/cc_posix_types.h new file mode 100644 index 00000000..501273b5 --- /dev/null +++ b/src/lib/libposix/include/cc_posix_types.h @@ -0,0 +1,70 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : cc_posix_types.h + * Description : POSIX typedefs + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#include + +/* + * sys/types.h defines a POSIX type when posixconfigENABLE_PTHREAD__T + * is not defined AND when posixconfigENABLE_PTHREAD__T is set to 1. + * cc_posix_internal.h defines internal type ONLY when + * posixconfigENABLE_PTHREAD__T is set to 1. + * #else part below is to have a type defined, so the code compiles, when + * posixconfigENABLE_PTHREAD__T is not defined. + */ +#if posixconfigENABLE_PTHREAD_MUTEX_T == 1 + typedef pthread_mutex_internal_t PthreadMutexType_t; +#else + typedef void * PthreadMutexType_t; +#endif + +#if posixconfigENABLE_PTHREAD_COND_T == 1 + typedef pthread_cond_internal_t PthreadCondType_t; +#else + typedef void * PthreadCondType_t; +#endif + +#if posixconfigENABLE_SEM_T == 1 + typedef sem_internal_t PosixSemType_t; +#else + typedef void * PosixSemType_t; +#endif + +#if posixconfigENABLE_PTHREAD_MUTEXATTR_T == 1 + typedef struct pthread_mutexattr + { + uint32_t ulpthreadMutexAttrStorage; + } PthreadMutexAttrType_t; +#else + typedef void * PthreadMutexAttrType_t; +#endif + +#if posixconfigENABLE_PTHREAD_ATTR_T == 1 + typedef struct pthread_attr + { + uint32_t ulpthreadAttrStorage; + } PthreadAttrType_t; +#else + typedef void * PthreadAttrType_t; +#endif + +#if posixconfigENABLE_PTHREAD_BARRIER_T == 1 + typedef pthread_barrier_internal_t PthreadBarrierType_t; +#else + typedef void * PthreadBarrierType_t; +#endif + +#if( posixconfigUSE_16_BIT_TICKS == 1 ) + typedef uint16_t TickType_t; +#else + typedef size_t TickType_t; +#endif +#define posixconfigMAX_DELAY (TickType_t)(~0) diff --git a/src/lib/libposix/include/posix/errno.h b/src/lib/libposix/include/posix/errno.h new file mode 100644 index 00000000..01501b40 --- /dev/null +++ b/src/lib/libposix/include/posix/errno.h @@ -0,0 +1,51 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : errno.h + * Description : System error numbers. + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_ERRNO_H_ + +#include + +/** + * @name Definition of POSIX errnos. + */ +/**@{ */ +#define SUCCESS success /**< Operation success*/ +#define EPERM (-error_access) /**< Operation not permitted. */ +#define ENOENT (-error_file_not_found) /**< No such file or directory. */ +#define EBADF (-error_file_desc) /**< Bad file descriptor. */ +#define EAGAIN (-error_device_inval) /**< Resource unavailable, try again. */ +#define ENOMEM (-error_memory_low) /**< Not enough space. */ +#define EEXIST (-error_file_exist) /**< File exists. */ +#define EBUSY (-error_device_busy) /**< Device or resource busy. */ +#define EINVAL (-error_func_inval_arg) /**< Invalid argument. */ +#define ENOSPC (-error_file_no_space) /**< No space left on device. */ +#define ERANGE (-error_math_large_val) /**< Result too large. */ +#define ENAMETOOLONG (-error_file_long_name) /**< File name too long. */ +#define EDEADLK (-error_os_deadlock) /**< Resource deadlock would occur. */ +#define EOVERFLOW (-error_overflow) /**< Value too large to be stored in data type. */ +#define ENOSYS (-error_func_inval) /**< Function not supported. */ +#define EMSGSIZE (-error_mesg_long) /**< Message too long. */ +#define ENOTSUP (-error_func_inval) /**< Operation not supported. */ +#define ETIMEDOUT (-error_net_con_timeout)/**< Connection timed out. */ +/**@} */ + +/** + * @name System Variable + * + * @brief Define CC+POSIX errno, if enabled. + * Set configUSE_POSIX_ERRNO to enable, and clear to disable. + * + * @{ + */ +#if ( configUSE_POSIX_ERRNO == 1 ) +#endif +/**@} */ diff --git a/src/lib/libposix/include/posix/fcntl.h b/src/lib/libposix/include/posix/fcntl.h new file mode 100644 index 00000000..ceae4781 --- /dev/null +++ b/src/lib/libposix/include/posix/fcntl.h @@ -0,0 +1,58 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : fcntl.h + * Description : File control options. + * : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_FCNTL_H_ + +/** + * @name File creation flags for use in the oflag value to open() and openat(). + */ +/**@{ */ +#define O_CLOEXEC 0x0001 /**< Close the file descriptor upon exec(). */ +#define O_CREAT 0x0002 /**< Create file if it does not exist. */ +#define O_DIRECTORY 0x0004 /**< Fail if file is a non-directory file. */ +#define O_EXCL 0x0008 /**< Exclusive use flag. */ +#define O_NOCTTY 0x0010 /**< Do not assign controlling terminal. */ +#define O_NOFOLLOW 0x0020 /**< Do not follow symbolic links. */ +#define O_TRUNC 0x0040 /**< Truncate flag. */ +#define O_TTY_INIT 0x0080 /**< termios structure provides conforming behavior. */ +/**@} */ + +/** + * @name File status flags for open(), openat(), and fcntl(). + */ +/**@{ */ +#define O_APPEND 0x0100 /**< Set append mode. */ +#define O_DSYNC 0x0200 /**< Write according to synchronized I/O data integrity completion. */ +#define O_NONBLOCK 0x0400 /**< Non-blocking mode. */ +#define O_RSYNC 0x0800 /**< Synchronized read I/O operations. */ +#define O_SYNC 0x0200 /**< Write according to synchronized I/O file integrity completion. */ +/**@} */ + +/** + * @name Mask for file access modes. + */ +/**@{ */ +#define O_ACCMODE 0xF000 +/**@} */ + +/** + * @name File access modes for open(), openat(), and fcntl(). + */ +/**@{ */ +#define O_EXEC 0x1000 /**< Open for execute only (non-directory files). */ +#define O_RDONLY 0x2000 /**< Open for reading only. */ +#define O_RDWR 0xA000 /**< Open for reading and writing. */ +#define O_SEARCH 0x4000 /**< Open directory for search only. */ +#define O_WRONLY 0x8000 /**< Open for writing only. */ +/**@} */ diff --git a/src/lib/libposix/include/posix/mqueue.h b/src/lib/libposix/include/posix/mqueue.h new file mode 100644 index 00000000..936f2774 --- /dev/null +++ b/src/lib/libposix/include/posix/mqueue.h @@ -0,0 +1,239 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : mqueue.h + * Description : This file consists of posix message queue related declarations + * : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/mqueue.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_MQUEUE_H_ + +/* CC+POSIX includes. */ +#include +#include + +/** + * @brief Message queue attributes. + */ +typedef struct mq_attr +{ + long mq_flags; /**< Message queue flags. */ + long mq_maxmsg; /**< Maximum number of messages. */ + long mq_msgsize; /**< Maximum message size. */ + long mq_curmsgs; /**< Number of messages currently queued. */ +}mq_attr_t; + +/** + * @brief Message queue descriptor. + */ +typedef struct mqd_section +{ + size_t id; + char mq_name[posixconfigMQ_NAME_LEN_MAX]; + mq_attr_t attr; + uintptr_t kernel_buff_send; + uintptr_t kernel_buff_recv; +}mqd_section_t; + +typedef void * mqd_t; + +/** + * @brief Close a message queue. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html + * + * @retval 0 - Upon successful completion + * @retval -1 - A error occurred. errno is also set. + * + * @sideeffect Possible errno values + *
+ * EBADF - The mqdes argument is not a valid message queue descriptor. + */ +int mq_close( mqd_t mqdes ); + +/** + * @brief Get message queue attributes. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html + * + * @retval 0 - Upon successful completion + * @retval -1 - A error occurred. errno is also set. + * + * @sideeffect Possible errno values + *
+ * DBADF - The mqdes argument is not a valid message queue descriptor. + */ +int mq_getattr( mqd_t mqdes, + mq_attr_t * mqstat ); + +/** + * @brief Open a message queue. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html + * + * @note Supported name pattern: leading <slash> character in name is always required; + * the maximum length (excluding null-terminator) of the name argument can be NAME_MAX. + * The default value of NAME_MAX in FreeRTOS_POSIX_portable_default.h is 64, which can be + * overwritten by user. + * @note mode argument is not supported. + * @note Supported oflags: O_RDWR, O_CREAT, O_EXCL, and O_NONBLOCK. + * + * @retval Message queue descriptor -- Upon successful completion + * @retval (mqd_t) - 1 -- An error occurred. errno is also set. + * + * @sideeffect Possible errno values + *
+ * EINVAL - name argument is invalid (not following name pattern), + * OR if O_CREAT is specified in oflag with attr argument not NULL and either mq_maxmsg or mq_msgsize is equal to or less than zero, + * OR either O_CREAT or O_EXCL is not set and a queue with the same name is unlinked but pending to be removed. + *
+ * EEXIST - O_CREAT and O_EXCL are set and the named message queue already exists. + *
+ * ENOSPC - There is insufficient space for the creation of the new message queue. + *
+ * ENOENT - O_CREAT is not set and the named message queue does not exist. + */ +mqd_t mq_open( const char * name, + int oflag, + mode_t mode, + mq_attr_t * attr ); + +/** + * @brief Receive a message from a message queue. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html + * + * @note msg_prio argument is not supported. Messages are not checked for corruption. + * + * @retval The length of the selected message in bytes - Upon successful completion. + * The message is removed from the queue + * @retval -1 - An error occurred. errno is also set. + * + * @sideeffect Possible errno values + *
+ * EBADF - The mqdes argument is not a valid message queue descriptor open for reading. + *
+ * EMSGSIZE - The specified message buffer size, msg_len, is less than the message size attribute of the message queue. + *
+ * ETIMEDOUT - The O_NONBLOCK flag was not set when the message queue was opened, + * but no message arrived on the queue before the specified timeout expired. + *
+ * EAGAIN - O_NONBLOCK was set in the message description associated with mqdes, and the specified message queue is empty. + */ +ssize_t mq_receive( mqd_t mqdes, + char * msg_ptr, + size_t msg_len, + unsigned int * msg_prio ); + +/** + * @brief Send a message to a message queue. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html + * + * @note msg_prio argument is not supported. + * + * @retval 0 - Upon successful completion. + * @retval -1 - An error occurred. errno is also set. + * + * @sideeffect Possible errno values + *
+ * EBADF - The mqdes argument is not a valid message queue descriptor open for writing. + *
+ * EMSGSIZE - The specified message length, msg_len, exceeds the message size attribute of the message queue, + * OR insufficient memory for the message to be sent. + *
+ * ETIMEDOUT - The O_NONBLOCK flag was not set when the message queue was opened, + * but the timeout expired before the message could be added to the queue. + *
+ * EAGAIN - The O_NONBLOCK flag is set in the message queue description associated with mqdes, + * and the specified message queue is full. + */ +int mq_send( mqd_t mqdes, + const char * msg_ptr, + size_t msg_len, + unsigned msg_prio ); + +/** + * @brief Receive a message from a message queue with timeout. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_timedreceive.html + * + * @note msg_prio argument is not supported. Messages are not checked for corruption. + * + * @retval The length of the selected message in bytes - Upon successful completion. + * The message is removed from the queue + * @retval -1 - An error occurred. errno is also set. + * + * @sideeffect Possible errno values + *
+ * EBADF - The mqdes argument is not a valid message queue descriptor open for reading. + *
+ * EMSGSIZE - The specified message buffer size, msg_len, is less than the message size attribute of the message queue. + *
+ * EINVAL - The process or thread would have blocked, and the abstime parameter specified a nanoseconds field value + * less than zero or greater than or equal to 1000 million. + *
+ * ETIMEDOUT - The O_NONBLOCK flag was not set when the message queue was opened, + * but no message arrived on the queue before the specified timeout expired. + *
+ * EAGAIN - O_NONBLOCK was set in the message description associated with mqdes, and the specified message queue is empty. + */ +ssize_t mq_timedreceive( mqd_t mqdes, + char * msg_ptr, + size_t msg_len, + unsigned * msg_prio, + const struct timespec * abstime ); + +/** + * @brief Send a message to a message queue with timeout. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_timedsend.html + * + * @note msg_prio argument is not supported. + * + * @retval 0 - Upon successful completion. + * @retval -1 - An error occurred. errno is also set. + * + * @sideeffect Possible errno values + *
+ * EBADF - The mqdes argument is not a valid message queue descriptor open for writing. + *
+ * EMSGSIZE - The specified message length, msg_len, exceeds the message size attribute of the message queue, + * OR insufficient memory for the message to be sent. + *
+ * EINVAL - The process or thread would have blocked, and the abstime parameter specified a nanoseconds field + * value less than zero or greater than or equal to 1000 million. + *
+ * ETIMEDOUT - The O_NONBLOCK flag was not set when the message queue was opened, + * but the timeout expired before the message could be added to the queue. + *
+ * EAGAIN - The O_NONBLOCK flag is set in the message queue description associated with mqdes, + * and the specified message queue is full. + */ +int mq_timedsend( mqd_t mqdes, + const char * msg_ptr, + size_t msg_len, + unsigned msg_prio, + const struct timespec * abstime ); + +/** + * @brief Remove a message queue. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html + * + * @retval 0 - Upon successful completion. + * @retval -1 - An error occurred. errno is also set. + * + * @sideeffect Possible errno values + *
+ * EINVAL - name argument is invalid. Refer to requirements on name argument in mq_open(). + *
+ * ENOENT - The named message queue does not exist. + */ +int mq_unlink( const char * name ); diff --git a/src/lib/libposix/include/posix/pthread.h b/src/lib/libposix/include/posix/pthread.h new file mode 100644 index 00000000..ba4ad394 --- /dev/null +++ b/src/lib/libposix/include/posix/pthread.h @@ -0,0 +1,480 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : pthread.h + * Description : Threads. + * : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_PTHREAD_H_ + +/* CC+POSIX includes. POSIX states that this header shall make symbols + * defined in sched.h and time.h visible. */ +#include "posix/sched.h" +#include "posix/time.h" + +/** + * @name pthread detach state. + */ +/**@{ */ +#define PTHREAD_CREATE_DETACHED 0 /**< Detached. */ +#define PTHREAD_CREATE_JOINABLE 1 /**< Joinable (default). */ +/**@} */ + +/** + * @name Returned to a single thread after a successful pthread_barrier_wait. + * + * @brief POSIX specifies that "The constant PTHREAD_BARRIER_SERIAL_THREAD is defined in + * and its value shall be distinct from any other value returned by pthread_barrier_wait()." + * So it's defined as negative to distinguish it from the errnos, which are positive. + */ +#define PTHREAD_BARRIER_SERIAL_THREAD ( -2 ) + +/** + * @name Mutex types. + */ +/**@{ */ +#ifndef PTHREAD_MUTEX_NORMAL + #define PTHREAD_MUTEX_NORMAL 0 /**< Non-robust, deadlock on relock, does not remember owner. */ +#endif +#ifndef PTHREAD_MUTEX_ERRORCHECK + #define PTHREAD_MUTEX_ERRORCHECK 1 /**< Non-robust, error on relock, remembers owner. */ +#endif +#ifndef PTHREAD_MUTEX_RECURSIVE + #define PTHREAD_MUTEX_RECURSIVE 2 /**< Non-robust, recursive relock, remembers owner. */ +#endif +#ifndef PTHREAD_MUTEX_DEFAULT + #define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL /**< PTHREAD_MUTEX_NORMAL (default). */ +#endif +/**@} */ + +/** + * @name Compile-time initializers. + * + * @brief To use PTHREAD_COND_INITIALIZER, posixconfigENABLE_PTHREAD_COND_T needs to be set to 1 + * in port specific POSIX config file. + * + * To use PTHREAD_MUTEX_INITIALIZER, posixconfigENABLE_PTHREAD_MUTEX_T needs to be set to 1 in + * port specific POSIX config file. + */ +/**@{ */ +#if posixconfigENABLE_PTHREAD_COND_T == 1 + #define PTHREAD_COND_INITIALIZER CC_POSIX_COND_INITIALIZER /**< pthread_cond_t. */ +#endif + +#if posixconfigENABLE_PTHREAD_MUTEX_T == 1 + #define PTHREAD_MUTEX_INITIALIZER CC_POSIX_MUTEX_INITIALIZER /**< pthread_mutex_t. */ +#endif + +/**@} */ + +/** + * @brief Destroy the thread attributes object. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_destroy.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_attr_destroy( pthread_attr_t * attr ); + +/** + * @brief Get detachstate attribute. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getdetachstate.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_attr_getdetachstate( const pthread_attr_t * attr, + int * detachstate ); + +/** + * @brief Get schedparam attribute. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getschedparam.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_attr_getschedparam( const pthread_attr_t * attr, + struct sched_param * param ); + +/** + * @brief Get stacksize attribute. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_getstacksize.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_attr_getstacksize( const pthread_attr_t * attr, + size_t * stacksize ); + +/** + * @brief Initialize the thread attributes object. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_init.html + * + * @retval 0 - Upon successful completion. + * + * @note Currently, only stack size, sched_param, and detach state attributes + * are supported. Also see pthread_attr_get*() and pthread_attr_set*(). + */ +int pthread_attr_init( pthread_attr_t * attr ); + +/** + * @brief Set detachstate attribute. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setdetachstate.html + * + * @retval 0 - Upon successful completion + * @retval EINVAL - The value of detachstate is not valid. Currently, supported detach states are -- + * PTHREAD_CREATE_DETACHED and PTHREAD_CREATE_JOINABLE. + */ +int pthread_attr_setdetachstate( pthread_attr_t * attr, + int detachstate ); + +/** + * @brief Set schedparam attribute. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setschedparam.html + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - The value of param is not valid. + * @retval ENOTSUP - An attempt was made to set the attribute to an unsupported value. + */ +int pthread_attr_setschedparam( pthread_attr_t * attr, + const struct sched_param * param ); + +/** + * @brief Set the schedpolicy attribute. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setschedpolicy.html + * + * @retval 0 - Upon successful completion. + * + * @warning This function is a stub and always returns 0. + */ +int pthread_attr_setschedpolicy( pthread_attr_t * attr, + int policy ); + +/** + * @brief Set stacksize attribute. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_attr_setstacksize.html + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - The value of stacksize is less than {PTHREAD_STACK_MIN}. + */ +int pthread_attr_setstacksize( pthread_attr_t * attr, + size_t stacksize ); + +/** + * @brief Destroy a barrier object. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_barrier_destroy.html + * + * @retval 0 - Upon successful completion. + * + * @note This function does not validate whether there is any thread blocking on the barrier before destroying. + */ +int pthread_barrier_destroy( pthread_barrier_t * barrier ); + +/** + * @brief Initialize a barrier object. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_barrier_init.html + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - The value specified by count is equal to zero. + * @retval ENOMEM - count cannot fit into Kernel event group type OR insufficient memory exists to initialize the barrier. + * + * @note attr is ignored. + * + * @note pthread_barrier_init() is implemented with Kernel event group. + * To ensure count fits in event group, count may be at most 8 when configUSE_16_BIT_TICKS is 1; + * it may be at most 24 otherwise. configUSE_16_BIT_TICKS is configured in application FreeRTOSConfig.h + * file, which defines how many bits tick count type has. See further details and limitation about event + * group and configUSE_16_BIT_TICKS in Kernel site. + */ +int pthread_barrier_init( pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned count ); + +/** + * @brief Synchronize at a barrier. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_barrier_wait.html + * + * @retval PTHREAD_BARRIER_SERIAL_THREAD - Upon successful completion, the first thread. + * @retval 0 - Upon successful completion, other thread(s). + */ +int pthread_barrier_wait( pthread_barrier_t * barrier ); + +/** + * @brief Thread creation. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html + * + * @retval 0 - Upon successful completion. + * @retval EAGAIN - Insufficient memory for either thread structure or task creation. + */ +int pthread_create( pthread_t * thread, + const pthread_attr_t * attr, + void *( *startroutine )( void * ), + void * arg ); + +/** + * @brief Broadcast a condition. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_broadcast.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_cond_broadcast( pthread_cond_t * cond ); + +/** + * @brief Destroy condition variables. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_destroy.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_cond_destroy( pthread_cond_t * cond ); + +/** + * @brief Initialize condition variables. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_init.html + * + * @retval 0 - Upon successful completion. + * @retval ENOMEM - Insufficient memory exists to initialize the condition variable. + * + * @note attr is ignored and treated as NULL. Default setting is always used. + */ +int pthread_cond_init( pthread_cond_t * cond, + const pthread_condattr_t * attr ); + +/** + * @brief Signal a condition. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_signal.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_cond_signal( pthread_cond_t * cond ); + +/** + * @brief Wait on a condition with a timeout. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - The abstime argument passed in does not refer to an initialized structure OR + * the abstime parameter specified a nanoseconds field value less than zero or + * greater than or equal to 1000 million. + * @retval ETIMEDOUT - The time specified by abstime to pthread_cond_timedwait() has passed. + */ +int pthread_cond_timedwait( pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec * abstime ); + +/** + * @brief Wait on a condition. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_wait.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_cond_wait( pthread_cond_t * cond, + pthread_mutex_t * mutex ); + +/** + * @brief Compare thread IDs. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_equal.html + * + * @retval 0 - t1 and t2 are both not NULL && equal. + * @retval non-zero - otherwise. + */ +int pthread_equal( pthread_t t1, + pthread_t t2 ); + +/** + * @brief Thread termination. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_exit.html + * + * @retval void - this function cannot return to its caller. + */ +void pthread_exit( void * value_ptr ); + +/** + * @brief Dynamic thread scheduling parameters access. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_getschedparam.html + * + * @retval 0 - Upon successful completion. + * + * @note policy is always set to SCHED_OTHER by this function. + */ +int pthread_getschedparam( pthread_t thread, + int * policy, + struct sched_param * param ); + +/** + * @brief Wait for thread termination. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html + * + * @retval 0 - Upon successful completion. + * @retval EDEADLK - The value specified by the thread argument to pthread_join() does not refer + * to a joinable thread OR multiple simultaneous calls to pthread_join() + * specifying the same target thread OR the value specified by the thread argument + * to pthread_join() refers to the calling thread. + */ +int pthread_join( pthread_t thread, + void ** retval ); + +/** + * @brief Destroy a mutex. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_destroy.html + * + * @retval 0 - Upon successful completion. + * + * @note If there exists a thread holding this mutex, this function returns 0 with mutex not being destroyed. + */ +int pthread_mutex_destroy( pthread_mutex_t * mutex ); + +/** + * @brief Initialize a mutex. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html + * + * @retval 0 - Upon successful completion. + * @retval ENOMEM - Insufficient memory exists to initialize the mutex structure. + * @retval EAGAIN - Unable to initialize the mutex structure member(s). + */ +int pthread_mutex_init( pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr ); + +/** + * @brief Lock a mutex. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - the abstime parameter specified a nanoseconds field value less than zero + * or greater than or equal to 1000 million. + * @retval EDEADLK - The mutex type is PTHREAD_MUTEX_ERRORCHECK and the current thread already + * owns the mutex. + */ +int pthread_mutex_lock( pthread_mutex_t * mutex ); + +/** + * @brief Lock a mutex with timeout. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_timedlock.html + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - The abstime argument passed in does not refer to an initialized structure OR + * the abstime parameter specified a nanoseconds field value less than zero or + * greater than or equal to 1000 million. + * @retval EDEADLK - The mutex type is PTHREAD_MUTEX_ERRORCHECK and the current thread already owns the mutex. + * @retval ETIMEDOUT - The mutex could not be locked before the specified timeout expired. + */ +int pthread_mutex_timedlock( pthread_mutex_t * mutex, + const struct timespec * abstime ); + +/** + * @brief Attempt to lock a mutex. Fail immediately if mutex is already locked. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_trylock.html + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - the abstime parameter specified a nanoseconds field value less than zero + * or greater than or equal to 1000 million. + * @retval EDEADLK - The mutex type is PTHREAD_MUTEX_ERRORCHECK and the current thread already + * owns the mutex. + * @retval EBUSY - The mutex could not be acquired because it was already locked. + */ +int pthread_mutex_trylock( pthread_mutex_t * mutex ); + +/** + * @brief Unlock a mutex. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html + * + * @retval 0 - Upon successful completion. + * @retval EPERM - The mutex type is PTHREAD_MUTEX_ERRORCHECK or PTHREAD_MUTEX_RECURSIVE, and + * the current thread does not own the mutex. + */ +int pthread_mutex_unlock( pthread_mutex_t * mutex ); + +/** + * @brief Destroy the mutex attributes object. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_destroy.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_mutexattr_destroy( pthread_mutexattr_t * attr ); + +/** + * @brief Get the mutex type attribute. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_gettype.html + * + * @retval 0 - Upon successful completion. + */ +int pthread_mutexattr_gettype( const pthread_mutexattr_t * attr, + int * type ); + +/** + * @brief Initialize the mutex attributes object. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_init.html + * + * @retval 0 - Upon successful completion. + * + * @note Currently, only the type attribute is supported. Also see pthread_mutexattr_settype() + * and pthread_mutexattr_gettype(). + */ +int pthread_mutexattr_init( pthread_mutexattr_t * attr ); + +/** + * @brief Set the mutex type attribute. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_settype.html + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - The value type is invalid. + */ +int pthread_mutexattr_settype( pthread_mutexattr_t * attr, + int type ); + +/** + * @brief Get the calling thread ID. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_self.html + * + * @retval the thread ID of the calling thread. + */ +pthread_t pthread_self( void ); + +/** + * @brief Dynamic thread scheduling parameters access. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_setschedparam.html + * + * @note policy is ignored; only priority (param.sched_priority) may be changed. + * + * @retval 0 - Upon successful completion. + */ +int pthread_setschedparam( pthread_t thread, + int policy, + const struct sched_param * param ); diff --git a/src/lib/libposix/include/posix/sched.h b/src/lib/libposix/include/posix/sched.h new file mode 100644 index 00000000..230f65f1 --- /dev/null +++ b/src/lib/libposix/include/posix/sched.h @@ -0,0 +1,63 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : sched.h + * Description : Execution scheduling. + * : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_SCHED_H_ + +/** + * @name Scheduling Policies + */ +/**@{ */ +#define SCHED_OTHER 0 /**< Another scheduling policy. */ +/**@} */ + +/** + * @brief Scheduling parameters required for implementation of each supported + * scheduling policy. + */ +struct sched_param +{ + int sched_priority; /**< Process or thread execution scheduling priority. */ +}; + +/** + * @brief Get priority limit (max). + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_get_priority_max.html + * + * @note policy is ignored. + * + * @return the maximum priority value (0-based) system configuration allows. + *
+ * e.g. if configMAX_PRIORITIES == 7, this function returns (configMAX_PRIORITIES - 1). + * configMAX_PRIORITIES is configured in application FreeRTOSConfig.h file. + */ +int sched_get_priority_max( int policy ); + +/** + * @brief Get priority limit (min). + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_get_priority_min.html + * + * @note policy is ignored. + */ +int sched_get_priority_min( int policy ); + +/** + * @brief Yield the processor. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html + * + * @retval 0 - Upon successful completion + */ +int sched_yield( void ); diff --git a/src/lib/libposix/include/posix/semaphore.h b/src/lib/libposix/include/posix/semaphore.h new file mode 100644 index 00000000..5ad9f4a1 --- /dev/null +++ b/src/lib/libposix/include/posix/semaphore.h @@ -0,0 +1,122 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : semaphore.h + * Description : This file consists of posix semaphore related declarations + * : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/semaphore.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_SEMAPHORE_H_ + +/* CC+POSIX includes. */ +#include +#include + +/** + * @brief Semaphore type. + */ +typedef PosixSemType_t sem_t; + +/** + * @brief Destroy an unnamed semaphore. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_destroy.html + * + * @retval 0 - upon successful completion + * + * @note Semaphore is destroyed regardless of whether there is any thread currently blocked on this semaphore. + */ +int sem_destroy( sem_t * sem ); + +/** + * @brief Get the value of a semaphore. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_getvalue.html + * + * @retval 0 - Upon successful completion + * + * @note If sem is locked, then the object to which sval points is set to zero. + */ +int sem_getvalue( sem_t * sem, + int * sval ); + +/** + * @brief Initialize an unnamed semaphore. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html + * + * @note pshared is ignored. Semaphores will always be considered "shared". + * + * @retval 0 - upon successful completion + * @retval -1 - otherwise. System error variable errno is also set in this case. + * + * @sideeffect Possible errno values + *
+ * EINVAL - The value argument exceeds {SEM_VALUE_MAX}. + *
+ * ENOSPC - A resource required to initialize the semaphore has been exhausted. + */ +int sem_init( sem_t * sem, + int pshared, + unsigned value ); + +/** + * @brief Unlock a semaphore. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html + * + * @retval 0 - upon successful completion + */ +int sem_post( sem_t * sem ); + +/** + * @brief Lock a semaphore with timeout. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_timedwait.html + * + * @retval 0 - upon successful completion + * @retval -1 - otherwise. System error variable errno is also set in this case. + * + * @sideeffect Possible errno values + *
+ * EINVAL - parameter specified a nanoseconds field value less than zero or greater + * than or equal to 1000 million + *
+ * ETIMEDOUT - The semaphore could not be locked before the specified timeout expired. + * + * @note Deadlock detection is not implemented. + */ +int sem_timedwait( sem_t * sem, + const struct timespec * abstime ); + +/** + * @brief Lock a semaphore if available. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_trywait.html + * + * @retval 0 - upon successful completion + * @retval -1 - otherwise. System error variable errno is also set in this case. + * + * @sideeffect Possible errno values + *
+ * EAGAIN - The semaphore was already locked, so it cannot be immediately locked by the sem_trywait() operation. + */ +int sem_trywait( sem_t * sem ); + +/** + * @brief Lock a semaphore. + * + * @see http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_wait.html + * + * @retval 0 - upon successful completion + * @retval -1 - otherwise. System error variable errno is also set in this case. + * + * @note Deadlock detection is not implemented. + */ +int sem_wait( sem_t * sem ); diff --git a/src/lib/libposix/include/posix/signal.h b/src/lib/libposix/include/posix/signal.h new file mode 100644 index 00000000..e800559f --- /dev/null +++ b/src/lib/libposix/include/posix/signal.h @@ -0,0 +1,45 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : signal.h + * Description : Signals (Signals are currently not implemented in CC+POSIX) + * : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_SIGNAL_H_ + +/** + * @name Values of sigev_notify. + */ +/**@{ */ +#define SIGEV_NONE 0 /**< No asynchronous notification is delivered when the event of interest occurs. */ +#define SIGEV_SIGNAL 1 /**< A queued signal, with an application-defined value, is generated when the event of interest occurs. Not supported. */ +#define SIGEV_THREAD 2 /**< A notification function is called to perform notification. */ +/**@} */ + +/** + * @brief Signal value. + */ +union sigval +{ + int sival_int; /**< Integer signal value. */ + void * sival_ptr; /**< Pointer signal value. */ +}; + +/** + * @brief Signal event structure. + */ +struct sigevent +{ + int sigev_notify; /**< Notification type. A value of SIGEV_SIGNAL is not supported. */ + int sigev_signo; /**< Signal number. This member is ignored. */ + union sigval sigev_value; /**< Signal value. Only the sival_ptr member is used. */ + void ( * sigev_notify_function )( union sigval ); /**< Notification function. */ + pthread_attr_t * sigev_notify_attributes; /**< Notification attributes. */ +}; diff --git a/src/lib/libposix/include/posix/sys/types.h b/src/lib/libposix/include/posix/sys/types.h new file mode 100644 index 00000000..8a0c3348 --- /dev/null +++ b/src/lib/libposix/include/posix/sys/types.h @@ -0,0 +1,170 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : sys/types.h + * Description : Data types. + * : https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_TYPES_H_ + +/* C standard library includes. */ +#include + +/* Kernel types include */ +#include + +/** + * @brief Used for system times in clock ticks or CLOCKS_PER_SEC. + * + * Enabled/disabled by posixconfigENABLE_CLOCK_T. + */ +#if !defined( posixconfigENABLE_CLOCK_T ) || ( posixconfigENABLE_CLOCK_T == 1 ) + typedef uint32_t clock_t; +#endif + +/** + * @brief Used for clock ID type in the clock and timer functions. + * + * Enabled/disabled by posixconfigENABLE_CLOCKID_T. + */ +#if !defined( posixconfigENABLE_CLOCKID_T ) || ( posixconfigENABLE_CLOCKID_T == 1 ) + typedef int clockid_t; +#endif + +/** + * @brief Used for some file attributes. + * + * Enabled/disabled by posixconfigENABLE_MODE_T. + */ +#if !defined( posixconfigENABLE_MODE_T ) || ( posixconfigENABLE_MODE_T == 1 ) + typedef int mode_t; +#endif + +/** + * @brief Used for process IDs and process group IDs. + * + * Enabled/disabled by posixconfigENABLE_PID_T. + */ +#if !defined( posixconfigENABLE_PID_T ) || ( posixconfigENABLE_PID_T == 1 ) + typedef int pid_t; +#endif + +/** + * @brief Used to identify a thread attribute object. + * + * Enabled/disabled by posixconfigENABLE_PTHREAD_ATTR_T. + */ +#if !defined( posixconfigENABLE_PTHREAD_ATTR_T ) || ( posixconfigENABLE_PTHREAD_ATTR_T == 1 ) + typedef PthreadAttrType_t pthread_attr_t; +#endif + +/** + * @brief Used to identify a barrier. + * + * Enabled/disabled by posixconfigENABLE_PTHREAD_BARRIER_T. + */ +#if !defined( posixconfigENABLE_PTHREAD_BARRIER_T ) || ( posixconfigENABLE_PTHREAD_BARRIER_T == 1 ) + typedef PthreadBarrierType_t pthread_barrier_t; +#endif + +/** + * @brief Used to define a barrier attributes object. + */ +typedef void * pthread_barrierattr_t; + +/** + * @brief Used for condition variables. + * + * Enabled/disabled by posixconfigENABLE_PTHREAD_COND_T. + */ +#if !defined( posixconfigENABLE_PTHREAD_COND_T ) || ( posixconfigENABLE_PTHREAD_COND_T == 1 ) + typedef PthreadCondType_t pthread_cond_t; +#endif + +/** + * @brief Used to identify a condition attribute object. + * + * Enabled/disabled by posixconfigENABLE_PTHREAD_CONDATTR_T. + */ +#if !defined( posixconfigENABLE_PTHREAD_CONDATTR_T ) || ( posixconfigENABLE_PTHREAD_CONDATTR_T == 1 ) + typedef void * pthread_condattr_t; +#endif + +/** + * @brief Used for mutexes. + * + * Enabled/disabled by posixconfigENABLE_PTHREAD_MUTEX_T. + */ +#if !defined( posixconfigENABLE_PTHREAD_MUTEX_T ) || ( posixconfigENABLE_PTHREAD_MUTEX_T == 1 ) + typedef PthreadMutexType_t pthread_mutex_t; +#endif + +/** + * @brief Used to identify a mutex attribute object. + * + * Enabled/disabled by posixconfigENABLE_PTHREAD_MUTEXATTR_T. + */ +#if !defined( posixconfigENABLE_PTHREAD_MUTEXATTR_T ) || ( posixconfigENABLE_PTHREAD_MUTEXATTR_T == 1 ) + typedef PthreadMutexAttrType_t pthread_mutexattr_t; +#endif + +/** + * @brief Used to identify a thread. + * + * Enabled/disabled by posixconfigENABLE_PTHREAD_T. + */ +#if !defined( posixconfigENABLE_PTHREAD_T ) || ( posixconfigENABLE_PTHREAD_T == 1 ) + typedef void * pthread_t; +#endif + +/** + * @brief Used for a count of bytes or an error indication. + * + * Enabled/disabled by posixconfigENABLE_SSIZE_T. + */ +#if !defined( posixconfigENABLE_SSIZE_T ) || ( posixconfigENABLE_SSIZE_T == 1 ) + typedef int ssize_t; +#endif + +/** + * @brief Used for time in seconds. + * + * Enabled/disabled by posixconfigENABLE_TIME_T. + */ +#if !defined( posixconfigENABLE_TIME_T ) || ( posixconfigENABLE_TIME_T == 1 ) + typedef int64_t time_t; +#endif + +/** + * @brief Used for timer ID returned by timer_create(). + * + * Enabled/disabled by posixconfigENABLE_TIMER_T. + */ +#if !defined( posixconfigENABLE_TIMER_T ) || ( posixconfigENABLE_TIMER_T == 1 ) + typedef void * timer_t; +#endif + +/** + * @brief Used for time in microseconds. + * + * Enabled/disabled by posixconfigENABLE_USECONDS_T. + */ +#if !defined( posixconfigENABLE_USECONDS_T ) || ( posixconfigENABLE_USECONDS_T == 1 ) + typedef unsigned long useconds_t; +#endif + +/** + * @brief Used for file sizes. + * + * Enabled/disabled by posixconfigENABLE_OFF_T. + */ +#if !defined( posixconfigENABLE_OFF_T ) || ( posixconfigENABLE_OFF_T == 1 ) + typedef long int off_t; +#endif diff --git a/src/lib/libposix/include/posix/time.h b/src/lib/libposix/include/posix/time.h new file mode 100644 index 00000000..9ecd8376 --- /dev/null +++ b/src/lib/libposix/include/posix/time.h @@ -0,0 +1,237 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : time.h + * Description : Time types + * : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_TIME_H_ + +/* CC+POSIX includes. */ +#include +#include + +/** + * @name Unit conversion constants. + */ +/**@{ */ +#define MICROSECONDS_PER_SECOND ( 1000000LL ) /**< Microseconds per second. */ +#define NANOSECONDS_PER_SECOND ( 1000000000LL ) /**< Nanoseconds per second. */ +#define NANOSECONDS_PER_TICK ( NANOSECONDS_PER_SECOND / posixconfigTICK_RATE_HZ ) /**< Nanoseconds per Kernel tick. */ +/**@} */ + +/** + * @name Clock identifiers. + */ +/**@{ */ +#define CLOCK_REALTIME 0 /**< The identifier of the system-wide clock measuring real time. */ +#define CLOCK_MONOTONIC 1 /**< The identifier for the system-wide monotonic clock.*/ +/**@} */ + +/** + * @name A number used to convert the value returned by the clock() function into seconds. + */ +/**@{ */ +#define CLOCKS_PER_SEC ( ( clock_t ) posixconfigTICK_RATE_HZ ) +/**@} */ + +/** + * @name Flag indicating time is absolute. + * + * For functions taking timer objects, this refers to the clock associated with the timer. + */ +/**@{ */ +#define TIMER_ABSTIME 0x01 +/**@} */ + +#if !defined( posixconfigENABLE_TIMESPEC ) || ( posixconfigENABLE_TIMESPEC == 1 ) + +/** + * @brief represents an elapsed time + */ + typedef struct timespec + { + time_t tv_sec; /**< Seconds. */ + long tv_nsec; /**< Nanoseconds. */ + }timespec_t; +#endif + +#if !defined( posixconfigENABLE_ITIMERSPEC ) || ( posixconfigENABLE_ITIMERSPEC == 1 ) + +/** + * @brief timer + */ + typedef struct itimerspec + { + timespec_t it_interval; /**< Timer period. */ + timespec_t it_value; /**< Timer expiration. */ + }itimerspec_t; +#endif + +/** + * @brief Report CPU time used. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock.html + * + * @return The number of Kernel ticks since the scheduler + * was started minus the ticks spent in the idle task. + * + * @note This function does NOT report the number of ticks spent by the calling thread. + */ +clock_t clock( void ); + +/** + * @brief Access a process CPU-time clock. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getcpuclockid.html + * + * @retval EPERM + * + * @note This function is currently unsupported. + * + */ +int clock_getcpuclockid( pid_t pid, + clockid_t * clock_id ); + +/** + * @brief Returns the resolution of a clock. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html + * + * @note clock_id is ignored + * @note This function stores the resolution of the Kernel tick count in the object res points to. + * + * @retval 0 - Upon successful execution + */ +int clock_getres( clockid_t clock_id, + timespec_t * res ); + +/** + * @brief Returns the current value for the specified clock, clock_id. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html + * + * @note clock_id is ignored + * @note this function does not check for overflows of time_t. + * + * @retval 0 - Upon successful completion. + */ +int clock_gettime( clockid_t clock_id, + timespec_t * tp ); + +/** + * @brief High resolution sleep with specifiable clock. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_nanosleep.html + * + * @note clock_id is ignored, as this function uses the Kernel tick count as its clock. + * @note flags is ignored, if INCLUDE_vTaskDelayUntil is 0. i.e. the Kernel function vTaskDelayUntil isn't available. + * @note rmtp is also ignored, as signals are not implemented. + * + * @retval 0 - Upon successful completion. + * @retval EINVAL - The rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 million. + */ +int clock_nanosleep( clockid_t clock_id, + int flags, + const timespec_t * rqtp, + timespec_t * rmtp ); + +/** + * @brief Sets the time for the specified clock. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_settime.html + * + * @retval -1 with errno set to EPERM. + * + * @note This function is currently unsupported, as Kernel does not provide a function to modify the tick count. + */ +int clock_settime( clockid_t clock_id, + const timespec_t * tp ); + +/** + * @brief High resolution sleep. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/nanosleep.html + * + * @note rmtp is ignored, as signals are not implemented. + * + * @retval 0 - Upon successful completion. + * @retval -1 - The rqtp argument is invalid OR the rqtp argument specified a nanosecond value less than zero or greater than or equal to 1000 million. + * + */ +int nanosleep( const timespec_t * rqtp, + timespec_t * rmtp ); + +/** + * @brief Create a per-process timer. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_create.html + * + * @note clock_id is ignored, as this function used the Kernel tick count as its clock. + * @note evp.sigev_notify must be set to SIGEV_THREAD, since signals are currently not supported. + * + * @retval 0 - Upon successful completion, with location referenced by timerid updated. + * @retval -1 - If an error occurs. errno is also set. + * + * @sideeffect Possible errno values + *
+ * ENOTSUP - If evp is NULL OR evp->sigen_notify == SIGEV_SIGNAL. + *
+ * EAGAIN - The system lacks sufficient signal queuing resources to honor the request. + */ +int timer_create( clockid_t clockid, + struct sigevent * evp, + timer_t * timerid ); + +/** + * @brief Delete a per-process timer. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_delete.html + * + * @retval 0 - Upon successful completion. + */ +int timer_delete( timer_t timerid ); + +/** + * @brief Get the timer overrun count. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html + * + * @retval 0 - Always return 0, since signals are not supported. + */ +int timer_getoverrun( timer_t timerid ); + +/** + * @brief Get the amount of time until the timer expires. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_gettime.html + * + * @retval 0 - Upon successful completion. + */ +int timer_gettime( timer_t timerid, + itimerspec_t * value ); + +/** + * @brief Set the time until the next expiration of the timer. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_settime.html + * + * @retval 0 - Upon successful completion. + * @retval -1 - An error occurred, errno is also set. + * + * @sideeffect Possible errno values + *
+ * EINVAL - A value structure specified a nanosecond value less than zero or greater than or equal to 1000 million, + * AND the it_value member of that structure did not specify zero seconds and nanoseconds. + */ +int timer_settime( timer_t timerid, + int flags, + const itimerspec_t * value, + itimerspec_t * ovalue ); diff --git a/src/lib/libposix/include/posix/unistd.h b/src/lib/libposix/include/posix/unistd.h new file mode 100644 index 00000000..c37db52e --- /dev/null +++ b/src/lib/libposix/include/posix/unistd.h @@ -0,0 +1,40 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : unistd.h + * Description : Standard symbolic constants and types + * : http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html + * + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#include "posix/sys/types.h" + +#define _CC_POSIX_UNISTD_H_ + +/** + * @brief Suspend execution for an interval of time. + * + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html + * + * @param[in] seconds The number of seconds to suspend execution. + * + * @retval 0 - Upon successful completion. + * + * @note Return value of a positive number is not yet supported. + */ +unsigned sleep( unsigned seconds ); + +/** + * @brief Suspend execution for microsecond intervals. + * + * This is a useful, non-POSIX function. + * @param[in] usec The number of microseconds to suspend execution. + * + * @retval 0 - Upon successful completion. + */ +int usleep( useconds_t usec ); diff --git a/src/lib/libposix/include/posix/utils.h b/src/lib/libposix/include/posix/utils.h new file mode 100644 index 00000000..4e08b5fc --- /dev/null +++ b/src/lib/libposix/include/posix/utils.h @@ -0,0 +1,149 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : utils.h + * Description : Utility functions used by CC_POSIX + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#pragma once + +#define _CC_POSIX_UTILS_ + +/* C standard library includes. */ +#include +#include + +/* CC+POSIX includes. */ +#include + +#define DELAY_MIN_TICK (1U) +#define DO_NOTHING +#define RST_VAL (0) +#define ASSERT_IF_FALSE(con, type) RET_ERR_IF_FALSE(con, -EINVAL, type) +#define RET_ERR_IF_FALSE(con, ret, type) if(!(con)){return (type) ret;} +#define IS_ISR() true + +/** + * @brief Calculates the length of pcString, up to xMaxLength. + * + * @param[in] pcString The string to find the length of. + * @param[in] xMaxLength The limit when searching for the end of pcString. + * + * @return 0 if pcString is NULL; otherwise, the length of pcString or xMaxLength, + * whichever is smaller. + */ +size_t UTILS_strnlen( const char * const pcString, + size_t xMaxLength ); + +/** + * @brief Calculates the number of ticks between now and a given timespec. + * + * @param[in] pxAbsoluteTime A time in the future, specified as seconds and + * nanoseconds since CLOCK_REALTIME's 0. + * @param[in] pxCurrentTime current time, specified as seconds and + * nanoseconds. + * @param[out] pxResult Where the result of the conversion is stored. The result + * is rounded up for fractional ticks. + * + * @return 0 on success. Otherwise, ETIMEDOUT if pxAbsoluteTime is in the past, + * or EINVAL for invalid parameters. + */ +int UTILS_AbsoluteTimespecToDeltaTicks( const struct timespec * const pxAbsoluteTime, + const struct timespec * const pxCurrentTime, + TickType_t * const pxResult ); + +/** + * @brief Converts a struct timespec to Kernel ticks. + * + * @param[in] pxTimespec The timespec to convert. + * @param[out] Where the result of the conversion is stored. The result is rounded + * up for fractional ticks. + * + * @return 0 on success. Otherwise, EINVAL for invalid parameters. + */ +int UTILS_TimespecToTicks( const struct timespec * const pxTimespec, + TickType_t * const pxResult ); + +/** + * @brief Converts an integer value to a timespec. + * + * @param[in] llSource The value to convert. + * @param[out] pxDestination Where to store the converted value. + * + * @return No return value. + */ +void UTILS_NanosecondsToTimespec( int64_t llSource, + struct timespec * const pxDestination ); + +/** + * @brief Calculates pxResult = x + y. + * + * @param[in] x The first argument for addition. + * @param[in] y The second argument for addition. + * @param[out] pxResult Where the result of the calculation is stored. + * + * @return -1 if any argument was NULL; 1 if result is negative (overflow); otherwise, 0. + */ +int UTILS_TimespecAdd( const struct timespec * const x, + const struct timespec * const y, + struct timespec * const pxResult ); + +/** + * @brief Calculates pxResult = x + ( struct timespec ) nanosec. + * + * @param[in] x The first argument for addition. + * @param[in] llNanoseconds The second argument for addition. + * @param[out] pxResult Where the result of the calculation is stored. + * + * @return -1 if pxResult or x was NULL; 1 if result is negative; otherwise, 0. + */ +int UTILS_TimespecAddNanoseconds( const struct timespec * const x, + int64_t llNanoseconds, + struct timespec * const pxResult ); + +/** + * @brief Calculates pxResult = x - y. If the result is negative contents of + * pResult are undefined + * + * @param[in] x The first argument for subtraction. + * @param[in] y The second argument for subtraction. + * @param[out] pxResult Where the result of the calculation is stored. + * + * @return -1 if any argument was NULL; 1 if result is negative; otherwise, 0. + */ +int UTILS_TimespecSubtract( const struct timespec * const x, + const struct timespec * const y, + struct timespec * const pxResult ); + +/** + * @brief Compare x == y. + * + * @param[in] x The first argument for comparison. + * @param[in] y The second argument for comparison. + * + * @return 0 if x == y; 1 if x > y; -1 if x < y or any argument was NULL + */ +int UTILS_TimespecCompare( const struct timespec * const x, + const struct timespec * const y ); + +/** + * @brief Checks that a timespec conforms to POSIX. + * + * A valid timespec must have 0 <= tv_nsec < 1000000000. + * + * @param[in] pxTimespec The timespec to validate. + * + * @return true if the pxTimespec is valid, false otherwise. + */ +bool UTILS_ValidateTimespec( const struct timespec * const pxTimespec ); +/** + * @brief Creates OS delay according to number of ticks provided + * + * @param[in] ticks Number of OS ticks to delay + * + * @return None + */ +void os_delay_ticks( const TickType_t ticks ); diff --git a/src/lib/libposix/src/build.mk b/src/lib/libposix/src/build.mk new file mode 100644 index 00000000..79a75548 --- /dev/null +++ b/src/lib/libposix/src/build.mk @@ -0,0 +1,14 @@ +# +# CYANCORE LICENSE +# Copyrights (C) 2019, Cyancore Team +# +# File Name : build.mk +# Descrption : This script accumulates all dp sources and +# generated dp library objects +# Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] +# Organisation : Cyancore Core-Team +# + +DIR := $(GET_PATH) + +include mk/lobj.mk diff --git a/src/lib/libposix/src/posix_mqueue.c b/src/lib/libposix/src/posix_mqueue.c new file mode 100644 index 00000000..0c3bfb90 --- /dev/null +++ b/src/lib/libposix/src/posix_mqueue.c @@ -0,0 +1,383 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : posix_mqueue.c + * Description : This file consists of posix message queue related call handles + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DELAY_MIN_TICK (1U) +#define IS_ISR() true + +size_t g_mq_id_ctr = RST_VAL; + +pthread_mutex_t g_mq_mutex; +pthread_mutexattr_t g_mq_mutex_attr = NULL; + +/********************* + * Static Functions + ********************/ + +static int s_find_queue_in_desc_list(char * name, mqd_section_t * p_mqd_section) +{ + (void)(name); + (void)(p_mqd_section); + return SUCCESS; +} + +static int s_queue_desc_allocator(size_t index, mqd_section_t ** p_mqd_section) +{ + (void)(index); + (void)(p_mqd_section); + return SUCCESS; +} + +static int s_queue_desc_deallocator(mqd_section_t ** p_mqd_section) +{ + (void)(p_mqd_section); + return SUCCESS; +} + +static int s_queue_write(mqd_t mqdes, const void * buff, size_t size, unsigned msg_prio) +{ + mqd_section_t * p_mqd_section = (mqd_section_t *) mqdes; + sret_t mq_sys_ret; + + RET_ERR_IF_FALSE((p_mqd_section->attr.mq_flags & O_RDONLY), -ENOTSUP, int); + + memcpy((void *)p_mqd_section->kernel_buff_send, buff, size); + + super_call(scall_id_mq_send, p_mqd_section->kernel_buff_send, size, msg_prio, &mq_sys_ret); + RET_ERR_IF_FALSE(mq_sys_ret.status == SUCCESS, -EBADF, int); + + return SUCCESS; +} + +static int s_queue_read(mqd_t mqdes, const void * buff, size_t size) +{ + mqd_section_t * p_mqd_section = (mqd_section_t *) mqdes; + sret_t mq_sys_ret; + + RET_ERR_IF_FALSE((p_mqd_section->attr.mq_flags & O_WRONLY), -ENOTSUP, int); + + super_call(scall_id_mq_receive, p_mqd_section->kernel_buff_recv, size, RST_VAL, &mq_sys_ret); + RET_ERR_IF_FALSE(mq_sys_ret.status == SUCCESS, -EBADF, int); + + memcpy((void *)buff, (void *) (mq_sys_ret.p), size); + + return SUCCESS; +} + +static int s_mq_lock_init(void) +{ + pthread_mutexattr_init(&g_mq_mutex_attr); + return pthread_mutex_init(&g_mq_mutex, &g_mq_mutex_attr); +} + +static int s_mq_lock_deinit(void) +{ + pthread_mutexattr_destroy(&g_mq_mutex_attr); + return pthread_mutex_destroy(&g_mq_mutex); +} + +static int s_mq_acquire_lock(void) +{ + return pthread_mutex_lock(&g_mq_mutex); +} + +static int s_mq_release_lock(void) +{ + return pthread_mutex_unlock(&g_mq_mutex); +} + +/********************* + * POSIX Functions + ********************/ + +mqd_t mq_open( const char * name, + int oflag, + mode_t mode _UNUSED, + mq_attr_t * attr ) +{ + mqd_section_t * p_mqd_section = NULL; + sret_t mq_sys_ret; + size_t name_len = UTILS_strnlen(name, posixconfigMQ_NAME_LEN_MAX); + + /* Check argument assertions */ + ASSERT_IF_FALSE(name != NULL, mqd_t); + ASSERT_IF_FALSE( name_len < posixconfigMQ_NAME_LEN_MAX, mqd_t); + + /* Return ENOENT if element already exist */ + RET_ERR_IF_FALSE(s_find_queue_in_desc_list((char *) name, NULL) == SUCCESS, -ENOENT, mqd_t); + + /* Return ENOENT if oflag is not equal to O_CREAT */ + RET_ERR_IF_FALSE( oflag & O_CREAT, -ENOENT, mqd_t); + + /* Initialise lock */ + p_mqd_section = (mqd_section_t *) s_mq_lock_init(); + RET_ERR_IF_FALSE(p_mqd_section == SUCCESS , p_mqd_section, mqd_t); + + /* Grab resource access else return EBUSY */ + RET_ERR_IF_FALSE( s_mq_acquire_lock() == SUCCESS, -EBUSY, mqd_t); + + /* Find available slot in descriptor table else return ENOSPC */ + if(s_queue_desc_allocator(g_mq_id_ctr++, &p_mqd_section ) == SUCCESS) + { + if (attr != NULL) + { + /* Fill user attributes */ + memcpy(&(p_mqd_section->attr), attr, sizeof(mq_attr_t)); + } + else + { /* Fill default attribute vals */ + p_mqd_section->attr.mq_maxmsg = posixconfigMQ_MAX_MESSAGES; + p_mqd_section->attr.mq_msgsize = posixconfigMQ_MAX_SIZE; + } + + p_mqd_section->attr.mq_flags = oflag; + + /* Perform super_call */ + super_call(scall_id_mq_open, + (p_mqd_section->attr.mq_maxmsg * p_mqd_section->attr.mq_msgsize), + (unsigned int) &(p_mqd_section->kernel_buff_send), + (unsigned int) &(p_mqd_section->kernel_buff_recv), + &mq_sys_ret + ); + if (mq_sys_ret.status != SUCCESS) + { + p_mqd_section = (mqd_section_t *) -ENOTSUP; + } + else + { + /* Set queue name as specified */ + memcpy(&(p_mqd_section->mq_name), name, name_len); + } + } + else + { + DO_NOTHING; + } + + RET_ERR_IF_FALSE( s_mq_release_lock() == SUCCESS, -EBUSY, mqd_t); + + return (mqd_t) p_mqd_section; +} + +int mq_close( mqd_t mqdes ) +{ + int err = SUCCESS; + sret_t mq_sys_ret; + + ASSERT_IF_FALSE(mqdes != NULL, ssize_t); + + /* Grab resource access else return EBUSY */ + RET_ERR_IF_FALSE( s_mq_acquire_lock() == SUCCESS, -EBUSY, int); + + /* Return ENOENT if element already exist */ + if (s_find_queue_in_desc_list(NULL, (mqd_section_t *) mqdes) == SUCCESS) + { + /* Reset attr values */ + memset(&((mqd_section_t *) mqdes)->attr, RST_VAL, sizeof(mq_attr_t)); + + /* Perform Super Call */ + super_call(scall_id_mq_close, ((mqd_section_t *) mqdes)->kernel_buff_send, RST_VAL, RST_VAL, &mq_sys_ret); + if (mq_sys_ret.status != SUCCESS) + { + err = -ENOTSUP; + } + else + { + /* Deallocate the descriptor section from user space */ + err = s_queue_desc_deallocator((mqd_section_t **) &mqdes); + } + } + else + { + err = -EBADF; + } + + RET_ERR_IF_FALSE( s_mq_release_lock() == SUCCESS, -EBUSY, ssize_t); + + RET_ERR_IF_FALSE( s_mq_lock_deinit() == SUCCESS, err, ssize_t ); + + return err; +} + +int mq_getattr( mqd_t mqdes, + mq_attr_t * attr ) +{ + ASSERT_IF_FALSE(mqdes != NULL, ssize_t); + + memcpy(attr, &(((mqd_section_t *) mqdes)->attr), sizeof(mq_attr_t)); + + return SUCCESS; +} + +ssize_t mq_receive( mqd_t mqdes, + char * msg_ptr, + size_t msg_len, + unsigned int * msg_prio ) +{ + return mq_timedreceive( mqdes, msg_ptr, msg_len, msg_prio, NULL ); +} + +int mq_send( mqd_t mqdes, + const char * msg_ptr, + size_t msg_len, + unsigned msg_prio ) +{ + return mq_timedsend( mqdes, msg_ptr, msg_len, msg_prio, NULL ); +} + +ssize_t mq_timedreceive( mqd_t mqdes, + char * msg_ptr, + size_t msg_len, + unsigned * msg_prio _UNUSED, + const timespec_t * abstime ) +{ + ASSERT_IF_FALSE(mqdes != NULL, ssize_t); + ASSERT_IF_FALSE(msg_ptr != NULL, ssize_t); + ASSERT_IF_FALSE(msg_len > RST_VAL, ssize_t); + + ssize_t err = SUCCESS; + TickType_t abs_ticks; + + if (abstime == NULL) + { + abs_ticks = IS_ISR() ? RST_VAL : posixconfigMAX_DELAY; + } + + else + { + ASSERT_IF_FALSE ( UTILS_TimespecToTicks(abstime, &abs_ticks) == SUCCESS, ssize_t ); + } + + /* Grab resource access else return EBUSY */ + RET_ERR_IF_FALSE( s_mq_acquire_lock() == SUCCESS, -EBUSY, ssize_t); + + /* Check the availability of the Queue entry */ + if (s_find_queue_in_desc_list(NULL, (mqd_section_t *) mqdes) == SUCCESS) + { + do + { + /* Try to read queue from kernel */ + if (s_queue_read(mqdes, msg_ptr, msg_len) == SUCCESS) + { + break; + } + else + { + if (((mqd_section_t *) mqdes)->attr.mq_flags & O_NONBLOCK) + { + err = -ENOSPC; + break; + } + else + { + if (abs_ticks == RST_VAL) + { + err = -ETIMEDOUT; + } + else + { + os_delay_ticks((const TickType_t)DELAY_MIN_TICK); + abs_ticks--; + } + } + } + }while(abs_ticks > RST_VAL); + } + else + { + err = -EBADF; + } + + RET_ERR_IF_FALSE( s_mq_release_lock() == SUCCESS, -EBUSY, ssize_t ); + + return err; +} + +int mq_timedsend( mqd_t mqdes, + const char * msg_ptr, + size_t msg_len, + unsigned msg_prio, + const struct timespec * abstime ) +{ + ASSERT_IF_FALSE(mqdes != NULL, int); + ASSERT_IF_FALSE(msg_ptr != NULL, int); + ASSERT_IF_FALSE(msg_len > RST_VAL, int); + + ssize_t err = SUCCESS; + TickType_t abs_ticks; + + if (abstime == NULL) + { + abs_ticks = IS_ISR() ? RST_VAL : posixconfigMAX_DELAY; + } + + else + { + ASSERT_IF_FALSE (UTILS_TimespecToTicks(abstime, &abs_ticks) == SUCCESS, ssize_t); + } + + /* Grab resource access else return EBUSY */ + RET_ERR_IF_FALSE( s_mq_acquire_lock() == SUCCESS, -EBUSY, ssize_t); + + /* Check the availability of the Queue entry */ + if (s_find_queue_in_desc_list(NULL, (mqd_section_t *) mqdes) == SUCCESS) + { + do + { + /* Try to send to kernel queue buffer */ + if (s_queue_write(mqdes, msg_ptr, msg_len, msg_prio) == SUCCESS) + { + break; + } + else + { + if (((mqd_section_t *) mqdes)->attr.mq_flags & O_NONBLOCK) + { + err = -ENOSPC; + break; + } + else + { + if (abs_ticks == RST_VAL) + { + err = -ETIMEDOUT; + } + else + { + os_delay_ticks((const TickType_t)DELAY_MIN_TICK); + abs_ticks--;; + } + } + } + }while(abs_ticks > RST_VAL); + } + else + { + err = -EBADF; + } + + RET_ERR_IF_FALSE( s_mq_release_lock() == SUCCESS, -EBUSY, ssize_t ); + + return err; +} + +int mq_unlink( const char * name ) +{ + (void)(name); + return SUCCESS; +} diff --git a/src/lib/libposix/src/posix_semaphore.c b/src/lib/libposix/src/posix_semaphore.c new file mode 100644 index 00000000..d1d943ff --- /dev/null +++ b/src/lib/libposix/src/posix_semaphore.c @@ -0,0 +1,152 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : posix_semaphore.c + * Description : This file consists of posix semaphore related call handles + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#include +#include +#include +#include +#include +#include + +/********************* + * Static Functions + ********************/ +static int s_sem_wait( sem_t * sem ) +{ + sret_t sem_sys_ret= + { + .status = SUCCESS + }; + ASSERT_IF_FALSE(sem != NULL, int); + + super_call(scall_id_sem_wait, (uintptr_t) *sem, RST_VAL, RST_VAL, &sem_sys_ret); + + return sem_sys_ret.status; +} + +/********************* + * POSIX Functions + ********************/ +int sem_destroy( sem_t * sem ) +{ + sret_t sem_sys_ret= + { + .status = SUCCESS + }; + ASSERT_IF_FALSE(sem != NULL, int); + + super_call(scall_id_sem_destroy, (uintptr_t) *sem, RST_VAL, RST_VAL, &sem_sys_ret); + RET_ERR_IF_FALSE(sem_sys_ret.status == SUCCESS, sem_sys_ret.status, int); + + *sem = (sem_t) NULL; + + return SUCCESS; +} + +int sem_getvalue( sem_t * sem, + int * sval ) +{ + sret_t sem_sys_ret= + { + .status = SUCCESS + }; + ASSERT_IF_FALSE(sem != NULL, int); + + super_call(scall_id_sem_getvalue, (uintptr_t) *sem, RST_VAL, RST_VAL, &sem_sys_ret); + RET_ERR_IF_FALSE(sem_sys_ret.status == SUCCESS, sem_sys_ret.status, int); + + *sval = (int) sem_sys_ret.p; + + return SUCCESS; +} + +int sem_init( sem_t * sem, + int pshared _UNUSED, + unsigned value ) +{ + sret_t sem_sys_ret= + { + .status = SUCCESS + }; + + ASSERT_IF_FALSE(sem != NULL, int); + + super_call(scall_id_sem_init, value, RST_VAL, RST_VAL, &sem_sys_ret); + RET_ERR_IF_FALSE(sem_sys_ret.status == SUCCESS, sem_sys_ret.status, int); + + *sem = (sem_t) sem_sys_ret.p; + + return SUCCESS; +} + +int sem_post( sem_t * sem ) +{ + sret_t sem_sys_ret= + { + .status = SUCCESS + }; + ASSERT_IF_FALSE(sem != NULL, int); + + super_call(scall_id_sem_post, (uintptr_t) *sem, RST_VAL, RST_VAL, &sem_sys_ret); + + return sem_sys_ret.status; +} + +int sem_timedwait( sem_t * sem, + const struct timespec * abstime ) +{ + ASSERT_IF_FALSE(sem != NULL, int); + + int err = SUCCESS; + TickType_t abs_ticks; + + if (abstime == NULL) + { + abs_ticks = IS_ISR() ? RST_VAL : posixconfigMAX_DELAY; + } + + else + { + ASSERT_IF_FALSE ( UTILS_TimespecToTicks(abstime, &abs_ticks) == SUCCESS, ssize_t ); + } + + do + { + if (s_sem_wait(sem) == SUCCESS) + { + break; + } + else + { + if (abs_ticks == RST_VAL) + { + err = -ETIMEDOUT; + } + else + { + os_delay_ticks((const TickType_t)DELAY_MIN_TICK); + abs_ticks--; + } + } + + }while(abs_ticks > RST_VAL); + + return err; +} + +int sem_trywait( sem_t * sem ) +{ + return sem_timedwait(sem, RST_VAL); +} + +int sem_wait( sem_t * sem ) +{ + return sem_timedwait(sem, NULL); +} diff --git a/src/lib/libposix/src/posix_time.c b/src/lib/libposix/src/posix_time.c new file mode 100644 index 00000000..0584e054 --- /dev/null +++ b/src/lib/libposix/src/posix_time.c @@ -0,0 +1,120 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : posix_time.c + * Description : This file consists of posix time related call handles + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#include +#include +#include + +unsigned sleep( unsigned seconds ) +{ + return (unsigned) usleep(MICROSECONDS_PER_SECOND * seconds); +} + +int usleep( useconds_t usec ) +{ + (void) usec; + return SUCCESS; +} + +clock_t clock( void ) +{ + return (clock_t) 0; +} + +int clock_getcpuclockid( pid_t pid, clockid_t * clock_id ) +{ + (void)(pid); + (void)(clock_id); + return SUCCESS; +} + +int clock_getres( clockid_t clock_id, struct timespec * res ) +{ + (void)(clock_id); + (void)(res); + return SUCCESS; +} + +int clock_gettime( clockid_t clock_id, struct timespec * tp ) +{ + (void)(clock_id); + (void)(tp); + return SUCCESS; +} + +int clock_nanosleep( clockid_t clock_id, + int flags, + const struct timespec * rqtp, + struct timespec * rmtp ) +{ + (void)(clock_id); + (void)(flags); + (void)(rqtp); + (void)(rmtp); + return SUCCESS; +} + +int clock_settime( clockid_t clock_id, + const struct timespec * tp ) +{ + (void)(clock_id); + (void)(tp); + return SUCCESS; +} + +int nanosleep( const struct timespec * rqtp, + struct timespec * rmtp ) +{ + (void)(rqtp); + (void)(rmtp); + return SUCCESS; +} + +int timer_create( clockid_t clock_id, + struct sigevent * evp, + timer_t * timerid ) +{ + (void)(clock_id); + (void)(evp); + (void)(timerid); + return SUCCESS; +} + +int timer_delete( timer_t timerid ) +{ + (void)(timerid); + return SUCCESS; +} + +int timer_getoverrun( timer_t timerid ) +{ + (void)(timerid); + return SUCCESS; +} + +int timer_gettime( timer_t timerid, + struct itimerspec * value ) +{ + (void)(timerid); + (void)(value); + return SUCCESS; +} + +int timer_settime( timer_t timerid, + int flags, + const struct itimerspec * value, + struct itimerspec * ovalue ) +{ + (void)(timerid); + (void)(flags); + (void)(value); + (void)(ovalue); + return SUCCESS; +} diff --git a/src/lib/libposix/src/posix_utils.c b/src/lib/libposix/src/posix_utils.c new file mode 100644 index 00000000..fca2a824 --- /dev/null +++ b/src/lib/libposix/src/posix_utils.c @@ -0,0 +1,348 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : posix_utils.c + * Description : This file consists of posix utils call handles + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#include +#include +#include +#include +#include + +size_t UTILS_strnlen( const char * const pcString, size_t xMaxLength ) +{ + size_t len = 0; + if (pcString != NULL) + { + while((len < xMaxLength) && (pcString[len] != '\0')) + { + len++; + } + } + + return len; +} +int UTILS_AbsoluteTimespecToDeltaTicks( const struct timespec * const pxAbsoluteTime, + const struct timespec * const pxCurrentTime, + TickType_t * const pxResult ) +{ + int err_status = 0; + struct timespec time_diff = { 0 }; + + /* Check parameters. */ + if( ( pxAbsoluteTime == NULL ) || ( pxCurrentTime == NULL ) || ( pxResult == NULL ) ) + { + err_status = -EINVAL; + } + + /* Calculate the difference between the current time and absolute time. */ + if( err_status == 0 ) + { + err_status = UTILS_TimespecSubtract( pxAbsoluteTime, pxCurrentTime, &time_diff ); + + if( err_status == 1 ) + { + /* pxAbsoluteTime was in the past. */ + err_status = -ETIMEDOUT; + } + else if( err_status == -1 ) + { + /* error */ + err_status = -EINVAL; + } + } + + /* Convert the time difference to ticks. */ + if( err_status == 0 ) + { + err_status = UTILS_TimespecToTicks( &time_diff, pxResult ); + } + + return err_status; +} + +int UTILS_TimespecToTicks( const struct timespec * const pxTimespec, + TickType_t * const pxResult ) +{ + int err_staus = 0; + int64_t total_ticks; + long nano_secs; + + /* Check parameters. */ + if( ( pxTimespec == NULL ) || ( pxResult == NULL ) ) + { + err_staus = -EINVAL; + } + else if( ( err_staus == 0 ) && ( UTILS_ValidateTimespec( pxTimespec ) == false ) ) + { + err_staus = -EINVAL; + } + + if( err_staus == 0 ) + { + /* Convert timespec.tv_sec to ticks. */ + total_ticks = ( int64_t ) posixconfigTICK_RATE_HZ * ( pxTimespec->tv_sec ); + + /* Convert timespec.tv_nsec to ticks. This value does not have to be checked + * for overflow because a valid timespec has 0 <= tv_nsec < 1000000000 and + * NANOSECONDS_PER_TICK > 1. */ + nano_secs = pxTimespec->tv_nsec / ( long ) NANOSECONDS_PER_TICK + /* Whole nanoseconds. */ + ( long ) ( pxTimespec->tv_nsec % ( long ) NANOSECONDS_PER_TICK != 0 ); /* Add 1 to round up if needed. */ + + /* Add the nanoseconds to the total ticks. */ + total_ticks += ( int64_t ) nano_secs; + + /* Check for overflow */ + if( total_ticks < 0 ) + { + err_staus = -EINVAL; + } + else + { + /* check if TickType_t is 32 bit or 64 bit */ + uint32_t ulTickTypeSize = sizeof( TickType_t ); + + /* check for downcast overflow */ + if( ulTickTypeSize == sizeof( uint32_t ) ) + { + if( total_ticks > UINT_MAX ) + { + err_staus = -EINVAL; + } + } + } + + /* Write result. */ + *pxResult = ( TickType_t ) total_ticks; + } + + return err_staus; +} + +void UTILS_NanosecondsToTimespec( int64_t llSource, + struct timespec * const pxDestination ) +{ + long carry_sec; + + /* Convert to timespec. */ + pxDestination->tv_sec = ( time_t ) ( llSource / NANOSECONDS_PER_SECOND ); + pxDestination->tv_nsec = ( long ) ( llSource % NANOSECONDS_PER_SECOND ); + + /* Subtract from tv_sec if tv_nsec < 0. */ + if( pxDestination->tv_nsec < 0L ) + { + /* Compute the number of seconds to carry. */ + carry_sec = ( pxDestination->tv_nsec / ( long ) NANOSECONDS_PER_SECOND ) + 1L; + + pxDestination->tv_sec -= ( time_t ) ( carry_sec ); + pxDestination->tv_nsec += carry_sec * ( long ) NANOSECONDS_PER_SECOND; + } +} + +int UTILS_TimespecAdd( const struct timespec * const x, + const struct timespec * const y, + struct timespec * const pxResult ) +{ + int64_t partial_sec; + int err_status = 0; + + /* Check parameters. */ + if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) ) + { + err_status = -1; + } + + if( err_status == 0 ) + { + /* Perform addition. */ + pxResult->tv_nsec = x->tv_nsec + y->tv_nsec; + + /* check for overflow in case nsec value was invalid */ + if( pxResult->tv_nsec < 0 ) + { + err_status = 1; + } + else + { + partial_sec = ( pxResult->tv_nsec ) / NANOSECONDS_PER_SECOND; + pxResult->tv_nsec = ( pxResult->tv_nsec ) % NANOSECONDS_PER_SECOND; + pxResult->tv_sec = x->tv_sec + y->tv_sec + partial_sec; + + /* check for overflow */ + if( pxResult->tv_sec < 0 ) + { + err_status = 1; + } + } + } + + return err_status; +} + +int UTILS_TimespecAddNanoseconds( const struct timespec * const x, + int64_t lnano_secs, + struct timespec * const pxResult ) +{ + int64_t total_sec; + int err_status = 0; + + /* Check parameters. */ + if( ( pxResult == NULL ) || ( x == NULL ) ) + { + err_status = -1; + } + + if( err_status == 0 ) + { + /* add nano seconds */ + total_sec = x->tv_nsec + lnano_secs; + + /* check for nano seconds overflow */ + if( total_sec < 0 ) + { + err_status = 1; + } + else + { + pxResult->tv_nsec = total_sec % NANOSECONDS_PER_SECOND; + pxResult->tv_sec = x->tv_sec + ( total_sec / NANOSECONDS_PER_SECOND ); + + /* check for seconds overflow */ + if( pxResult->tv_sec < 0 ) + { + err_status = 1; + } + } + } + + return err_status; +} + +int UTILS_TimespecSubtract( const struct timespec * const x, + const struct timespec * const y, + struct timespec * const pxResult ) +{ + int comp; + int err_status = 0; + + /* Check parameters. */ + if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) ) + { + err_status = -1; + } + + if( err_status == 0 ) + { + comp = UTILS_TimespecCompare( x, y ); + + /* if x < y then result would be negative, return 1 */ + if( comp == -1 ) + { + err_status = 1; + } + else if( comp == 0 ) + { + /* if times are the same return zero */ + pxResult->tv_sec = 0; + pxResult->tv_nsec = 0; + } + else + { + /* If x > y Perform subtraction. */ + pxResult->tv_sec = x->tv_sec - y->tv_sec; + pxResult->tv_nsec = x->tv_nsec - y->tv_nsec; + + /* check if nano seconds value needs to borrow */ + if( pxResult->tv_nsec < 0 ) + { + /* Based on comparison, tv_sec > 0 */ + pxResult->tv_sec--; + pxResult->tv_nsec += ( long ) NANOSECONDS_PER_SECOND; + } + + /* if nano second is negative after borrow, it is an overflow error */ + if( pxResult->tv_nsec < 0 ) + { + err_status = -1; + } + } + } + + return err_status; +} + +int UTILS_TimespecCompare( const struct timespec * const x, + const struct timespec * const y ) +{ + int err_status = 0; + + /* Check parameters */ + if( ( x == NULL ) && ( y == NULL ) ) + { + err_status = 0; + } + else if( y == NULL ) + { + err_status = 1; + } + else if( x == NULL ) + { + err_status = -1; + } + else if( x->tv_sec > y->tv_sec ) + { + err_status = 1; + } + else if( x->tv_sec < y->tv_sec ) + { + err_status = -1; + } + else + { + /* seconds are equal compare nano seconds */ + if( x->tv_nsec > y->tv_nsec ) + { + err_status = 1; + } + else if( x->tv_nsec < y->tv_nsec ) + { + err_status = -1; + } + else + { + err_status = 0; + } + } + + return err_status; +} + +bool UTILS_ValidateTimespec( const struct timespec * const pxTimespec ) +{ + bool ret = false; + + if( pxTimespec != NULL ) + { + /* Verify 0 <= tv_nsec < 1000000000. */ + if( ( pxTimespec->tv_nsec >= 0 ) && + ( pxTimespec->tv_nsec < NANOSECONDS_PER_SECOND ) ) + { + ret = true; + } + } + + return ret; +} + +void os_delay_ticks( const TickType_t ticks ) +{ + sret_t sys_ret; + + super_call(scall_id_pthread_delay_ticks, ticks, RST_VAL, RST_VAL, &sys_ret); + RET_ERR_IF_FALSE(sys_ret.status == SUCCESS, EAGAIN, void); +} diff --git a/src/visor/supervisor/workers/scall/build.mk b/src/visor/supervisor/workers/scall/build.mk new file mode 100644 index 00000000..c07c5394 --- /dev/null +++ b/src/visor/supervisor/workers/scall/build.mk @@ -0,0 +1,17 @@ +# +# CYANCORE LICENSE +# Copyrights (C) 2019, Cyancore Team +# +# File Name : build.mk +# Description : This file builds worker sources +# Primary Author : Akash Kollipara [akashkollipara@gmail.com] +# Organisation : Cyancore Core-Team +# + +MCALL_DIR := $(GET_PATH) + +LD_SUPPLEMENT += $(MCALL_DIR)/scall.ld.sx + +DIR := $(MCALL_DIR) + +include mk/obj.mk diff --git a/src/visor/supervisor/workers/scall/scall.ld.sx b/src/visor/supervisor/workers/scall/scall.ld.sx new file mode 100644 index 00000000..8771727f --- /dev/null +++ b/src/visor/supervisor/workers/scall/scall.ld.sx @@ -0,0 +1,22 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : scall.ld.sx + * Description : This file contains memory layout for the + * cyancore scall framework + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +SECTIONS +{ + .scall_table : + { + PROVIDE(_scall_table_start = .); + KEEP(*(.scall)) + PROVIDE(_scall_table_end = .); + } +} + +INSERT BEFORE .stack; diff --git a/src/visor/supervisor/workers/scall/supervisory_call.c b/src/visor/supervisor/workers/scall/supervisory_call.c new file mode 100644 index 00000000..c53bfa2d --- /dev/null +++ b/src/visor/supervisor/workers/scall/supervisory_call.c @@ -0,0 +1,55 @@ +/* + * CYANCORE LICENSE + * Copyrights (C) 2019, Cyancore Team + * + * File Name : supervisory_call.c + * Description : This file contains sources of supervisory call handler + * Primary Author : Pranjal Chanda [pranjalchanda08@gmail.com] + * Organisation : Cyancore Core-Team + */ + +#include +#include +#include +#include +#include +#include + +/* mcall Table start and end defined in linker script mcall.ld.sx */ +extern scall_t _scall_table_start; +extern scall_t _scall_table_end; + +void super_call(scall_id_t id, unsigned int a0, unsigned int a1, unsigned int a2, sret_t *ret) +{ + /* mcall Table pointer */ + scall_t *ptr; + + /* Assign "ret" parameters to default error case, + * on execution of the call, the ret will updated. + */ + ret->p = (uintptr_t) NULL; + ret->size = 0; + ret->status = error_scall_code_inval; + + /* Assign the pointer to start of table */ + ptr = &_scall_table_start; + + /* Run through the table till the end */ + while(ptr <= & _scall_table_end) + { + /* Check if the mcall ID matches */ + if(ptr->id == id) + { + /* Execute the callback function and update the "ret" */ + if (ptr->callback != NULL) + { + *ret = ptr->callback(a0, a1, a2); + } + /* Stop parsing the table and return */ + break; + } + /* Increament location pointer */ + ptr++; + } + return; +} diff --git a/src/visor/terravisor/workers/mcall/machine_call.c b/src/visor/terravisor/workers/mcall/machine_call.c index 46e7f6bf..a374a10f 100644 --- a/src/visor/terravisor/workers/mcall/machine_call.c +++ b/src/visor/terravisor/workers/mcall/machine_call.c @@ -41,7 +41,10 @@ void machine_call(mcall_id_t id, unsigned int a0, unsigned int a1, unsigned int if(ptr->id == id) { /* Execute the callback function and update the "ret" */ - *ret = ptr->callback(a0, a1, a2); + if (ptr->callback != NULL) + { + *ret = ptr->callback(a0, a1, a2); + } /* Stop parsing the table and return */ break; }