1 POSIX Compliancy Wrapper for Azure RTOS ThreadX 2 3 4 51.0 POSIX Compliancy Wrapper Overview 6 7The POSIX Compliancy Wrapper supports many of the basic POSIX calls, with 8some limitations, and utilizes ThreadX� primitives underneath. This POSIX 9compatibility layer should have good performance since it utilizes internal 10ThreadX primitives and bypasses basic ThreadX error checking. 11 12 131.1 POSIX Compliancy Wrapper Source 14 15The Wrapper source code is designed for simplicity and is comprised of separate source 16files for most functions. Including the supplied pthread.h file will import 17all the necessary POSIX constants and subroutine prototypes. 18 19 201.2 POSIX Compliancy Wrapper Documentation 21 22This document itself serves as a POSIX Compliancy Wrapper User Guide by 23providing an overview of the porting process, including various caveats and 24pitfalls to watch out for. In addition, each covered POSIX call is documented, 25including information about supported/unsupported options, limitations, deviations, 26and suggestions on how to work-around any limitations. 27 28 292.0 Installation 30 31The POSIX Compliancy Wrapper is easily installed by adding the 32the posix library to your current application build. Make sure your application build 33references the same header files as the ones the posix library has been built with. 34The file pthread.h must be included in your application source where POSIX 35calls are required. 36Since the POSIX compliancy wrapper does not cover the complete standard, not all prototypes 37are provided. Most notably is the header file tx_px_time.h. 38 392.1 Initialization 40 41The POSIX Compliancy Wrapper requires that a special initialization function is called 42prior to accessing any POSIX calls. The function to call and its prototype is: 43 44VOID *posix_initialize(VOID * posix_memory); 45 46This function is usually called from the application specific ThreadX 47initialization routine, tx_application_define(). The memory pointer supplied 48to posix_initialize must be a contiguouis reserved section of memory 49that has at least the following number of bytes: 50 51 52 POSIX_SYSTEM_STACK_SIZE + 53 TX_REGION0_SIZE_IN_BYTES + /* Region0 size */ 54 (WORK_QUEUE_DEPTH * WORK_REQ_SIZE) + /* system queue size */ 55 POSIX_HEAP_SIZE_IN_BYTES 56 57 58These equates are defined in tx_posix.h. The following additional equates 59define the number of POSIX objects supported by the POSIX Wrapper (default 60value is shown): 61 62 SEM_NSEMS_MAX 100 /* simultaneous POSIX semaphores */ 63 64 SEM_NAME_MAX 10 /* maximum length of name of semaphore */ 65 66 SEM_VALUE_MAX 100 /* max value of semaphore while initialization */ 67 68 POSIX_MAX_QUEUES 32 /* maximum number of simultaneous POSIX 69 message queues supported */ 70 71 PATH_MAX 10 /* maximum length of name of a message queue */ 72 73 PTHREAD_THREADS_MAX 256 /* define the maximum number of simultaneous 74 POSIX Pthreads supported. */ 75 76 POSIX_MAX_MUTEX 32 /* define the maximum number of simultaneous 77 POSIX mutexes sported. */ 78 79 80The function posix_initialize will return a pointer to the next free 81available memory location for the application. 82 83 843.0 POSIX Calls 85 86Once posix_initialize returns, POSIX calls can be made. 87The Threadx POSIX Compliancy Wrapper supports the following POSIX 88calls: 89 90/***********************************************************************/ 91/* CALLS RELATED TO POSIX MESSAGE QUEUE */ 92/***********************************************************************/ 93 94INT mq_send(mqd_t mqdes, const char * msg_ptr, 95 ssize_t msg_len,ULONG msg_prio ); 96ssize_t mq_receive(mqd_t mqdes, VOID *pMsg, ssize_t msgLen, 97 ULONG *pMsgPrio ); 98INT mq_unlink(const char * mqName); 99INT mq_close(mqd_t mqdes); 100mqd_t mq_open(const CHAR * mqName, ULONG oflags,...); 101 102 103/***********************************************************************/ 104/* CALLS RELATED TO POSIX SEMAPHORE */ 105/***********************************************************************/ 106 107INT sem_close(sem_t * sem); 108INT sem_getvalue(sem_t * sem,ULONG * sval); 109sem_t *sem_open(const char * name, ULONG oflag, ...); 110INT sem_post(sem_t * sem); 111INT sem_trywait(sem_t * sem); 112INT sem_unlink(const char * name); 113INT sem_wait( sem_t * sem ); 114INT sem_init(sem_t *sem , INT pshared, UINT value); 115INT sem_destroy(sem_t *sem); 116 117/***********************************************************************/ 118/* CALLS RELATED TO POSIX pthreads */ 119/***********************************************************************/ 120 121INT sched_yield(VOID); 122INT pthread_create (pthread_t *thread, 123 pthread_attr_t *attr, 124 VOID *(*start_routine)(VOID*),VOID *arg); 125INT pthread_detach(pthread_t thread); 126INT pthread_join(pthread_t thread, VOID **value_ptr); 127INT pthread_equal(pthread_t thread1, pthread_t thread2); 128VOID pthread_exit(VOID *value_ptr); 129pthread_t pthread_self(VOID); 130INT pthread_attr_destroy(pthread_attr_t *attr); 131INT pthread_attr_getdetachstate( pthread_attr_t *attr,INT *detachstate); 132INT pthread_attr_setdetachstate(pthread_attr_t *attr,INT detachstate); 133INT pthread_attr_getinheritsched(pthread_attr_t *attr, INT *inheritsched); 134INT pthread_attr_setinheritsched(pthread_attr_t *attr, INT inheritsched); 135INT pthread_attr_getschedparam(pthread_attr_t *attr,struct sched_param *param); 136INT pthread_attr_setschedparam(pthread_attr_t *attr,struct sched_param *param); 137INT pthread_attr_getschedpolicy(pthread_attr_t *attr, INT *policy); 138INT pthread_attr_setschedpolicy(pthread_attr_t *attr, INT policy); 139INT pthread_attr_init(pthread_attr_t *attr); 140INT phread_attr_getstackaddr( pthread_attr_t *attr,VOID **stackaddr); 141INT phread_attr_setstackaddr(pthread_attr_t *attr,VOID **stackaddr); 142INT pthread_attr_getstacksize( pthread_attr_t *attr, ssize_t *stacksize); 143INT pthread_attr_setstacksize(pthread_attr_t *attr, ssize_t stacksize); 144INT phread_attr_getstack( pthread_attr_t *attr,VOID **stackaddr, 145 ssize_t *stacksize); 146INT phread_attr_setstack( pthread_attr_t *attr,VOID *stackaddr, 147 ssize_t stacksize); 148 149INT pthread_mutexattr_gettype(pthread_mutexattr_t *attr, INT *type); 150INT pthread_mutexattr_settype(pthread_mutexattr_t *attr, INT type); 151INT pthread_mutexattr_destroy(pthread_mutexattr_t *attr); 152INT pthread_mutexattr_init(pthread_mutexattr_t *attr); 153INT pthread_mutex_destroy(pthread_mutex_t *mutex); 154INT pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr); 155INT pthread_mutex_lock(pthread_mutex_t *mutex ); 156INT pthread_mutex_unlock(pthread_mutex_t *mutex ); 157INT pthread_mutex_trylock(pthread_mutex_t *mutex); 158INT pthread_mutexattr_getprotocol( pthread_mutexattr_t *attr, INT *protocol); 159INT pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, INT protocol); 160INT pthread_mutexattr_getpshared (pthread_mutexattr_t *attr, INT *pshared); 161INT pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, INT pshared); 162INT pthread_mutex_timedlock(pthread_mutex_t *mutex, struct timespec *abs_timeout); 163INT pthread_setcancelstate (INT state, INT *oldstate); 164INT pthread_setcanceltype (INT type, INT *oldtype); 165INT pthread_cancel(pthread_t thread); 166VOID pthread_yield(VOID); 167VOID pthread_testcancel(VOID); 168INT pthread_getschedparam(pthread_t thread, INT *policy, struct sched_param *param); 169INT pthread_setschedparam(pthread_t thread, INT policy, const struct sched_param *param); 170 171INT sched_get_priority_max(INT policy) 172INT sched_get_priority_min(INT policy) 173 174INT pthread_once (pthread_once_t * once_control, VOID (*init_routine) (VOID)) 175 176INT pthread_kill(ALIGN_TYPE thread_id, int sig) 177INT pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask) 178 179 180/***********************************************************************/ 181/* CALLS RELATED TO POSIX CONDITION VARIABLE */ 182/***********************************************************************/ 183 184INT pthread_cond_destroy(pthread_cond_t *cond); 185INT pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr); 186INT pthread_cond_broadcast(pthread_cond_t *cond); 187INT pthread_cond_signal(pthread_cond_t *cond); 188INT pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex, 189 struct timespec *abstime); 190INT pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); 191 192 193/***********************************************************************/ 194/* CALLS RELATED TO Timer */ 195/***********************************************************************/ 196 197INT nanosleep(struct timespec *req, struct timespec *rem) 198INT sleep(ULONG seconds) 199INT clock_gettime(clockid_t t, struct timespec * tspec) 200INT clock_settime(clockid_t t, const struct timespec * tspec) 201INT clock_getres(clockid_t t, struct timespec * tspec) 202 203/***********************************************************************/ 204/* CALLS RELATED TO Signal */ 205/***********************************************************************/ 206 207INT sigwait(const sigset_t *set, int *sig) 208INT sigaddset(sigset_t *set, int signo) 209INT sigdelset(sigset_t *set, int signo) 210INT sigemptyset(sigset_t *set) 211INT signal(int signo, void (*func)(int)) 212INT sigfillset(sigset_t *set) 213 214 2154.0 POSIX Compliancy Wrapper Error Handling 216 217There are two "error handling" functions defined in tx_posix.c and used 218throughout the Wrapper, as follows: 219 220 posix_error_handler 221 posix_internal_error 222 223In general these routines are called when basic usage errors occur. These 224routines may also be used as a place to catch errors that are not detected if the 225application source is not checking the return status. The default processing for each of 226these is a simple spin loop. 227 228Most functions can provide an error number. The means by which each function 229provides its error numbers is specified in its description. Some functions 230provide the error number in a variable accessed through the symbol posix_errno. 231While other functions return an error number directly as the function value. Functions 232return a value of zero to indicate success. If more than one error occurs in 233processing a function call, any one of the possible errors may be returned, as the order 234of detection is undefined. 235 236Some functions may return [ENOSYS] suggesting that an attempt was made to 237use a function that is not available in this implementation. 238 239Each pthread has its own error number, which can be obtained through a 240function call: 241 242INT posix_get_pthread_errno(pthread_t ptid) 243 244This call will return the last generated error code for the pthread having 245ptid as an ID. 246 247 2485.1 POSIX Compliancy Wrapper Limitations 249 250Due to performance and architecture issues, this POSIX Compliancy Wrapper 251does not support all the POSIX calls. A summary of the POSIX Compliancy 252Wrapper limitations is as follows: 253 254� Configuration 255� Initialization 256� Driver and I/O model might require porting of current drivers. 257� Multi-processor extensions are not supported 258� Unsupported calls (please see below) 259. Calls supported with certain limitations (please see list below) 260 261The POSIX Compliancy Wrapper supports a subset of POSIX calls. In addition, 262there are also certain limitations with respect to some services. Below is the list of 263such limitations: 264 265 266LIMITATIONS 267 268Following calls are implemented with some limitations: 269 2701.) mq_open() 271 272 LIMITATIONS : 273 a.) The value of mode (mode_t) has no effect in this implementation. 274 b.) If pAttr is NULL, the message queue is created with 275 implementation-defined default message queue attributes. 276 The default message queue attributes selected are : 277 278 #define MQ_MAXMSG 125 [MQ_MAXMSG 1024 (POSIX value)] 279 #define MQ_MSGSIZE 500 [MQ_MSGSIZE 4096 (POSIX value)] 280 #define MQ_FLAGS 0 281 282 This is due to limitation of size of posix_region0_byte_pool (64KB ). 283 2842.) mq_send() 285 286 LIMITATIONS : 287 a.) In POSIX : If more than one mq_send() is blocked on a queue and 288 space becomes available in that queue, the message with the highest 289 priority will be unblocked. THIS FEATURE IS NOT IMPLEMENTED. 290 291 b.) If a message is sent (or received) to a queue with out opening the named 292 queue, in such a case mqdes (message queue descriptor) pointer is 293 invalid and may result in erratic behavior. 294 2953.) mq_receive() 296 297 LIMITATIONS : 298 a.) If a receive (or send) message from queue with out it being opened, erratic 299 behavior may ensue. 300 3014.) ULONG sem_close() 302 303 LIMITATIONS : 304 a.) This routine does not deallocate any system resources. 305 3065.) POSIX SEMAPHORE 307 308 LIMITATIONS : 309 a.) If any operation (eg. sem_post, sem_wait, sem_trywait, sem_getvalue ) is done on a 310 semaphore before creating or opening (sem_open()) the named semaphore, erratic 311 behavior may result. 312 3136.) ULONG sem_trywait(sem_t * sem) 314 315 LIMITATIONS : 316 317 a.) EDEADLKA :->[ This is a return value when deadlock condition is detected; i.e., two separate 318 processes are waiting for an available resource to be released via a 319 semaphore "held" by the other process.] This is not implemented. 320 321 b.) EINTR :->[ This is a return value when sem_wait() was interrupted by a signal.] 322 This is not implemented. 3237.) Thread Cancelation 324 325pthread cancelation cleanup handlers are not supported which means 326pthread_cleanup_push( ) and pthread_cleanup_pop( ) functions are not 327implemented. 328 329When the pthread_cancel( ) function is called the target thread is canceled 330with immediate effect. (provided cancelability is enabled for the target 331pthread) 332 333The cancelation processing in the target thread shall run asynchronously 334with respect to the ailing thread returning from pthread_cancel( ). 335 3368.) Attributes for Condition Variable 337 No attributes are supported for condition variable in this implementation. 338 3399.) pthreads suspended by nanosleep() and sleep() calls can not be awakened 340by signals, once in the suspension both these calls will complete the 341suspension period. 342 34310.) pthread_once (pthread_once_t * once_control, VOID (*init_routine) (VOID)) 344There is no provision if the init_routine contains a cancellation point. 345 346 3476.0 Demonstration System 348 349The file posix_demo.c contains a demonstration system that utilizes POSIX 350calls. This Demo application will demonstrate some of the basic POSIX 351calls. This demo application should be used as an example of how to integrate the POSIX 352Compliancy Wrapper into your application. 353 354 3557.0 Future POSIX Compliancy Wrapper Phases 356 357Please get in touch with us for next phases of this POSIX Compliancy 358Wrapper. 359 360 361 362 363