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