diff --git a/.gitignore b/.gitignore index 38df5eb0..64f98198 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ stamp-h1 .deps/ .libs/ +.dirstamp # Compiled objects *.o diff --git a/configure.ac b/configure.ac index 4c6d7639..900877ed 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,7 @@ AC_CONFIG_FILES([ Makefile inc/Makefile src/Makefile +src/generated/Makefile test/Makefile ]) AC_OUTPUT diff --git a/inc/Makefile.am b/inc/Makefile.am index 24f281f3..75cb2421 100644 --- a/inc/Makefile.am +++ b/inc/Makefile.am @@ -5,6 +5,7 @@ fastrpc_include_HEADERS += $(top_srcdir)/inc/remote.h fastrpc_include_HEADERS += $(top_srcdir)/inc/rpcmem.h noinst_HEADERS = \ + misc/fastrpc.h \ AEEBufBound.h \ AEEQList.h \ AEEStdDef.h \ @@ -13,27 +14,11 @@ noinst_HEADERS = \ HAP_farf.h \ HAP_farf_internal.h \ HAP_pls.h \ - adsp_current_process.h \ - adsp_current_process1.h \ - adsp_default_listener.h \ - adsp_default_listener1.h \ - adsp_listener.h \ - adsp_listener1.h \ - adsp_perf.h \ - adsp_perf1.h \ adsp_pls.h \ - adspmsgd_adsp.h \ - adspmsgd_adsp1.h \ - adspmsgd_apps.h \ adspmsgd_internal.h \ - apps_mem.h \ apps_mem_internal.h \ - apps_remotectl.h \ - apps_std.h \ apps_std_internal.h \ dspqueue.h \ - dspqueue_rpc.h \ - dspqueue_shared.h \ dspsignal.h \ fastrpc_apps_user.h \ fastrpc_async.h \ @@ -57,17 +42,11 @@ noinst_HEADERS = \ listener_buf.h \ log_config.h \ mod_table.h \ - mutex.h \ platform_libs.h \ pls.h \ - remote64.h \ - remotectl.h \ - remotectl1.h \ + pthread_rw_mutex.h \ rpcmem_internal.h \ sbuf.h \ sbuf_parser.h \ - shared.h \ - std_dtoa.h \ uthash.h \ - verify.h \ - version.h + verify.h diff --git a/inc/dspqueue_shared.h b/inc/dspqueue_shared.h deleted file mode 100644 index 958f3420..00000000 --- a/inc/dspqueue_shared.h +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef DSPQUEUE_SHARED_H -#define DSPQUEUE_SHARED_H - -#include -#include -#include "dspqueue.h" - -/* Shared memory queue definitions. - - Each queue is allocated as a single shared ION buffer. The buffer consists of: - * struct dspqueue_header - - request packet queue header. Used for messages from the host CPU to the DSP. - - response packet queue header. Used for messages from the DSP to the host CPU. - * read/write states for each packet queue, including read/write pointers. - Each read/write state structure must be on a separate cache line. - * Request and response packet queues - - Packet queues are circular buffers consisting packet headers and data - - Packets are padded to be 64-bit aligned - - The reader and writer manage read and write positions - - Packets do not wrap around at the end of the queue. If a packet cannot fit before the end - of the queue, the entire packet is written at the beginning. The 64-bit header is replicated. -*/ - - -/* Header structure for each one-way packet queue. - All offsets are in bytes to the beginning of the shared memory queue block. */ -struct dspqueue_packet_queue_header { - uint32_t queue_offset; /* Queue offset */ - uint32_t queue_length; /* Queue length in bytes */ - uint32_t read_state_offset; /* Read state offset. Contains struct dspqueue_packet_queue_state, - describing the state of the reader of this queue. */ - uint32_t write_state_offset; /* Write state offset. Contains a struct dspqueue_packet_queue_state, - describing the state of the writer of this queue. */ -}; - -/* State structure, used to describe the state of the reader or writer of each queue. - The state structure is at an offset from the start of the header as defined in - struct dspqueue_packet_queue_header above, and must fit in a single cache line. */ -struct dspqueue_packet_queue_state { - volatile uint32_t position; /* Position within the queue in bytes */ - volatile uint32_t packet_count; /* Number of packets read/written */ - volatile uint32_t wait_count; /* Non-zero if the reader/writer is waiting for a signal - for a new packet or more space in the queue respectively */ -}; - - -/* Userspace shared memory queue header */ -struct dspqueue_header { - uint32_t version; /* Initial version 1, 2 if any flags are set and need to be checked. */ - int32_t error; - uint32_t flags; - struct dspqueue_packet_queue_header req_queue; /* CPU to DSP */ - struct dspqueue_packet_queue_header resp_queue; /* DSP to CPU */ - uint32_t queue_count; -}; - -/* The version number currently expected if both CPU and DSP sides match */ -#define DSPQUEUE_HEADER_CURRENT_VERSION 2 - -/* Wait counts present in the packet queue header. Set by the CPU, DSP must - fail initialization if the feature is not supported. */ -#define DSPQUEUE_HEADER_FLAG_WAIT_COUNTS 1 - -/* Use driver signaling. Set by the CPU, DSP must fail initialization - if the feature is not supported. */ -#define DSPQUEUE_HEADER_FLAG_DRIVER_SIGNALING 2 - -/* Unexpected flags */ -#define DSPQUEUE_HEADER_UNEXPECTED_FLAGS ~(DSPQUEUE_HEADER_FLAG_WAIT_COUNTS | DSPQUEUE_HEADER_FLAG_DRIVER_SIGNALING) - - -/* Maximum queue size in bytes */ -#define DSPQUEUE_MAX_QUEUE_SIZE 16777216 - -/* Maximum number of buffers in a packet */ -#define DSPQUEUE_MAX_BUFFERS 64 - -/* Maximum message size */ -#define DSPQUEUE_MAX_MESSAGE_SIZE 65536 - -/* Default sizes */ -#define DSPQUEUE_DEFAULT_REQ_SIZE 65536 -#define DSPQUEUE_DEFAULT_RESP_SIZE 16384 - - -/* Maximum number of queues per process. Must ensure the state arrays get cache line aligned. - Update signal allocations in dspsignal.h if this changes. */ -#define DSPQUEUE_MAX_PROCESS_QUEUES 64 - - -/* Process queue information block, used with RPC-based signaling. - - Each participant increments the packet/space count for the - corresponding queue when there is a new packet or more space - available and signals the other party. The other party then goes - through active queues to see which one needs processing. - - This reduces the number of signals to two per process and lets us - use argumentless FastRPC calls for signaling. - */ -struct dspqueue_process_queue_state { - uint32_t req_packet_count[DSPQUEUE_MAX_PROCESS_QUEUES]; - uint32_t req_space_count[DSPQUEUE_MAX_PROCESS_QUEUES]; - uint32_t resp_packet_count[DSPQUEUE_MAX_PROCESS_QUEUES]; - uint32_t resp_space_count[DSPQUEUE_MAX_PROCESS_QUEUES]; -}; - -/* Info specific to multi-domain queues */ -struct dspqueue_multidomain { - /* Flag to indicate if queue is multidomain */ - bool is_mdq; - - /* Multi-domain context id associated with queue */ - uint64_t ctx; - - /* Number of domains on which queue was created */ - unsigned int num_domain_ids; - - /* Effective domain ids on which queue was created */ - unsigned int *effec_domain_ids; - - /* Array of queue handles - one for each domain */ - dspqueue_t *queues; - - /* Array of queue ids - one for each domain */ - uint64_t *dsp_ids; -}; - -/* Signals IDs used with driver signaling. Update the signal allocations in dspsignal.h - if this changes. */ -enum dspqueue_signal { - DSPQUEUE_SIGNAL_REQ_PACKET = 0, - DSPQUEUE_SIGNAL_REQ_SPACE, - DSPQUEUE_SIGNAL_RESP_PACKET, - DSPQUEUE_SIGNAL_RESP_SPACE, - DSPQUEUE_NUM_SIGNALS -}; - - -#endif diff --git a/inc/fastrpc_async.h b/inc/fastrpc_async.h index 76c244dd..28c069fe 100644 --- a/inc/fastrpc_async.h +++ b/inc/fastrpc_async.h @@ -4,7 +4,7 @@ #ifndef FASTRPC_ASYNC_H #define FASTRPC_ASYNC_H -#include "remote64.h" +#include "remote.h" #include "fastrpc_internal.h" #define POS_TO_MASK(pos) ((1UL << pos) - 1) diff --git a/inc/fastrpc_internal.h b/inc/fastrpc_internal.h index 859bfe8c..a00dcdc2 100644 --- a/inc/fastrpc_internal.h +++ b/inc/fastrpc_internal.h @@ -10,7 +10,7 @@ #include "HAP_farf.h" #include "AEEStdErr.h" -#include "remote64.h" +#include "remote.h" #include "verify.h" #include "AEEstd.h" #include "AEEQList.h" @@ -52,9 +52,6 @@ /* Max value of remote_mem_map_flags, used to validate the input flag */ #define REMOTE_MAP_MAX_FLAG REMOTE_MAP_MEM_STATIC + 1 -/* Max value of fastrpc_map_flags, used to validate range of supported flags */ -#define FASTRPC_MAP_MAX FASTRPC_MAP_FD_NOMAP + 1 - #if !(defined __qdsp6__) && !(defined __hexagon__) static __inline uint32_t Q6_R_cl0_R(uint32_t num) { int ii; @@ -231,29 +228,6 @@ enum fastrpc_map_type { MUNMAP_FD, }; -/** - * @brief memory mapping and unmapping data structures used in - * mmap/munmap ioctls. internal datastructures. - * fastrpc_mem_map - used for storing memory map information - * fastrpc_mem_unmap - used while unmapping the memory from the - * local data structures. - **/ -struct fastrpc_mem_map { - int fd; /* ion fd */ - int offset; /* buffer offset */ - uint32_t flags; /* flags defined in enum fastrpc_map_flags */ - int attrs; /* buffer attributes used for SMMU mapping */ - uintptr_t vaddrin; /* buffer virtual address */ - size_t length; /* buffer length */ - uint64_t vaddrout; /* [out] remote virtual address */ -}; - -struct fastrpc_mem_unmap { - int fd; /* ion fd */ - uint64_t vaddr; /* remote process (dsp) virtual address */ - size_t length; /* buffer size */ -}; - struct fastrpc_map { int version; struct fastrpc_mem_map m; diff --git a/inc/fastrpc_ioctl.h b/inc/fastrpc_ioctl.h index 779d0345..29a13279 100644 --- a/inc/fastrpc_ioctl.h +++ b/inc/fastrpc_ioctl.h @@ -5,26 +5,8 @@ #define FASTRPC_INTERNAL_UPSTREAM_H #include -#include -/* File only compiled when support to upstream kernel is required*/ - - -/** - * FastRPC IOCTL functions - **/ -#define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_ioctl_alloc_dma_buf) -#define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, __u32) -#define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_ioctl_invoke) -#define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4) -#define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_ioctl_init_create) -#define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_ioctl_req_mmap) -#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_ioctl_req_munmap) -#define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8) -#define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_ioctl_init_create_static) -#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_ioctl_mem_map) -#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_ioctl_mem_unmap) -#define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability) +#include #define ADSPRPC_DEVICE "/dev/fastrpc-adsp" #define SDSPRPC_DEVICE "/dev/fastrpc-sdsp" @@ -77,102 +59,13 @@ args[i].fd = filedesc; \ args[i].attr = attrs; -#define set_args_ptr(i, pra) args[i].ptr = (uint64_t)pra -#define set_args_len(i, len) args[i].length = len -#define set_args_attr(i, attrs) args[i].attr = attrs #define set_args_fd(i, filedesc) args[i].fd = filedesc -#define get_args_ptr(i) args[i].ptr -#define get_args_len(i) args[i].length -#define get_args_attr(i) args[i].attr -#define get_args_fd(i) args[i].fd #define append_args_attr(i, attrs) args[i].attr |= attrs -#define get_args() args -#define is_upstream() 1 -//Utility macros for reading the ioctl structure -#define NOTIF_GETDOMAIN(response) -1; -#define NOTIF_GETSESSION(response) -1; -#define NOTIF_GETSTATUS(response) -1; - -#define FASTRPC_INVOKE2_STATUS_NOTIF 2 //TODO: Temporary change (Bharath to fix) -#define FASTRPC_INVOKE2_KERNEL_OPTIMIZATIONS 1 //TODO: Temporary change (Bharath to fix) #ifndef FASTRPC_MAX_DSP_ATTRIBUTES_FALLBACK #define FASTRPC_MAX_DSP_ATTRIBUTES_FALLBACK 1 #endif -struct fastrpc_invoke_args { - __u64 ptr; /* pointer to invoke address*/ - __u64 length; /* size*/ - __s32 fd; /* fd */ - __u32 attr; /* invoke attributes */ -}; - -struct fastrpc_ioctl_invoke { - __u32 handle; - __u32 sc; - __u64 args; -}; - -struct fastrpc_ioctl_alloc_dma_buf { - __s32 fd; /* fd */ - __u32 flags; /* flags to map with */ - __u64 size; /* size */ -}; - -struct fastrpc_ioctl_init_create { - __u32 filelen; /* elf file length */ - __s32 filefd; /* fd for the file */ - __u32 attrs; - __u32 siglen; - __u64 file; /* pointer to elf file */ -}; - -struct fastrpc_ioctl_init_create_static { - __u32 namelen; /* length of pd process name */ - __u32 memlen; - __u64 name; /* pd process name */ -}; - -struct fastrpc_ioctl_req_mmap { - __s32 fd; - __u32 flags; /* flags for dsp to map with */ - __u64 vaddrin; /* optional virtual address */ - __u64 size; /* size */ - __u64 vaddrout; /* dsp virtual address */ -}; - -struct fastrpc_ioctl_mem_map { - __s32 version; - __s32 fd; /* fd */ - __s32 offset; /* buffer offset */ - __u32 flags; /* flags defined in enum fastrpc_map_flags */ - __u64 vaddrin; /* buffer virtual address */ - __u64 length; /* buffer length */ - __u64 vaddrout; /* [out] remote virtual address */ - __s32 attrs; /* buffer attributes used for SMMU mapping */ - __s32 reserved[4]; -}; - -struct fastrpc_ioctl_req_munmap { - __u64 vaddrout; /* address to unmap */ - __u64 size; /* size */ -}; - -struct fastrpc_ioctl_mem_unmap { - __s32 version; - __s32 fd; /* fd */ - __u64 vaddr; /* remote process (dsp) virtual address */ - __u64 length; /* buffer size */ - __s32 reserved[5]; -}; - -struct fastrpc_ioctl_capability { - __u32 domain; /* domain of the PD*/ - __u32 attribute_id; /* attribute id*/ - __u32 capability; /* dsp capability */ - __u32 reserved[4]; -}; - /** * @brief internal data strcutures used in remote handle control * fastrpc_ctrl_latency - diff --git a/inc/fastrpc_notif.h b/inc/fastrpc_notif.h index 174e1093..db0614e6 100644 --- a/inc/fastrpc_notif.h +++ b/inc/fastrpc_notif.h @@ -4,7 +4,7 @@ #ifndef FASTRPC_NOTIF_H #define FASTRPC_NOTIF_H -#include "remote64.h" +#include "remote.h" #include "fastrpc_internal.h" /* @@ -21,17 +21,6 @@ int fastrpc_notif_domain_init(int domain); */ void fastrpc_notif_domain_deinit(int domain); -/* - * Internal function to get notification response from kernel. Waits in kernel until notifications are received from DSP - * @ domain: domain to which notification needs to be received - * returns 0 on success - */ -int get_remote_notif_response(int domain); - -/* - * API to cleanup all the clients registered for notifcation - */ -void fastrpc_cleanup_notif_list(); /* * API to register a notification mechanism for a state change in DSP Process. * state changes can be PD start, PD exit, PD crash. diff --git a/inc/misc/fastrpc.h b/inc/misc/fastrpc.h new file mode 100644 index 00000000..ece8bbe6 --- /dev/null +++ b/inc/misc/fastrpc.h @@ -0,0 +1,167 @@ +// Copyright (c) Qualcomm Innovation Center, Inc. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef __QCOM_FASTRPC_H__ +#define __QCOM_FASTRPC_H__ + +#include + +/** + * FastRPC IOCTL functions + **/ +#define FASTRPC_IOCTL_ALLOC_DMA_BUFF _IOWR('R', 1, struct fastrpc_alloc_dma_buf) +#define FASTRPC_IOCTL_FREE_DMA_BUFF _IOWR('R', 2, __u32) +#define FASTRPC_IOCTL_INVOKE _IOWR('R', 3, struct fastrpc_invoke) +#define FASTRPC_IOCTL_INIT_ATTACH _IO('R', 4) +#define FASTRPC_IOCTL_INIT_CREATE _IOWR('R', 5, struct fastrpc_init_create) +#define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_req_mmap) +#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_req_munmap) +#define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8) +#define FASTRPC_IOCTL_INIT_CREATE_STATIC _IOWR('R', 9, struct fastrpc_init_create_static) +#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map) +#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap) +#define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability) + +/** + * @enum fastrpc_map_flags for fastrpc_mmap and fastrpc_munmap + * @brief Types of maps with cache maintenance + */ +enum fastrpc_map_flags { + /** + * Map memory pages with RW- permission and CACHE WRITEBACK. + * Driver will clean cache when buffer passed in a FastRPC call. + * Same remote virtual address will be assigned for subsequent + * FastRPC calls. + */ + FASTRPC_MAP_STATIC, + + /** Reserved for compatibility with deprecated flag */ + FASTRPC_MAP_RESERVED, + + /** + * Map memory pages with RW- permission and CACHE WRITEBACK. + * Mapping tagged with a file descriptor. User is responsible for + * maintenance of CPU and DSP caches for the buffer. Get virtual address + * of buffer on DSP using HAP_mmap_get() and HAP_mmap_put() functions. + */ + FASTRPC_MAP_FD, + + /** + * Mapping delayed until user calls HAP_mmap() and HAP_munmap() + * functions on DSP. User is responsible for maintenance of CPU and DSP + * caches for the buffer. Delayed mapping is useful for users to map + * buffer on DSP with other than default permissions and cache modes + * using HAP_mmap() and HAP_munmap() functions. + */ + FASTRPC_MAP_FD_DELAYED, + + /** Reserved for compatibility **/ + FASTRPC_MAP_RESERVED_4, + FASTRPC_MAP_RESERVED_5, + FASTRPC_MAP_RESERVED_6, + FASTRPC_MAP_RESERVED_7, + FASTRPC_MAP_RESERVED_8, + FASTRPC_MAP_RESERVED_9, + FASTRPC_MAP_RESERVED_10, + FASTRPC_MAP_RESERVED_11, + FASTRPC_MAP_RESERVED_12, + FASTRPC_MAP_RESERVED_13, + FASTRPC_MAP_RESERVED_14, + FASTRPC_MAP_RESERVED_15, + + /** + * This flag is used to skip CPU mapping, + * otherwise behaves similar to FASTRPC_MAP_FD_DELAYED flag. + */ + FASTRPC_MAP_FD_NOMAP, + + /** Update FASTRPC_MAP_MAX when adding new value to this enum **/ +}; + +/* Max value of fastrpc_map_flags, used to validate range of supported flags */ +#define FASTRPC_MAP_MAX FASTRPC_MAP_FD_NOMAP + 1 + +enum fastrpc_proc_attr { + FASTRPC_MODE_DEBUG = 0x1, + FASTRPC_MODE_PTRACE = 0x2, + FASTRPC_MODE_CRC = 0x4, + FASTRPC_MODE_UNSIGNED_MODULE = 0x8, + FASTRPC_MODE_ADAPTIVE_QOS = 0x10, + FASTRPC_MODE_SYSTEM_PROCESS = 0x20, + FASTRPC_MODE_PRIVILEGED = 0x40, // this attribute will be populated in kernel +}; + +struct fastrpc_invoke_args { + __u64 ptr; /* pointer to invoke address*/ + __u64 length; /* size*/ + __s32 fd; /* fd */ + __u32 attr; /* invoke attributes */ +}; + +struct fastrpc_invoke { + __u32 handle; + __u32 sc; + __u64 args; +}; + +struct fastrpc_init_create { + __u32 filelen; /* elf file length */ + __s32 filefd; /* fd for the file */ + __u32 attrs; + __u32 siglen; + __u64 file; /* pointer to elf file */ +}; + +struct fastrpc_init_create_static { + __u32 namelen; /* length of pd process name */ + __u32 memlen; + __u64 name; /* pd process name */ +}; + +struct fastrpc_alloc_dma_buf { + __s32 fd; /* fd */ + __u32 flags; /* flags to map with */ + __u64 size; /* size */ +}; + +struct fastrpc_req_mmap { + __s32 fd; + __u32 flags; /* flags for dsp to map with */ + __u64 vaddrin; /* optional virtual address */ + __u64 size; /* size */ + __u64 vaddrout; /* dsp virtual address */ +}; + +struct fastrpc_mem_map { + __s32 version; + __s32 fd; /* fd */ + __s32 offset; /* buffer offset */ + __u32 flags; /* flags defined in enum fastrpc_map_flags */ + __u64 vaddrin; /* buffer virtual address */ + __u64 length; /* buffer length */ + __u64 vaddrout; /* [out] remote virtual address */ + __s32 attrs; /* buffer attributes used for SMMU mapping */ + __s32 reserved[4]; +}; + +struct fastrpc_req_munmap { + __u64 vaddrout; /* address to unmap */ + __u64 size; /* size */ +}; + +struct fastrpc_mem_unmap { + __s32 version; + __s32 fd; /* fd */ + __u64 vaddr; /* remote process (dsp) virtual address */ + __u64 length; /* buffer size */ + __s32 reserved[5]; +}; + +struct fastrpc_ioctl_capability { + __u32 domain; /* domain of the PD*/ + __u32 attribute_id; /* attribute id*/ + __u32 capability; /* dsp capability */ + __u32 reserved[4]; +}; + +#endif /* __QCOM_FASTRPC_H__ */ diff --git a/inc/mod_table.h b/inc/mod_table.h index b1accd9a..99d9a432 100644 --- a/inc/mod_table.h +++ b/inc/mod_table.h @@ -4,7 +4,7 @@ #ifndef MOD_TABLE_H #define MOD_TABLE_H -#include "remote64.h" +#include "remote.h" #include "AEEStdDef.h" #ifdef __cplusplus diff --git a/inc/mutex.h b/inc/mutex.h deleted file mode 100644 index f230d070..00000000 --- a/inc/mutex.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef MUTEX_H -#define MUTEX_H - -#if (defined __qdsp6__) || (defined __hexagon__) -#include "qurt_mutex.h" - -#define RW_MUTEX_T qurt_mutex_t -#define RW_MUTEX_CTOR(mut) qurt_mutex_init(& (mut)) -#define RW_MUTEX_LOCK_READ(mut) qurt_mutex_lock(& (mut)) -#define RW_MUTEX_UNLOCK_READ(mut) qurt_mutex_unlock(& (mut)) -#define RW_MUTEX_LOCK_WRITE(mut) qurt_mutex_lock(& (mut)) -#define RW_MUTEX_UNLOCK_WRITE(mut) qurt_mutex_unlock(& (mut)) -#define RW_MUTEX_DTOR(mut) qurt_mutex_destroy(& (mut)) - -#elif (1 == __linux) || (1 == __linux__) || (1 == __gnu_linux__) || (1 == linux) - -#include -#include -#include - -/* asserts may be compiled out, this should always be present */ -#define ABORT_FAIL( ff ) \ - do {\ - if(! (ff) ) {\ - fprintf(stderr, "assertion \"%s\" failed: file \"%s\", line %d\n", #ff, __FILE__, __LINE__);\ - abort();\ - }\ - } while(0) - -#define RW_MUTEX_T pthread_rwlock_t -#define RW_MUTEX_CTOR(mut) ABORT_FAIL(0 == pthread_rwlock_init( & (mut), 0)) -#define RW_MUTEX_LOCK_READ(mut) ABORT_FAIL(0 == pthread_rwlock_rdlock( & (mut))) -#define RW_MUTEX_UNLOCK_READ(mut) ABORT_FAIL(0 == pthread_rwlock_unlock( & (mut))) -#define RW_MUTEX_LOCK_WRITE(mut) ABORT_FAIL(0 == pthread_rwlock_wrlock( & (mut))) -#define RW_MUTEX_UNLOCK_WRITE(mut) ABORT_FAIL(0 == pthread_rwlock_unlock( & (mut))) -#define RW_MUTEX_DTOR(mut) ABORT_FAIL(0 == pthread_rwlock_destroy( & (mut))) - - -#else - -#include "AEEstd.h" - -#define RW_MUTEX_T uint32_t -#define RW_MUTEX_CTOR(mut) mut = 0 -#define RW_MUTEX_LOCK_READ(mut) \ - do {\ - assert(STD_BIT_TEST(&mut, 1) == 0); \ - assert(STD_BIT_TEST(&mut, 2) == 0); \ - STD_BIT_SET(&mut, 1); \ - } while (0) - -#define RW_MUTEX_UNLOCK_READ(mut) \ - do {\ - assert(STD_BIT_TEST(&mut, 1)); \ - assert(STD_BIT_TEST(&mut, 2) == 0); \ - STD_BIT_CLEAR(&mut, 1); \ - } while (0) - -#define RW_MUTEX_LOCK_WRITE(mut) \ - do {\ - assert(STD_BIT_TEST(&mut, 1) == 0); \ - assert(STD_BIT_TEST(&mut, 2) == 0); \ - STD_BIT_SET(&mut, 2); \ - } while (0) - -#define RW_MUTEX_UNLOCK_WRITE(mut) \ - do {\ - assert(STD_BIT_TEST(&mut, 1) == 0); \ - assert(STD_BIT_TEST(&mut, 2)); \ - STD_BIT_CLEAR(&mut, 2); \ - } while (0) - -#define RW_MUTEX_DTOR(mut) mut = 0 - -#endif -#endif //MUTEX_H diff --git a/inc/pthread_rw_mutex.h b/inc/pthread_rw_mutex.h index f2b7b0a0..d6f1c979 100644 --- a/inc/pthread_rw_mutex.h +++ b/inc/pthread_rw_mutex.h @@ -20,13 +20,9 @@ #define RW_MUTEX_T pthread_rwlock_t #define RW_MUTEX_CTOR(mut) ABORT_FAIL(0 == pthread_rwlock_init( & (mut), 0)) #define RW_MUTEX_LOCK_READ(mut) ABORT_FAIL(0 == pthread_rwlock_rdlock( & (mut))) - #define RW_MUTEX_UNLOCK_READ(mut) ABORT_FAIL(0 == pthread_rwlock_unlock( & (mut))) - #define RW_MUTEX_LOCK_WRITE(mut) ABORT_FAIL(0 == pthread_rwlock_wrlock( & (mut))) - #define RW_MUTEX_UNLOCK_WRITE(mut) ABORT_FAIL(0 == pthread_rwlock_unlock( & (mut))) - #define RW_MUTEX_DTOR(mut) ABORT_FAIL(0 == pthread_rwlock_destroy( & (mut))) diff --git a/inc/remote.h b/inc/remote.h index 1fa3baa8..f3bacc2d 100644 --- a/inc/remote.h +++ b/inc/remote.h @@ -6,6 +6,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -647,62 +648,6 @@ enum remote_mem_map_flags { /** Update REMOTE_MAP_MAX_FLAG when adding new value to this enum **/ }; -/** - * @enum fastrpc_map_flags for fastrpc_mmap and fastrpc_munmap - * @brief Types of maps with cache maintenance - */ -enum fastrpc_map_flags { - /** - * Map memory pages with RW- permission and CACHE WRITEBACK. - * Driver will clean cache when buffer passed in a FastRPC call. - * Same remote virtual address will be assigned for subsequent - * FastRPC calls. - */ - FASTRPC_MAP_STATIC, - - /** Reserved for compatibility with deprecated flag */ - FASTRPC_MAP_RESERVED, - - /** - * Map memory pages with RW- permission and CACHE WRITEBACK. - * Mapping tagged with a file descriptor. User is responsible for - * maintenance of CPU and DSP caches for the buffer. Get virtual address - * of buffer on DSP using HAP_mmap_get() and HAP_mmap_put() functions. - */ - FASTRPC_MAP_FD, - - /** - * Mapping delayed until user calls HAP_mmap() and HAP_munmap() - * functions on DSP. User is responsible for maintenance of CPU and DSP - * caches for the buffer. Delayed mapping is useful for users to map - * buffer on DSP with other than default permissions and cache modes - * using HAP_mmap() and HAP_munmap() functions. - */ - FASTRPC_MAP_FD_DELAYED, - - /** Reserved for compatibility **/ - FASTRPC_MAP_RESERVED_4, - FASTRPC_MAP_RESERVED_5, - FASTRPC_MAP_RESERVED_6, - FASTRPC_MAP_RESERVED_7, - FASTRPC_MAP_RESERVED_8, - FASTRPC_MAP_RESERVED_9, - FASTRPC_MAP_RESERVED_10, - FASTRPC_MAP_RESERVED_11, - FASTRPC_MAP_RESERVED_12, - FASTRPC_MAP_RESERVED_13, - FASTRPC_MAP_RESERVED_14, - FASTRPC_MAP_RESERVED_15, - - /** - * This flag is used to skip CPU mapping, - * otherwise behaves similar to FASTRPC_MAP_FD_DELAYED flag. - */ - FASTRPC_MAP_FD_NOMAP, - - /** Update FASTRPC_MAP_MAX when adding new value to this enum **/ -}; - /** * Attributes for remote_register_buf_attr **/ diff --git a/inc/remote64.h b/inc/remote64.h deleted file mode 100644 index ec08d2d2..00000000 --- a/inc/remote64.h +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef REMOTE64_H -#define REMOTE64_H - -#include "remote.h" - -/* -All the functions declared here are moved to remote.h, remote64.h will be deleted in future. -*/ -#endif // REMOTE64_H diff --git a/inc/shared.h b/inc/shared.h deleted file mode 100644 index a6b5f42f..00000000 --- a/inc/shared.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef SHARED_H -#define SHARED_H - -#if defined(__NIX) -// TODO these sections not supported? -//static __so_func *__autostart[] __attribute__((section (".CRT$XIU"))) = { (__so_func*)__so_ctor }; -//static __so_func *__autoexit[] __attribute__((section (".CRT$XPU"))) = { (__so_func*)__so_dtor }; - -#define SHARED_OBJECT_API_ENTRY(ctor, dtor) - -#elif defined(_WIN32) -#include - -typedef int __so_cb(void); -static __so_cb *__so_get_ctor(); -static __so_cb *__so_get_dtor(); - -typedef void __so_func(void); -static void __so_ctor() { - (void)(__so_get_ctor())(); -} - -static void __so_dtor() { - (void)(__so_get_dtor())(); -} - -#pragma data_seg(".CRT$XIU") - static __so_func *__autostart[] = { (__so_func*)__so_ctor }; -#pragma data_seg(".CRT$XPU") - static __so_func *__autoexit[] = { (__so_func*)__so_dtor }; -#pragma data_seg() - -#define SHARED_OBJECT_API_ENTRY(ctor, dtor)\ - static __so_cb *__so_get_ctor() { return (__so_cb*)ctor; }\ - static __so_cb *__so_get_dtor() { return (__so_cb*)dtor; } - -#else //better be gcc - -#define SHARED_OBJECT_API_ENTRY(ctor, dtor)\ -__attribute__((constructor)) \ -static void __ctor__##ctor(void) {\ - (void)ctor();\ -}\ -\ -__attribute__((destructor))\ -static void __dtor__##dtor(void) {\ - (void)dtor();\ -} - -#endif //ifdef _WIN32 - -#endif // SHARED_H diff --git a/inc/std_dtoa.h b/inc/std_dtoa.h deleted file mode 100644 index a514c0ff..00000000 --- a/inc/std_dtoa.h +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef STD_DTOA_H -#define STD_DTOA_H - -// -// Constant Definitions -// - -// For floating point numbers, the range of a double precision number is -// approximately +/- 10 ^ 308.25 as per the IEEE Standard 754. -// As such, the maximum size of the integer portion of the -// string is assumed to be 311 (309 + sign + \0). The maximum -// size of the fractional part is assumed to be 100. Thus, the -// maximum size of the string that would contain the number -// after conversion is safely assumed to be 420 (including any -// prefix, the null character and exponent specifiers 'e'). -// -// The buffers that contain the converted integer and the fraction parts of -// the float are safely assumed to be of size 310. -#define STD_DTOA_FORMAT_FLOAT_SIZE 420 -#define STD_DTOA_FORMAT_INTEGER_SIZE 311 -#define STD_DTOA_FORMAT_FRACTION_SIZE 100 - -// Constants for operations on the IEEE 754 representation of double -// precision floating point numbers. -#define STD_DTOA_DP_SIGN_SHIFT_COUNT 63 -#define STD_DTOA_DP_EXPONENT_SHIFT_COUNT 52 -#define STD_DTOA_DP_EXPONENT_MASK 0x7ff -#define STD_DTOA_DP_EXPONENT_BIAS 1023 -#define STD_DTOA_DP_MANTISSA_MASK ( ( (uint64_t)1 << 52 ) - 1 ) -#define STD_DTOA_DP_INFINITY_EXPONENT_ID 0x7FF -#define STD_DTOA_DP_MAX_EXPONENT 1023 -#define STD_DTOA_DP_MIN_EXPONENT_NORM -1022 -#define STD_DTOA_DP_MIN_EXPONENT_DENORM -1074 -#define STD_DTOA_DP_MAX_EXPONENT_DEC 308 -#define STD_DTOA_DP_MIN_EXPONENT_DEC_DENORM -323 - -#define STD_DTOA_PRECISION_ROUNDING_VALUE 4 -#define STD_DTOA_DEFAULT_FLOAT_PRECISION 6 - -#define STD_DTOA_NEGATIVE_INF_UPPER_CASE "-INF" -#define STD_DTOA_NEGATIVE_INF_LOWER_CASE "-inf" -#define STD_DTOA_POSITIVE_INF_UPPER_CASE "INF" -#define STD_DTOA_POSITIVE_INF_LOWER_CASE "inf" -#define STD_DTOA_NAN_UPPER_CASE "NAN" -#define STD_DTOA_NAN_LOWER_CASE "nan" -#define STD_DTOA_FP_POSITIVE_INF 0x7FF0000000000000uLL -#define STD_DTOA_FP_NEGATIVE_INF 0xFFF0000000000000uLL -#define STD_DTOA_FP_SNAN 0xFFF0000000000001uLL -#define STD_DTOA_FP_QNAN 0xFFFFFFFFFFFFFFFFuLL - -// -// Useful Macros -// - -#define MY_ISDIGIT(c) ( ( (c) >= '0' ) && ( (c) <= '9' ) ) -#define FP_EXPONENT(u) ( ( ( (u) >> STD_DTOA_DP_EXPONENT_SHIFT_COUNT ) \ - & STD_DTOA_DP_EXPONENT_MASK ) - STD_DTOA_DP_EXPONENT_BIAS ) -#define FP_EXPONENT_BIASED(u) ( ( (u) >> STD_DTOA_DP_EXPONENT_SHIFT_COUNT ) \ - & STD_DTOA_DP_EXPONENT_MASK ) -#define FP_MANTISSA_NORM(u) ( ( (u) & STD_DTOA_DP_MANTISSA_MASK ) | \ - ( (uint64_t)1 << STD_DTOA_DP_EXPONENT_SHIFT_COUNT ) ) -#define FP_MANTISSA_DENORM(u) ( (u) & STD_DTOA_DP_MANTISSA_MASK ) -#define FP_MANTISSA(u) ( FP_EXPONENT_BIASED(u) ? FP_MANTISSA_NORM(u) : \ - FP_MANTISSA_DENORM(u) ) -#define FP_SIGN(u) ( (u) >> STD_DTOA_DP_SIGN_SHIFT_COUNT ) - -// -// Type Definitions -// - -typedef enum -{ - FP_TYPE_UNKOWN = 0, - FP_TYPE_NEGATIVE_INF, - FP_TYPE_POSITIVE_INF, - FP_TYPE_NAN, - FP_TYPE_GENERAL, -} FloatingPointType; - -// -// Function Declarations -// - -#ifdef __cplusplus -extern "C" { -#endif // #ifdef __cplusplus - -double fp_pow_10( int nPow ); -double fp_round( double dNumber, int nPrecision ); -int fp_log_10( double dNumber ); -int fp_check_special_cases( double dNumber, FloatingPointType* pNumberType ); -int std_dtoa_decimal( double dNumber, int nPrecision, - char acIntegerPart[ STD_DTOA_FORMAT_INTEGER_SIZE ], - char acFractionPart[ STD_DTOA_FORMAT_FRACTION_SIZE ] ); -int std_dtoa_hex( double dNumber, int nPrecision, char cFormat, - char acIntegerPart[ STD_DTOA_FORMAT_INTEGER_SIZE ], - char acFractionPart[ STD_DTOA_FORMAT_FRACTION_SIZE ], - int* pnExponent ); - -#ifdef __cplusplus -} -#endif // #ifdef __cplusplus - -#endif // STD_DTOA_H - diff --git a/inc/version.h b/inc/version.h deleted file mode 100644 index 893d6c77..00000000 --- a/inc/version.h +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#ifndef VERSION_H -#define VERSION_H -/*=========================================================================== - -FILE: version.h - -GENERAL DESCRIPTION: - Definitions for versioning -===========================================================================*/ -#if !defined(VERSION_CL) -#define VERSION_CL "?" -#endif - -#if !defined(VERSION_PROD) -#define VERSION_PROD "unknown" -#endif - -#if !defined(VERSION_BRANCH) -#define VERSION_BRANCH "?" -#endif - -#if !defined(VERSION_NUM) -#define VERSION_NUM "?.?.?.?" -#endif - -#define VERSION_STRING \ - VERSION_PROD " " \ - VERSION_NUM " " \ - "(br=" VERSION_BRANCH "; cl=" VERSION_CL ")" - -/* -======================================================================= -MACROS DOCUMENTATION -======================================================================= - -VERSION_MAJOR - -Description: - Defines the major release number of the version. - -Comments: - It has to be a valid numerical value -======================================================================= - -VERSION_MINOR - -Description: - Defines the minor release number of the version. - -Comments: - It has to be a valid numerical value -======================================================================= - -VERSION_MAINT - -Description: - Defines the maintenance release of the version. - -Comments: - It has to be a valid numerical value -======================================================================= - -VERSION_BUILD - -Description: - Defines the build ID of the version. - -Comments: - It has to be a valid numerical value -======================================================================= - -VERSION_STRING - -Description: - Defines the version string that specifies the version number. - -Definition: - - #define VERSION_STRING "a.b.c.d (name=value;name=value;...)" - where a=major release number - b=minor release number - c=maintenance release number - d=build number - - name=value pair provides additional information about the build. - Example: - patch/feature=comma separated list of features/patches that have been installed. - br=p4 branch that was used for the build - cl=p4 change list number - machine=hostname of the machine that was used for the build. - -Comments: - -======================================================================= -*/ - -#endif // VERSION_H diff --git a/src/Makefile.am b/src/Makefile.am index 7c28c49a..aac8ed6e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,8 @@ +SUBDIRS = generated + lib_LTLIBRARIES = -LIBDSPRPC_CFLAGS = -fno-short-enums -U_DEBUG -DARM_ARCH_7A -DLE_ENABLE -DENABLE_UPSTREAM_DRIVER_INTERFACE -DUSE_SYSLOG -I$(top_srcdir)/inc +LIBDSPRPC_CFLAGS = -fno-short-enums -U_DEBUG -DARM_ARCH_7A -DLE_ENABLE -DENABLE_UPSTREAM_DRIVER_INTERFACE -DUSE_SYSLOG -I$(top_srcdir)/inc -I$(srcdir)/generated LIBDSPRPC_SOURCES = \ fastrpc_apps_user.c \ @@ -18,40 +20,39 @@ LIBDSPRPC_SOURCES = \ log_config.c \ dspsignal.c \ dspqueue/dspqueue_cpu.c \ - dspqueue/dspqueue_rpc_stub.c \ listener_android.c \ apps_std_imp.c \ apps_mem_imp.c \ - apps_mem_skel.c \ rpcmem_linux.c \ adspmsgd.c \ adspmsgd_printf.c \ std_path.c \ - std_dtoa.c \ BufBound.c \ platform_libs.c \ pl_list.c \ gpls.c \ - remotectl_stub.c \ - remotectl1_stub.c \ - adspmsgd_apps_skel.c \ - adspmsgd_adsp_stub.c \ - adspmsgd_adsp1_stub.c \ - apps_remotectl_skel.c \ - adsp_current_process_stub.c \ - adsp_current_process1_stub.c \ - adsp_listener_stub.c \ - adsp_listener1_stub.c \ - apps_std_skel.c \ - adsp_perf_stub.c \ - adsp_perf1_stub.c \ mod_table.c \ - fastrpc_context.c + fastrpc_context.c \ + generated/dspqueue_rpc_stub.c \ + generated/apps_mem_skel.c \ + generated/remotectl_stub.c \ + generated/remotectl1_stub.c \ + generated/adspmsgd_apps_skel.c \ + generated/adspmsgd_adsp_stub.c \ + generated/adspmsgd_adsp1_stub.c \ + generated/apps_remotectl_skel.c \ + generated/adsp_current_process_stub.c \ + generated/adsp_current_process1_stub.c \ + generated/adsp_listener_stub.c \ + generated/adsp_listener1_stub.c \ + generated/apps_std_skel.c \ + generated/adsp_perf_stub.c \ + generated/adsp_perf1_stub.c LIBDEFAULT_LISTENER_SOURCES = \ adsp_default_listener.c \ - adsp_default_listener_stub.c \ - adsp_default_listener1_stub.c + generated/adsp_default_listener_stub.c \ + generated/adsp_default_listener1_stub.c if ANDROID_CC USE_LOG = -llog @@ -98,10 +99,12 @@ libsdsp_default_listener_la_CFLAGS = $(SDSP_CFLAGS) -DUSE_SYSLOG GDSP_CFLAGS = $(LIBDSPRPC_CFLAGS) -DDEFAULT_DOMAIN_ID=5 +lib_LTLIBRARIES += libgdsprpc.la libgdsprpc_la_SOURCES = $(LIBDSPRPC_SOURCES) libgdsprpc_la_LDFLAGS = -ldl -lm $(USE_LOG) -version-number @LT_VERSION_NUMBER@ libgdsprpc_la_CFLAGS = $(GDSP_CFLAGS) +lib_LTLIBRARIES += libgdsp_default_listener.la libgdsp_default_listener_la_SOURCES = $(LIBDEFAULT_LISTENER_SOURCES) libgdsp_default_listener_la_DEPENDENCIES = libcdsprpc.la libgdsp_default_listener_la_LDFLAGS = libcdsprpc.la -shared -module $(USE_LOG) -version-number @LT_VERSION_NUMBER@ @@ -134,4 +137,4 @@ gdsprpcddir = $(libdir) gdsprpcd_SOURCES = dsprpcd.c gdsprpcd_DEPENDENCIES = libcdsp_default_listener.la gdsprpcd_CFLAGS = -I$(top_srcdir)/inc -DDEFAULT_DOMAIN_ID=5 -DUSE_SYSLOG -DUSE_GDSP -gdsprpcd_LDADD = -ldl $(USE_LOG) \ No newline at end of file +gdsprpcd_LDADD = -ldl $(USE_LOG) diff --git a/src/apps_mem_imp.c b/src/apps_mem_imp.c index f288d0a6..c843be96 100644 --- a/src/apps_mem_imp.c +++ b/src/apps_mem_imp.c @@ -14,7 +14,7 @@ #include "fastrpc_apps_user.h" #include "fastrpc_mem.h" #include "fastrpc_trace.h" -#include "remote64.h" +#include "remote.h" #include "rpcmem_internal.h" #include "verify.h" #include diff --git a/src/dspqueue/dspqueue_cpu.c b/src/dspqueue/dspqueue_cpu.c index 66092fa6..42d5af3e 100644 --- a/src/dspqueue/dspqueue_cpu.c +++ b/src/dspqueue/dspqueue_cpu.c @@ -21,7 +21,6 @@ #include "AEEQList.h" // Needed by fastrpc_mem.h #include "dspqueue.h" #include "dspqueue_rpc.h" -#include "dspqueue_shared.h" #include "dspsignal.h" #include "fastrpc_apps_user.h" #include "fastrpc_internal.h" @@ -36,9 +35,142 @@ #include #include #include +#include +#include #include #include +/* Shared memory queue definitions. + + Each queue is allocated as a single shared ION buffer. The buffer consists of: + * struct dspqueue_header + - request packet queue header. Used for messages from the host CPU to the DSP. + - response packet queue header. Used for messages from the DSP to the host CPU. + * read/write states for each packet queue, including read/write pointers. + Each read/write state structure must be on a separate cache line. + * Request and response packet queues + - Packet queues are circular buffers consisting packet headers and data + - Packets are padded to be 64-bit aligned + - The reader and writer manage read and write positions + - Packets do not wrap around at the end of the queue. If a packet cannot fit before the end + of the queue, the entire packet is written at the beginning. The 64-bit header is replicated. +*/ + + +/* Header structure for each one-way packet queue. + All offsets are in bytes to the beginning of the shared memory queue block. */ +struct dspqueue_packet_queue_header { + uint32_t queue_offset; /* Queue offset */ + uint32_t queue_length; /* Queue length in bytes */ + uint32_t read_state_offset; /* Read state offset. Contains struct dspqueue_packet_queue_state, + describing the state of the reader of this queue. */ + uint32_t write_state_offset; /* Write state offset. Contains a struct dspqueue_packet_queue_state, + describing the state of the writer of this queue. */ +}; + +/* State structure, used to describe the state of the reader or writer of each queue. + The state structure is at an offset from the start of the header as defined in + struct dspqueue_packet_queue_header above, and must fit in a single cache line. */ +struct dspqueue_packet_queue_state { + volatile uint32_t position; /* Position within the queue in bytes */ + volatile uint32_t packet_count; /* Number of packets read/written */ + volatile uint32_t wait_count; /* Non-zero if the reader/writer is waiting for a signal + for a new packet or more space in the queue respectively */ +}; + + +/* Userspace shared memory queue header */ +struct dspqueue_header { + uint32_t version; /* Initial version 1, 2 if any flags are set and need to be checked. */ + int32_t error; + uint32_t flags; + struct dspqueue_packet_queue_header req_queue; /* CPU to DSP */ + struct dspqueue_packet_queue_header resp_queue; /* DSP to CPU */ + uint32_t queue_count; +}; + +/* The version number currently expected if both CPU and DSP sides match */ +#define DSPQUEUE_HEADER_CURRENT_VERSION 2 + +/* Wait counts present in the packet queue header. Set by the CPU, DSP must + fail initialization if the feature is not supported. */ +#define DSPQUEUE_HEADER_FLAG_WAIT_COUNTS 1 + +/* Use driver signaling. Set by the CPU, DSP must fail initialization + if the feature is not supported. */ +#define DSPQUEUE_HEADER_FLAG_DRIVER_SIGNALING 2 + +/* Unexpected flags */ +#define DSPQUEUE_HEADER_UNEXPECTED_FLAGS ~(DSPQUEUE_HEADER_FLAG_WAIT_COUNTS | DSPQUEUE_HEADER_FLAG_DRIVER_SIGNALING) + + +/* Maximum queue size in bytes */ +#define DSPQUEUE_MAX_QUEUE_SIZE 16777216 + +/* Maximum number of buffers in a packet */ +#define DSPQUEUE_MAX_BUFFERS 64 + +/* Maximum message size */ +#define DSPQUEUE_MAX_MESSAGE_SIZE 65536 + +/* Default sizes */ +#define DSPQUEUE_DEFAULT_REQ_SIZE 65536 +#define DSPQUEUE_DEFAULT_RESP_SIZE 16384 + + +/* Maximum number of queues per process. Must ensure the state arrays get cache line aligned. + Update signal allocations in dspsignal.h if this changes. */ +#define DSPQUEUE_MAX_PROCESS_QUEUES 64 + + +/* Process queue information block, used with RPC-based signaling. + + Each participant increments the packet/space count for the + corresponding queue when there is a new packet or more space + available and signals the other party. The other party then goes + through active queues to see which one needs processing. + + This reduces the number of signals to two per process and lets us + use argumentless FastRPC calls for signaling. + */ +struct dspqueue_process_queue_state { + uint32_t req_packet_count[DSPQUEUE_MAX_PROCESS_QUEUES]; + uint32_t req_space_count[DSPQUEUE_MAX_PROCESS_QUEUES]; + uint32_t resp_packet_count[DSPQUEUE_MAX_PROCESS_QUEUES]; + uint32_t resp_space_count[DSPQUEUE_MAX_PROCESS_QUEUES]; +}; + +/* Info specific to multi-domain queues */ +struct dspqueue_multidomain { + /* Flag to indicate if queue is multidomain */ + bool is_mdq; + + /* Multi-domain context id associated with queue */ + uint64_t ctx; + + /* Number of domains on which queue was created */ + unsigned int num_domain_ids; + + /* Effective domain ids on which queue was created */ + unsigned int *effec_domain_ids; + + /* Array of queue handles - one for each domain */ + dspqueue_t *queues; + + /* Array of queue ids - one for each domain */ + uint64_t *dsp_ids; +}; + +/* Signals IDs used with driver signaling. Update the signal allocations in dspsignal.h + if this changes. */ +enum dspqueue_signal { + DSPQUEUE_SIGNAL_REQ_PACKET = 0, + DSPQUEUE_SIGNAL_REQ_SPACE, + DSPQUEUE_SIGNAL_RESP_PACKET, + DSPQUEUE_SIGNAL_RESP_SPACE, + DSPQUEUE_NUM_SIGNALS +}; + struct dspqueue { unsigned id; int domain; diff --git a/src/fastrpc_apps_user.c b/src/fastrpc_apps_user.c index 6de574a5..c24def31 100644 --- a/src/fastrpc_apps_user.c +++ b/src/fastrpc_apps_user.c @@ -70,7 +70,6 @@ #include "remotectl.h" #include "remotectl1.h" #include "rpcmem_internal.h" -#include "shared.h" #include "verify.h" #include "fastrpc_context.h" #include "fastrpc_process_attributes.h" @@ -150,14 +149,7 @@ inline static void deinit_fastrpc_dsp_lib_refcnt(void) { } } -enum fastrpc_proc_attr { - FASTRPC_MODE_DEBUG = 0x1, - FASTRPC_MODE_PTRACE = 0x2, - FASTRPC_MODE_CRC = 0x4, - FASTRPC_MODE_UNSIGNED_MODULE = 0x8, - FASTRPC_MODE_ADAPTIVE_QOS = 0x10, - FASTRPC_MODE_SYSTEM_PROCESS = 0x20, - FASTRPC_MODE_PRIVILEGED = 0x40, // this attribute will be populated in kernel +enum fastrpc_proc_attr_local { // Attribute to enable pd dump feature for both signed/unsigned pd FASTRPC_MODE_ENABLE_PDDUMP = 0x80, // System attribute to enable pd dump debug data collection on rooted devices @@ -1357,7 +1349,7 @@ int remote_handle_invoke_domain(int domain, remote_handle handle, wake_lock = 0; } // Macros are initializing and destroying pfds and pattrs. - nErr = ioctl_invoke(dev, req, handle, sc, get_args(), pfds, pattrs, job, + nErr = ioctl_invoke(dev, req, handle, sc, args, pfds, pattrs, job, crc_remote, perf_kernel, perf_dsp); if (nErr) { nErr = convert_kernel_to_user_error(nErr, errno); diff --git a/src/fastrpc_ioctl.c b/src/fastrpc_ioctl.c index e0329e13..930f7c87 100644 --- a/src/fastrpc_ioctl.c +++ b/src/fastrpc_ioctl.c @@ -56,8 +56,8 @@ const char *get_secure_domain_name(int domain_id) { int ioctl_init(int dev, uint32_t flags, int attr, unsigned char *shell, int shelllen, int shellfd, char *mem, int memlen, int memfd, int tessiglen) { int ioErr = 0; - struct fastrpc_ioctl_init_create init = {0}; - struct fastrpc_ioctl_init_create_static init_static = {0}; + struct fastrpc_init_create init = {0}; + struct fastrpc_init_create_static init_static = {0}; switch (flags) { case FASTRPC_INIT_ATTACH: @@ -94,7 +94,7 @@ int ioctl_invoke(int dev, int req, remote_handle handle, uint32_t sc, void *pra, int *fds, unsigned int *attrs, void *job, unsigned int *crc, uint64_t *perf_kernel, uint64_t *perf_dsp) { int ioErr = AEE_SUCCESS; - struct fastrpc_ioctl_invoke invoke = {0}; + struct fastrpc_invoke invoke = {0}; invoke.handle = handle; invoke.sc = sc; @@ -123,7 +123,7 @@ int ioctl_mmap(int dev, int req, uint32_t flags, int attr, int fd, int offset, switch (req) { case MEM_MAP: { - struct fastrpc_ioctl_mem_map map = {0}; + struct fastrpc_mem_map map = {0}; map.version = 0; map.fd = fd; map.offset = offset; @@ -136,7 +136,7 @@ int ioctl_mmap(int dev, int req, uint32_t flags, int attr, int fd, int offset, } break; case MMAP: case MMAP_64: { - struct fastrpc_ioctl_req_mmap map = {0}; + struct fastrpc_req_mmap map = {0}; map.fd = fd; map.flags = flags; map.vaddrin = (uint64_t)vaddrin; @@ -159,7 +159,7 @@ int ioctl_munmap(int dev, int req, int attr, void *buf, int fd, int len, switch (req) { case MEM_UNMAP: case MUNMAP_FD: { - struct fastrpc_ioctl_mem_unmap unmap = {0}; + struct fastrpc_mem_unmap unmap = {0}; unmap.version = 0; unmap.fd = fd; unmap.vaddr = vaddr; @@ -168,7 +168,7 @@ int ioctl_munmap(int dev, int req, int attr, void *buf, int fd, int len, } break; case MUNMAP: case MUNMAP_64: { - struct fastrpc_ioctl_req_munmap unmap = {0}; + struct fastrpc_req_munmap unmap = {0}; unmap.vaddrout = vaddr; unmap.size = (ssize_t)len; ioErr = ioctl(dev, FASTRPC_IOCTL_MUNMAP, (unsigned long)&unmap); @@ -256,4 +256,4 @@ int ioctl_mdctx_manage(int dev, int req, void *user_ctx, { // TODO: Implement this for opensource return AEE_EUNSUPPORTED; -} \ No newline at end of file +} diff --git a/src/fastrpc_mem.c b/src/fastrpc_mem.c index 8f62fc25..9a467795 100644 --- a/src/fastrpc_mem.c +++ b/src/fastrpc_mem.c @@ -38,7 +38,6 @@ #include "fastrpc_internal.h" #include "fastrpc_mem.h" #include "rpcmem.h" -#include "shared.h" #include "verify.h" #ifdef LE_ENABLE diff --git a/src/fastrpc_notif.c b/src/fastrpc_notif.c index be4bde6a..acd5d2d3 100644 --- a/src/fastrpc_notif.c +++ b/src/fastrpc_notif.c @@ -52,10 +52,12 @@ static pthread_mutex_t update_notif_list_mut; /* List of all clients who registered for process status notification */ static struct other_handle_list notif_list; -void fastrpc_cleanup_notif_list(); +static void fastrpc_cleanup_notif_list(); DECLARE_HASH_TABLE(fastrpc_notif, notif_config); +static int get_remote_notif_response(int domain); + static void *notif_fastrpc_thread(void *arg) { notif_config *me = (notif_config *)arg; int nErr = AEE_SUCCESS, domain = me->domain; @@ -201,7 +203,7 @@ static int fastrpc_notify_status(int domain, int session, int status) { return nErr; } -void fastrpc_cleanup_notif_list() { +static void fastrpc_cleanup_notif_list() { QNode *pn = NULL, *pnn = NULL; struct fastrpc_notif *lnotif = NULL; @@ -219,7 +221,7 @@ void fastrpc_cleanup_notif_list() { } /* Function to wait in kernel for an update in remote process status */ -int get_remote_notif_response(int domain) { +static int get_remote_notif_response(int domain) { int nErr = AEE_SUCCESS, dev; int dom = -1, session = -1, status = -1; diff --git a/src/generated/Makefile.am b/src/generated/Makefile.am new file mode 100644 index 00000000..7cb85f15 --- /dev/null +++ b/src/generated/Makefile.am @@ -0,0 +1,18 @@ +noinst_HEADERS = \ + adsp_current_process.h \ + adsp_current_process1.h \ + adsp_default_listener.h \ + adsp_default_listener1.h \ + adsp_listener.h \ + adsp_listener1.h \ + adsp_perf.h \ + adsp_perf1.h \ + adspmsgd_adsp.h \ + adspmsgd_adsp1.h \ + adspmsgd_apps.h \ + apps_mem.h \ + apps_remotectl.h \ + apps_std.h \ + dspqueue_rpc.h \ + remotectl.h \ + remotectl1.h diff --git a/inc/adsp_current_process.h b/src/generated/adsp_current_process.h similarity index 100% rename from inc/adsp_current_process.h rename to src/generated/adsp_current_process.h diff --git a/inc/adsp_current_process1.h b/src/generated/adsp_current_process1.h similarity index 100% rename from inc/adsp_current_process1.h rename to src/generated/adsp_current_process1.h diff --git a/src/adsp_current_process1_stub.c b/src/generated/adsp_current_process1_stub.c similarity index 100% rename from src/adsp_current_process1_stub.c rename to src/generated/adsp_current_process1_stub.c diff --git a/src/adsp_current_process_stub.c b/src/generated/adsp_current_process_stub.c similarity index 100% rename from src/adsp_current_process_stub.c rename to src/generated/adsp_current_process_stub.c diff --git a/inc/adsp_default_listener.h b/src/generated/adsp_default_listener.h similarity index 100% rename from inc/adsp_default_listener.h rename to src/generated/adsp_default_listener.h diff --git a/inc/adsp_default_listener1.h b/src/generated/adsp_default_listener1.h similarity index 100% rename from inc/adsp_default_listener1.h rename to src/generated/adsp_default_listener1.h diff --git a/src/adsp_default_listener1_stub.c b/src/generated/adsp_default_listener1_stub.c similarity index 100% rename from src/adsp_default_listener1_stub.c rename to src/generated/adsp_default_listener1_stub.c diff --git a/src/adsp_default_listener_stub.c b/src/generated/adsp_default_listener_stub.c similarity index 100% rename from src/adsp_default_listener_stub.c rename to src/generated/adsp_default_listener_stub.c diff --git a/inc/adsp_listener.h b/src/generated/adsp_listener.h similarity index 100% rename from inc/adsp_listener.h rename to src/generated/adsp_listener.h diff --git a/inc/adsp_listener1.h b/src/generated/adsp_listener1.h similarity index 100% rename from inc/adsp_listener1.h rename to src/generated/adsp_listener1.h diff --git a/src/adsp_listener1_stub.c b/src/generated/adsp_listener1_stub.c similarity index 100% rename from src/adsp_listener1_stub.c rename to src/generated/adsp_listener1_stub.c diff --git a/src/adsp_listener_stub.c b/src/generated/adsp_listener_stub.c similarity index 100% rename from src/adsp_listener_stub.c rename to src/generated/adsp_listener_stub.c diff --git a/inc/adsp_perf.h b/src/generated/adsp_perf.h similarity index 100% rename from inc/adsp_perf.h rename to src/generated/adsp_perf.h diff --git a/inc/adsp_perf1.h b/src/generated/adsp_perf1.h similarity index 100% rename from inc/adsp_perf1.h rename to src/generated/adsp_perf1.h diff --git a/src/adsp_perf1_stub.c b/src/generated/adsp_perf1_stub.c similarity index 100% rename from src/adsp_perf1_stub.c rename to src/generated/adsp_perf1_stub.c diff --git a/src/adsp_perf_stub.c b/src/generated/adsp_perf_stub.c similarity index 100% rename from src/adsp_perf_stub.c rename to src/generated/adsp_perf_stub.c diff --git a/inc/adspmsgd_adsp.h b/src/generated/adspmsgd_adsp.h similarity index 100% rename from inc/adspmsgd_adsp.h rename to src/generated/adspmsgd_adsp.h diff --git a/inc/adspmsgd_adsp1.h b/src/generated/adspmsgd_adsp1.h similarity index 100% rename from inc/adspmsgd_adsp1.h rename to src/generated/adspmsgd_adsp1.h diff --git a/src/adspmsgd_adsp1_stub.c b/src/generated/adspmsgd_adsp1_stub.c similarity index 100% rename from src/adspmsgd_adsp1_stub.c rename to src/generated/adspmsgd_adsp1_stub.c diff --git a/src/adspmsgd_adsp_stub.c b/src/generated/adspmsgd_adsp_stub.c similarity index 100% rename from src/adspmsgd_adsp_stub.c rename to src/generated/adspmsgd_adsp_stub.c diff --git a/inc/adspmsgd_apps.h b/src/generated/adspmsgd_apps.h similarity index 100% rename from inc/adspmsgd_apps.h rename to src/generated/adspmsgd_apps.h diff --git a/src/adspmsgd_apps_skel.c b/src/generated/adspmsgd_apps_skel.c similarity index 100% rename from src/adspmsgd_apps_skel.c rename to src/generated/adspmsgd_apps_skel.c diff --git a/inc/apps_mem.h b/src/generated/apps_mem.h similarity index 100% rename from inc/apps_mem.h rename to src/generated/apps_mem.h diff --git a/src/apps_mem_skel.c b/src/generated/apps_mem_skel.c similarity index 100% rename from src/apps_mem_skel.c rename to src/generated/apps_mem_skel.c diff --git a/inc/apps_remotectl.h b/src/generated/apps_remotectl.h similarity index 100% rename from inc/apps_remotectl.h rename to src/generated/apps_remotectl.h diff --git a/src/apps_remotectl_skel.c b/src/generated/apps_remotectl_skel.c similarity index 100% rename from src/apps_remotectl_skel.c rename to src/generated/apps_remotectl_skel.c diff --git a/inc/apps_std.h b/src/generated/apps_std.h similarity index 100% rename from inc/apps_std.h rename to src/generated/apps_std.h diff --git a/src/apps_std_skel.c b/src/generated/apps_std_skel.c similarity index 100% rename from src/apps_std_skel.c rename to src/generated/apps_std_skel.c diff --git a/inc/dspqueue_rpc.h b/src/generated/dspqueue_rpc.h similarity index 100% rename from inc/dspqueue_rpc.h rename to src/generated/dspqueue_rpc.h diff --git a/src/dspqueue/dspqueue_rpc_stub.c b/src/generated/dspqueue_rpc_stub.c similarity index 100% rename from src/dspqueue/dspqueue_rpc_stub.c rename to src/generated/dspqueue_rpc_stub.c diff --git a/inc/remotectl.h b/src/generated/remotectl.h similarity index 100% rename from inc/remotectl.h rename to src/generated/remotectl.h diff --git a/inc/remotectl1.h b/src/generated/remotectl1.h similarity index 100% rename from inc/remotectl1.h rename to src/generated/remotectl1.h diff --git a/src/remotectl1_stub.c b/src/generated/remotectl1_stub.c similarity index 100% rename from src/remotectl1_stub.c rename to src/generated/remotectl1_stub.c diff --git a/src/remotectl_stub.c b/src/generated/remotectl_stub.c similarity index 100% rename from src/remotectl_stub.c rename to src/generated/remotectl_stub.c diff --git a/src/gpls.c b/src/gpls.c index 0d69ef59..7928d309 100644 --- a/src/gpls.c +++ b/src/gpls.c @@ -6,10 +6,8 @@ #include "adsp_pls.h" #include "platform_libs.h" #include "pls.h" -#include "version.h" static struct pls_table gpls; -const char pls_version[] = VERSION_STRING; int gpls_init(void) { pls_ctor(&gpls, 1); return 0; diff --git a/src/listener_android.c b/src/listener_android.c index 712945ce..54116bcc 100644 --- a/src/listener_android.c +++ b/src/listener_android.c @@ -30,7 +30,6 @@ #include "mod_table.h" #include "platform_libs.h" #include "rpcmem.h" -#include "shared.h" #include "verify.h" #include "fastrpc_hash_table.h" diff --git a/src/mod_table.c b/src/mod_table.c index d19fa908..6c6cb7be 100644 --- a/src/mod_table.c +++ b/src/mod_table.c @@ -16,9 +16,9 @@ #include "HAP_farf.h" #include "HAP_pls.h" #include "fastrpc_trace.h" -#include "mutex.h" +#include "pthread_rw_mutex.h" #include "platform_libs.h" -#include "remote64.h" +#include "remote.h" #include "sbuf_parser.h" #include "uthash.h" #include "verify.h" diff --git a/src/rpcmem_linux.c b/src/rpcmem_linux.c index a0814b97..067fedf3 100644 --- a/src/rpcmem_linux.c +++ b/src/rpcmem_linux.c @@ -82,12 +82,6 @@ struct rpc_info { int dma; }; -struct fastrpc_alloc_dma_buf { - int fd; /* fd */ - uint32_t flags; /* flags to map with */ - uint64_t size; /* size */ -}; - void rpcmem_init() { QList_Ctor(&rpclst); pthread_mutex_init(&rpcmt, 0); @@ -175,7 +169,7 @@ void *rpcmem_alloc_internal(int heapid, uint32_t flags, size_t size) { } fd = dmabuf.fd; } else { - struct fastrpc_ioctl_alloc_dma_buf buf; + struct fastrpc_alloc_dma_buf buf; buf.size = size + PAGE_SIZE; buf.fd = -1; diff --git a/src/std_dtoa.c b/src/std_dtoa.c deleted file mode 100644 index d2dfb8a4..00000000 --- a/src/std_dtoa.c +++ /dev/null @@ -1,495 +0,0 @@ -// Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -#include "AEEStdDef.h" -#include "AEEstd.h" -#include "AEEStdErr.h" -#include "std_dtoa.h" -#include "math.h" - -// -// Useful Macros -// -#define FAILED(b) ( (b) != AEE_SUCCESS ? true : false ) -#define CLEANUP_ON_ERROR(b,l) if( FAILED( b ) ) { goto l; } -#define FP_POW_10(n) fp_pow_10(n) - -static __inline -uint32_t std_dtoa_clz32( uint32_t ulVal ) -// -// This function returns the number of leading zeroes in a uint32_t. -// This is a naive implementation that uses binary search. This could be -// replaced by an optimized inline assembly code. -// -{ - if( (int)ulVal <= 0 ) - { - return ( ulVal == 0 ) ? 32 : 0; - } - else - { - uint32_t uRet = 28; - uint32_t uTmp = 0; - uTmp = ( ulVal > 0xFFFF ) * 16; ulVal >>= uTmp, uRet -= uTmp; - uTmp = ( ulVal > 0xFF ) * 8; ulVal >>= uTmp, uRet -= uTmp; - uTmp = ( ulVal > 0xF ) * 4; ulVal >>= uTmp, uRet -= uTmp; - return uRet + ( ( 0x55AF >> ( ulVal * 2 ) ) & 3 ); - } -} - -static __inline -uint32_t std_dtoa_clz64( uint64_t ulVal ) -// -// This function returns the number of leading zeroes in a uint64_t. -// -{ - uint32_t ulCount = 0; - - if( !( ulVal >> 32 ) ) - { - ulCount += 32; - } - else - { - ulVal >>= 32; - } - - return ulCount + std_dtoa_clz32( (uint32_t)ulVal ); -} - -double fp_pow_10( int nPow ) -{ - double dRet = 1.0; - int nI = 0; - bool bNegative = false; - double aTablePos[] = { 0, 1e1, 1e2, 1e4, 1e8, 1e16, 1e32, 1e64, 1e128, - 1e256 }; - double aTableNeg[] = { 0, 1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32, 1e-64, 1e-128, - 1e-256 }; - double* pTable = aTablePos; - int nTableSize = STD_ARRAY_SIZE( aTablePos ); - - if( 0 == nPow ) - { - return 1.0; - } - - if( nPow < 0 ) - { - bNegative = true; - nPow = -nPow; - pTable = aTableNeg; - nTableSize = STD_ARRAY_SIZE( aTableNeg ); - } - - for( nI = 1; nPow && (nI < nTableSize); nI++ ) - { - if( nPow & 1 ) - { - dRet *= pTable[nI]; - } - - nPow >>= 1; - } - - if( nPow ) - { - // Overflow. Trying to compute a large power value. - union { - uint64_t ul; - double d; - } val; - val.ul = STD_DTOA_FP_POSITIVE_INF; - dRet = bNegative ? 0 : val.d; - } - - return dRet; -} - -double fp_round( double dNumber, int nPrecision ) -// -// This functions rounds dNumber to the specified precision nPrecision. -// For example: -// fp_round(2.34553, 3) = 2.346 -// fp_round(2.34553, 4) = 2.3455 -// -{ - double dResult = dNumber; - double dRoundingFactor = FP_POW_10( -nPrecision ) * 0.5; - - if( dNumber < 0 ) - { - dResult = dNumber - dRoundingFactor; - } - else - { - dResult = dNumber + dRoundingFactor; - } - - return dResult; -} - -int fp_log_10( double dNumber ) -// -// This function finds the integer part of the log_10( dNumber ). -// The function assumes that dNumber != 0. -// -{ - // Absorb the negative sign - if( dNumber < 0 ) - { - dNumber = -dNumber; - } - - return (int)( floor( log10( dNumber ) ) ); -} - -int fp_check_special_cases( double dNumber, FloatingPointType* pNumberType ) -// -// This function evaluates the input floating-point number dNumber to check for -// following special cases: NaN, +/-Infinity. -// The evaluation is based on the IEEE Standard 754 for Floating Point Numbers -// -{ - int nError = AEE_SUCCESS; - FloatingPointType NumberType = FP_TYPE_UNKOWN; - uint64_t ullValue = 0; - uint64_t ullSign = 0; - int64_t n64Exponent = 0; - uint64_t ullMantissa = 0; - - union { - uint64_t ul; - double d; - } val; - - val.d = dNumber; - ullValue = val.ul; - - // Extract the sign, exponent and mantissa - ullSign = FP_SIGN( ullValue ); - n64Exponent = FP_EXPONENT_BIASED( ullValue ); - ullMantissa = FP_MANTISSA_DENORM( ullValue ); - - // - // Rules for special cases are listed below: - // For Infinity, the following needs to be true: - // 1. Exponent should have all bits set to 1. - // 2. Mantissa should have all bits set to 0. - // - // For NaN, the following needs to be true: - // 1. Exponent should have all bits set to 1. - // 2. Mantissa should be non-zero. - // Note that we do not differentiate between QNaNs and SNaNs. - // - if( STD_DTOA_DP_INFINITY_EXPONENT_ID == n64Exponent ) - { - if( 0 == ullMantissa ) - { - // Inifinity. - if( ullSign ) - { - NumberType = FP_TYPE_NEGATIVE_INF; - } - else - { - NumberType = FP_TYPE_POSITIVE_INF; - } - } - else - { - // NaN - NumberType = FP_TYPE_NAN; - } - } - else - { - // A normal number - NumberType = FP_TYPE_GENERAL; - } - - // Set the output value - *pNumberType = NumberType; - - return nError; -} - -int std_dtoa_decimal( double dNumber, int nPrecision, - char acIntegerPart[ STD_DTOA_FORMAT_INTEGER_SIZE ], - char acFractionPart[ STD_DTOA_FORMAT_FRACTION_SIZE ] ) -{ - int nError = AEE_SUCCESS; - bool bNegativeNumber = false; - double dIntegerPart = 0.0; - double dFractionPart = 0.0; - double dTempIp = 0.0; - double dTempFp = 0.0; - int nMaxIntDigs = STD_DTOA_FORMAT_INTEGER_SIZE; - uint32_t ulI = 0; - int nIntStartPos = 0; - - // Optimization: Special case an input of 0 - if( 0.0 == dNumber ) - { - acIntegerPart[0] = '0'; - acIntegerPart[1] = '\0'; - - for( ulI = 0; (ulI < STD_DTOA_FORMAT_FRACTION_SIZE - 1) && (nPrecision > 0); - ulI++, nPrecision-- ) - { - acFractionPart[ulI] = '0'; - } - acFractionPart[ ulI ] = '\0'; - - goto bail; - } - - // Absorb the negative sign - if( dNumber < 0 ) - { - acIntegerPart[0] = '-'; - nIntStartPos = 1; - dNumber = -dNumber; - bNegativeNumber = true; - } - - // Split the input number into it's integer and fraction parts - dFractionPart = modf( dNumber, &dIntegerPart ); - - // First up, convert the integer part - if( 0.0 == dIntegerPart ) - { - acIntegerPart[ nIntStartPos ] = '0'; - } - else - { - double dRoundingConst = FP_POW_10( -STD_DTOA_PRECISION_ROUNDING_VALUE ); - int nIntDigs = 0; - int nI = 0; - - // Compute the number of digits in the integer part of the number - nIntDigs = fp_log_10( dIntegerPart ) + 1; - - // For negative numbers, a '-' sign has already been written. - if( true == bNegativeNumber ) - { - nIntDigs++; - } - - // Check for overflow - if( nIntDigs >= nMaxIntDigs ) - { - // Overflow! - // Note that currently, we return a simple AEE_EFAILED for all - // errors. - nError = AEE_EFAILED; - goto bail; - } - - // Null Terminate the string - acIntegerPart[ nIntDigs ] = '\0'; - - for( nI = nIntDigs - 1; nI >= nIntStartPos; nI-- ) - { - dIntegerPart = dIntegerPart / 10.0; - dTempFp = modf( dIntegerPart, &dTempIp ); - - // Round it to the a specific precision - dTempFp = dTempFp + dRoundingConst; - - // Convert the digit to a character - acIntegerPart[ nI ] = (int)( dTempFp * 10 ) + '0'; - if( !MY_ISDIGIT( acIntegerPart[ nI ] ) ) - { - // Overflow! - // Note that currently, we return a simple AEE_EFAILED for all - // errors. - nError = AEE_EFAILED; - goto bail; - } - dIntegerPart = dTempIp; - } - } - - // Just a double check for integrity sake. This should ideally never happen. - // Out of bounds scenario. That is, the integer part of the input number is - // too large. - if( dIntegerPart != 0.0 ) - { - // Note that currently, we return a simple AEE_EFAILED for all - // errors. - nError = AEE_EFAILED; - goto bail; - } - - // Now, convert the fraction part - for( ulI = 0; ( nPrecision > 0 ) && ( ulI < STD_DTOA_FORMAT_FRACTION_SIZE - 1 ); - nPrecision--, ulI++ ) - { - if( 0.0 == dFractionPart ) - { - acFractionPart[ ulI ] = '0'; - } - else - { - double dRoundingValue = FP_POW_10( -( nPrecision + - STD_DTOA_PRECISION_ROUNDING_VALUE ) ); - acFractionPart[ ulI ] = (int)( ( dFractionPart + dRoundingValue ) * 10.0 ) + '0'; - if( !MY_ISDIGIT( acFractionPart[ ulI ] ) ) - { - // Overflow! - // Note that currently, we return a simple AEE_EFAILED for all - // errors. - nError = AEE_EFAILED; - goto bail; - } - - dFractionPart = ( dFractionPart * 10.0 ) - - (int)( ( dFractionPart + FP_POW_10( -nPrecision - 6 ) ) * 10.0 ); - } - } - - -bail: - - return nError; -} - -int std_dtoa_hex( double dNumber, int nPrecision, char cFormat, - char acIntegerPart[ STD_DTOA_FORMAT_INTEGER_SIZE ], - char acFractionPart[ STD_DTOA_FORMAT_FRACTION_SIZE ], - int* pnExponent ) -{ - int nError = AEE_SUCCESS; - uint64_t ullMantissa = 0; - uint64_t ullSign = 0; - int64_t n64Exponent = 0; - static const char HexDigitsU[] = "0123456789ABCDEF"; - static const char HexDigitsL[] = "0123456789abcde"; - bool bFirstDigit = true; - int nI = 0; - int nF = 0; - union { - uint64_t ul; - double d; - } val; - - val.d = dNumber; - uint64_t ullValue = val.ul; - - int nManShift = 0; - const char *pcDigitArray = ( cFormat == 'A' ) ? HexDigitsU : HexDigitsL; - bool bPrecisionSpecified = true; - - // If no precision is specified, then set the precision to be fairly - // large. - if( nPrecision < 0 ) - { - nPrecision = STD_DTOA_FORMAT_FRACTION_SIZE; - bPrecisionSpecified = false; - } - else - { - bPrecisionSpecified = true; - } - - // Extract the sign, exponent and mantissa - ullSign = FP_SIGN( ullValue ); - n64Exponent = FP_EXPONENT( ullValue ); - ullMantissa = FP_MANTISSA( ullValue ); - - // Write out the sign - if( ullSign ) - { - acIntegerPart[ nI++ ] = '-'; - } - - // Optimization: Special case an input of 0 - if( 0.0 == dNumber ) - { - acIntegerPart[0] = '0'; - acIntegerPart[1] = '\0'; - - for( nF = 0; (nF < STD_DTOA_FORMAT_FRACTION_SIZE - 1) && (nPrecision > 0); - nF++, nPrecision-- ) - { - acFractionPart[nF] = '0'; - } - acFractionPart[nF] = '\0'; - - goto bail; - } - - // The mantissa is in lower 53 bits (52 bits + an implicit 1). - // If we are dealing with a denormalized number, then the implicit 1 - // is absent. The above macros would have then set that bit to 0. - // Shift the mantisaa on to the highest bits. - - if( 0 == ( n64Exponent + STD_DTOA_DP_EXPONENT_BIAS ) ) - { - // DENORMALIZED NUMBER. - // A denormalized number is of the form: - // 0.bbb...bbb x 2^Exponent - // Shift the mantissa to the higher bits while discarding the leading 0 - ullMantissa <<= 12; - - // Lets update the exponent so as to make sure that the first hex value - // in the mantissa is non-zero, i.e., at least one of the first 4 bits is - // non-zero. - nManShift = std_dtoa_clz64( ullMantissa ) - 3; - if( nManShift > 0 ) - { - ullMantissa <<= nManShift; - n64Exponent -= nManShift; - } - } - else - { - // NORMALIZED NUMBER. - // A normalized number has the following form: - // 1.bbb...bbb x 2^Exponent - // Shift the mantissa to the higher bits while retaining the leading 1 - ullMantissa <<= 11; - } - - // Now, lets get the decimal point out of the picture by shifting the - // exponent by 1. - n64Exponent++; - - // Read the mantissa four bits at a time to form the hex output - for( nI = 0, nF = 0, bFirstDigit = true; ullMantissa != 0; - ullMantissa <<= 4 ) - { - uint64_t ulHexVal = ullMantissa & 0xF000000000000000uLL; - ulHexVal >>= 60; - if( bFirstDigit ) - { - // Write to the integral part of the number - acIntegerPart[ nI++ ] = pcDigitArray[ulHexVal]; - bFirstDigit = false; - } - else if( nF < nPrecision ) - { - // Write to the fractional part of the number - acFractionPart[ nF++ ] = pcDigitArray[ulHexVal]; - } - } - - // Pad the fraction with trailing zeroes upto the specified precision - for( ; bPrecisionSpecified && (nF < nPrecision); nF++ ) - { - acFractionPart[ nF ] = '0'; - } - - // Now the output is of the form; - // h.hhh x 2^Exponent - // where h is a non-zero hexadecimal number. - // But we were dealing with a binary fraction 0.bbb...bbb x 2^Exponent. - // Therefore, we need to subtract 4 from the exponent (since the shift - // was to the base 16 and the exponent is to the base 2). - n64Exponent -= 4; - *pnExponent = (int)n64Exponent; - -bail: - return nError; -}