summaryrefslogtreecommitdiff
path: root/utility/rtos_compatibility_layers/posix/px_mq_create.c
blob: dc9f0fc341e11fb9e093f646bd0abb3c86b67867 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 * Copyright (c) 2026-present Eclipse ThreadX contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** POSIX wrapper for THREADX                                             */
/**                                                                       */
/**                                                                       */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/

/* Include necessary system files.  */

#include "tx_api.h"     /* Threadx API */
#include "pthread.h"    /* Posix API */
#include "px_int.h"     /* Posix helper functions */

/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    posix_mq_create                                     PORTABLE C      */
/*                                                           6.2.0        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    William E. Lamie, Microsoft Corporation                             */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This subroutine creates and initializes a message queue             */
/*    As the message length is user defined, message pointer and message  */
/*    length is stored in a ThreadX queue(instead of the actual message)  */
/*    The actual message is stored in a dedicated byte pool for the       */
/*    queue                                                               */
/*                                                                        */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    mq_name                               name of the Queue             */
/*    msgq_attr                             Pointer to mq_attr structure  */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    posix_q                               If success                    */
/*    NULL                                  If failure                    */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    posix_in_thread_context               Make sure caller is thread    */
/*    tx_queue_create                       to create a ThreadX Queue     */
/*    posix_internal_error                  Generic error Handler         */
/*    posix_memory_allocate                 to create a byte pool         */
/*    tx_queue_delete                       to delete the queue           */
/*    posix_putback_queue                   to delete the queue           */
/*    tx_byte_pool_create                   to create a byte pool         */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    POSIX internal Code                                                 */
/*                                                                        */
/**************************************************************************/
POSIX_MSG_QUEUE * posix_mq_create (const CHAR * mq_name,
                                      struct mq_attr * msgq_attr)
{

TX_INTERRUPT_SAVE_AREA

POSIX_MSG_QUEUE    *posix_q;
UINT                temp1;
VOID               *bp;
INT                 retval;
ULONG               size;
TX_QUEUE           *TheQ;

    /* Make sure we're calling this routine from a thread context.  */
    if (!posix_in_thread_context())
    {
       /* return POSIX error.  */
       posix_internal_error(444);

       /* return error.  */
       return ((POSIX_MSG_QUEUE *)ERROR);
    }
    /* Disable interrupts.*/
    TX_DISABLE

    /* Get a new queue from the POSIX queue pool.  */
    /* Make sure we have enough space for the size.  */

    posix_q = posix_get_new_queue(msgq_attr->mq_maxmsg);

    /* Make sure we actually got a queue.  */
    if (!posix_q)
    {
        /* Restore interrupts.  */
        TX_RESTORE

        /* User configuration error -  not enough memory.  */
        posix_errno = EBADF;
	    posix_set_pthread_errno(EBADF);

        /* Return ERROR.  */
        return(TX_NULL);
    }

    /* Now create a ThreadX message queue.
       to store only the message pointer and message length.  */
    temp1 = tx_queue_create((&(posix_q->queue)),
                             (CHAR *)mq_name,
                             TX_POSIX_MESSAGE_SIZE,
                             posix_q->storage,
                             (msgq_attr->mq_maxmsg * (sizeof(ULONG) * TX_POSIX_MESSAGE_SIZE)));

    /* Make sure it worked.  */
    if (temp1 != TX_SUCCESS)
    {
        /*. Return generic error.  */
        posix_internal_error(188);

        /* Restore interrupts.  */
        TX_RESTORE

        /* Return ERROR.  */
        return(TX_NULL);
    }
    /* Restore no. of maximum messages.  */
    posix_q->q_attr.mq_maxmsg = msgq_attr->mq_maxmsg;

    /* Restore maximum message length.  */
    posix_q->q_attr.mq_msgsize = msgq_attr->mq_msgsize;

    /* Flags are stored in que descriptor structure and
       not in mq_att structure.  */

    /* Create a byte pool for the  queue.
       Determine how much memory we need to store all messages in this queue.
       11 bytes are added to counter overhead as well as alignment problem if any.  */
    size = ( ((msgq_attr->mq_maxmsg) + 1)  * (msgq_attr->mq_msgsize + 11) );

    if(size < 100)
        size = 100;

    /* Now attempt to allocate that much memory for the queue.  */

    retval = posix_memory_allocate(size,&bp);

    /* Make sure we obtained the memory we requested.  */
    if (retval)
    {
        /* Created  queue Control block, got memory to store message pointers
           and lengths which means that created a fixed length message queue but
           not enough memory to store actual messages.  */

        /* Delete the queue.  */

        /* Assign a temporary variable for clarity.  */
        TheQ   = (TX_QUEUE * )posix_q;
        retval = tx_queue_delete(TheQ);

        /* Make sure the queue was deleted.  */
        if (retval != TX_SUCCESS)
        {
            /* Return generic error.  */
            posix_internal_error(799);

            /* Restore interrupts.  */
            TX_RESTORE

            /* Return ERROR.  */
            return(TX_NULL);
        }
        /* Put the queue back into the POSIX queue pool.  */
        posix_putback_queue(TheQ);

        /* User configuration error -  not enough memory.  */
        posix_errno =  EBADF;
        posix_set_pthread_errno(EBADF);
        TX_RESTORE;

        /* Return ERROR.  */
        return(TX_NULL);
    }
    /* Create a ThreadX byte pool that will provide memory needed by the queue.  */
    retval = tx_byte_pool_create((&(posix_q->vq_message_area)), "POSIX Queue",
                                    bp, size);

    /* Make sure the byte pool was created successfully.  */
    if (retval)
    {
        /* Error creating byte pool.  */
        posix_internal_error(9999);

        /* Restore interrupts.  */
        TX_RESTORE

        /* Return ERROR.*/
        return(TX_NULL);
    }

    posix_q->name = (CHAR*) mq_name;

    /* Restore interrupts.  */
    TX_RESTORE

    /* All done.  */
    return(posix_q);
}