1 /*
2 * Copyright (c) 2012-2013, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /**
33 * @file ti/ipc/ListMP.h
34 *
35 * @brief Multiple processor shared memory list
36 *
37 * @note ListMP is currently only available for SYS/BIOS.
38 *
39 * ListMP is a doubly linked-list based module designed to be used
40 * in a multi-processor environment. It provides a way for
41 * multiple processors to create, access, and manipulate the same link
42 * list in shared memory.
43 *
44 * The ListMP module uses a NameServer instance
45 * to store information about an instance during create. Each
46 * ListMP instance is created by specifying a name and region id.
47 * The name supplied must be unique for all ListMP instances in the system.
48 *
49 * ListMP_create() is used to create an instance of a ListMP.
50 * Shared memory is modified during create. Once created, an instance
51 * may be opened by calling ListMP_open(). Open does not
52 * modify any shared memory. Open() should be called only when global
53 * interrupts are enabled.
54 *
55 * To use a ListMP instance, a #ListMP_Elem must be embedded
56 * as the very first element of a structure. ListMP does not provide
57 * cache coherency for the buffer put onto the link list.
58 * ListMP only provides cache coherency for the #ListMP_Elem
59 * fields. The buffer should be written back before being placed
60 * on a ListMP, if cache coherency is required.
61 *
62 * The ListMP header should be included in an application as follows:
63 * @code
64 * #include <ti/ipc/ListMP.h>
65 * @endcode
66 */
68 #ifndef ti_ipc_ListMP__include
69 #define ti_ipc_ListMP__include
71 #include <ti/ipc/SharedRegion.h>
72 #include <ti/ipc/GateMP.h>
74 #if defined (__cplusplus)
75 extern "C" {
76 #endif
78 /* =============================================================================
79 * All success and failure codes for the module
80 * =============================================================================
81 */
83 /*!
84 * @brief The resource is still in use
85 */
86 #define ListMP_S_BUSY 2
88 /*!
89 * @brief The module has been already setup
90 */
91 #define ListMP_S_ALREADYSETUP 1
93 /*!
94 * @brief Operation is successful.
95 */
96 #define ListMP_S_SUCCESS 0
98 /*!
99 * @brief Generic failure.
100 */
101 #define ListMP_E_FAIL -1
103 /*!
104 * @brief Argument passed to function is invalid.
105 */
106 #define ListMP_E_INVALIDARG -2
108 /*!
109 * @brief Operation resulted in memory failure.
110 */
111 #define ListMP_E_MEMORY -3
113 /*!
114 * @brief The specified entity already exists.
115 */
116 #define ListMP_E_ALREADYEXISTS -4
118 /*!
119 * @brief Unable to find the specified entity.
120 */
121 #define ListMP_E_NOTFOUND -5
123 /*!
124 * @brief Operation timed out.
125 */
126 #define ListMP_E_TIMEOUT -6
128 /*!
129 * @brief Module is not initialized.
130 */
131 #define ListMP_E_INVALIDSTATE -7
133 /*!
134 * @brief A failure occurred in an OS-specific call
135 */
136 #define ListMP_E_OSFAILURE -8
138 /*!
139 * @brief Specified resource is not available
140 */
141 #define ListMP_E_RESOURCE -9
143 /*!
144 * @brief Operation was interrupted. Please restart the operation
145 */
146 #define ListMP_E_RESTART -10
148 /* =============================================================================
149 * Structures & Enums
150 * =============================================================================
151 */
153 /*!
154 * @brief ListMP_Handle type
155 */
156 typedef struct ListMP_Object *ListMP_Handle;
158 /*!
159 * @brief Structure defining a ListMP element.
160 */
161 typedef struct ListMP_Elem {
162 volatile SharedRegion_SRPtr next;
163 /*!< SharedRegion pointer to next element */
165 volatile SharedRegion_SRPtr prev;
166 /*!< SharedRegion pointer to previous element */
168 } ListMP_Elem;
170 /*!
171 * @brief Structure defining parameter structure for ListMP_create().
172 */
173 typedef struct ListMP_Params {
174 GateMP_Handle gate;
175 /*!< GateMP instance for critical region management of shared memory
176 *
177 * Using the default value of NULL will result in use of the GateMP
178 * system gate for context protection.
179 */
181 /*! @cond */
182 Ptr sharedAddr;
183 /*!< Physical address of the shared memory
184 *
185 * The shared memory that will be used for maintaining shared state
186 * information. This is an optional parameter to create. If value
187 * is null, then the shared memory for the new instance will be
188 * allocated from the heap in the specified region Id.
189 */
190 /*! @endcond */
192 String name;
193 /*!< Name of the instance
194 *
195 * The name (if not NULL) must be unique among all ListMP
196 * instances in the entire system. When creating a new
197 * heap, it is necessary to supply an instance name.
198 *
199 * The name does not have to be persistent. The supplied string is copied
200 * into persistent memory.
201 */
203 UInt16 regionId;
204 /*!< SharedRegion ID.
205 *
206 * The ID corresponding to the index of the shared region in which this
207 * shared instance is to be placed. This is used in create() only when
208 * name is not null.
209 */
211 } ListMP_Params;
213 /* =============================================================================
214 * ListMP Module-wide Functions
215 * =============================================================================
216 */
218 /*!
219 * @brief Initializes ListMP parameters.
220 *
221 * @param params Instance param structure.
222 */
223 Void ListMP_Params_init(ListMP_Params *params);
225 /*!
226 * @brief Creates and initializes ListMP module.
227 *
228 * @param params Instance param structure.
229 *
230 * @return ListMP instance handle. NULL if create failed.
231 *
232 * @sa ListMP_delete()
233 */
234 ListMP_Handle ListMP_create(const ListMP_Params *params);
236 /*!
237 * @brief Close an opened ListMP instance
238 *
239 * Closing an instance will free local memory consumed by the opened
240 * instance. Instances that are opened should be closed before the
241 * instance is deleted. If using NameServer,
242 * the instance name will be removed from the NameServer instance.
243 *
244 * @param handlePtr Pointer to a ListMP instance
245 *
246 * @return Status
247 * - #ListMP_S_SUCCESS: ListMP successfully closed
248 * - #ListMP_E_FAIL: A general failure has occurred
249 *
250 * @sa ListMP_open()
251 */
252 Int ListMP_close(ListMP_Handle *handlePtr);
254 /*!
255 * @brief Deletes a ListMP instance.
256 *
257 * @param handlePtr Pointer to ListMP instance
258 *
259 * @return Status
260 * - #ListMP_S_SUCCESS: ListMP successfully deleted
261 * - #ListMP_E_FAIL: ListMP delete failed
262 *
263 * @sa ListMP_create()
264 */
265 Int ListMP_delete(ListMP_Handle *handlePtr);
267 /*!
268 * @brief Open a created ListMP instance
269 *
270 * An open can be performed on a previously created instance.
271 * Open is used to gain access to the same ListMP instance.
272 * Generally an instance is created on one processor and opened on
273 * other processors but it can be opened on the same processor too.
274 * Open returns a ListMP instance handle like create, but it does
275 * not initialize any shared memory.
276 *
277 * The open call searches the local ListMP NameServer table first
278 * for a matching name. If no local match is found, it will search all
279 * remote ListMP NameServer tables for a matching name.
280 *
281 * A status value of #ListMP_S_SUCCESS is returned if a matching
282 * ListMP instance is found. A #ListMP_E_FAIL is returned if no
283 * matching instance is found. Generally this means the ListMP instance
284 * has not yet been created. A more specific status error is returned if
285 * an error was raised.
286 *
287 * Call close() when the opened instance is no longer needed.
288 *
289 * @param name Name of created ListMP instance
290 * @param handlePtr pointer to the handle if a handle was found.
291 *
292 * @return Status
293 * - #ListMP_S_SUCCESS: ListMP successfully opened
294 * - #ListMP_E_NOTFOUND: ListMP is not yet ready to be opened.
295 * - #ListMP_E_FAIL: A general failure has occurred
296 *
297 * @sa ListMP_close()
298 * @sa ListMP_create()
299 */
300 Int ListMP_open(String name, ListMP_Handle *handlePtr);
302 /*! @cond
303 * @brief Open a created ListMP instance by address
304 *
305 * Just like ListMP_open(), openByAddr returns a handle to a
306 * created ListMP instance. This function allows the ListMP to be
307 * opened using a shared address instead of a name.
308 * While ListMP_open() should generally be used to open ListMP
309 * instances that have been either locally or remotely created, openByAddr
310 * may be used to bypass a NameServer query that would typically be
311 * required of an ListMP_open() call.
312 *
313 * Opening by address requires that the created instance was created
314 * by supplying a ListMP_Params#sharedAddr parameter rather than a
315 * ListMP_Params#regionId parameter.
316 *
317 * A status value of #ListMP_S_SUCCESS is returned if the ListMP is
318 * successfully opened. #ListMP_E_FAIL indicates that the ListMP is
319 * not yet ready to be opened.
320 *
321 * Call ListMP_close() when the opened instance is not longer needed.
322 *
323 * @param sharedAddr Shared address for the ListMP instance
324 * @param handlePtr Pointer to ListMP handle to be opened
325 *
326 * @return Status
327 * - #ListMP_S_SUCCESS: ListMP successfully opened
328 * - #ListMP_E_FAIL: ListMP is not ready to be opened
329 */
330 Int ListMP_openByAddr(Ptr sharedAddr, ListMP_Handle *handlePtr);
332 /*! @endcond */
334 /*! @cond
335 * @brief Amount of shared memory required for creation of each instance
336 *
337 * The ListMP_Params#regionId or ListMP_Params#sharedAddr
338 * needs to be supplied because the cache alignment settings for the region
339 * may affect the total amount of shared memory required.
340 *
341 * @param params Pointer to the parameters that will be used in
342 * the create.
343 *
344 * @return Number of MAUs needed to create the instance.
345 */
346 SizeT ListMP_sharedMemReq(const ListMP_Params *params);
348 /*! @endcond */
350 /* =============================================================================
351 * ListMP Per-instance Functions
352 * =============================================================================
353 */
355 /*!
356 * @brief Determines if a ListMP instance is empty
357 *
358 * @param handle a ListMP handle.
359 *
360 * @return TRUE if 'next' element points to head, otherwise FALSE
361 */
362 Bool ListMP_empty(ListMP_Handle handle);
364 /*!
365 * @brief Retrieves the GateMP handle associated with the ListMP instance.
366 *
367 * @param handle a ListMP handle.
368 *
369 * @return GateMP handle for ListMP instance.
370 */
371 GateMP_Handle ListMP_getGate(ListMP_Handle handle);
373 /*!
374 * @brief Get an element from front of a ListMP instance
375 *
376 * Atomically removes the element from the front of a
377 * ListMP instance and returns a pointer to it.
378 * Uses #ListMP_Params.gate for critical region management.
379 *
380 * @param handle a ListMP handle.
381 *
382 * @return pointer to former first element. NULL if the ListMP is empty.
383 */
384 Ptr ListMP_getHead(ListMP_Handle handle);
386 /*!
387 * @brief Get an element from back of a ListMP instance
388 *
389 * Atomically removes the element from the back of a
390 * ListMP instance and returns a pointer to it.
391 * Uses #ListMP_Params.gate for critical region management.
392 *
393 * @param handle a ListMP handle.
394 *
395 * @return pointer to former last element. NULL if the ListMP is empty.
396 */
397 Ptr ListMP_getTail(ListMP_Handle handle);
399 /*!
400 * @brief Insert an element into a ListMP instance
401 *
402 * Atomically inserts @c newElem in the instance in front of @c curElem.
403 * To place an element at the back of a ListMP instance, use
404 * ListMP_putTail(). To place an element at the front of a
405 * ListMP instance, use ListMP_putHead().
406 *
407 * The following code shows an example.
408 *
409 * @code
410 * ListMP_Elem elem, curElem;
411 *
412 * ListMP_insert(listHandle, &elem, &curElem); // insert before curElem
413 * @endcode
414 *
415 * @param handle a ListMP handle.
416 * @param newElem new element to insert into the ListMP.
417 * @param curElem current element in the ListMP.
418 *
419 * @return Status
420 * - #ListMP_S_SUCCESS: if operation was successful
421 * - #ListMP_E_FAIL: if operation failed
422 */
423 Int ListMP_insert(ListMP_Handle handle,
424 ListMP_Elem *newElem,
425 ListMP_Elem *curElem);
427 /*!
428 * @brief Return the next element in a ListMP instance (non-atomic)
429 *
430 * Is useful in searching a ListMP instance.
431 * It does not remove any items from the ListMP instance.
432 * The caller should protect the ListMP instance from being changed
433 * while using this call since it is non-atomic.
434 *
435 * To look at the first `elem` on the ListMP, use NULL as the `elem`
436 * argument.
437 *
438 * The following code shows an example.
439 * The scanning of a ListMP instance should be protected
440 * against other threads that modify the ListMP.
441 *
442 * @code
443 * ListMP_Elem *elem = NULL;
444 * GateMP_Handle gate;
445 * IArg key;
446 *
447 * // get the gate for the ListMP instance
448 * gate = ListMP_getGate(listHandle);
449 *
450 * // Begin protection against modification of the ListMP.
451 * key = GateMP_enter(gate);
452 *
453 * while ((elem = ListMP_next(ListMPHandle, elem)) != NULL) {
454 * //act on elem as needed. For example call ListMP_remove().
455 * }
456 *
457 * // End protection against modification of the ListMP.
458 * GateMP_leave(gate, key);
459 * @endcode
460 *
461 * @param handle a ListMP handle.
462 * @param elem element in ListMP or NULL to start at the head
463 *
464 * @return next element in ListMP instance or NULL to denote end.
465 */
466 Ptr ListMP_next(ListMP_Handle handle, ListMP_Elem *elem);
468 /*!
469 * @brief Return the previous element in ListMP instance (non-atomic)
470 *
471 * Useful in searching a ListMP instance in reverse order.
472 * It does not remove any items from the ListMP instance.
473 * The caller should protect the ListMP instance from being changed
474 * while using this call since it is non-atomic.
475 *
476 * To look at the last `elem` on the ListMP instance, use NULL as the
477 * `elem` argument.
478 *
479 * The following code shows an example. The scanning of a ListMP instance
480 * should be protected against other threads that modify the instance.
481 *
482 * @code
483 * ListMP_Elem *elem = NULL;
484 * GateMP_Handle gate;
485 * IArg key;
486 *
487 * // get the gate for the ListMP instance
488 * gate = ListMP_getGate(listHandle);
489 *
490 * // Begin protection against modification of the ListMP.
491 * key = GateMP_enter(gate);
492 *
493 * while ((elem = ListMP_prev(listHandle, elem)) != NULL) {
494 * //act on elem as needed. For example call ListMP_remove().
495 * }
496 *
497 * // End protection against modification of the ListMP.
498 * GateMP_leave(gate, key);
499 * @endcode
500 *
501 * @param handle a ListMP handle.
502 * @param elem element in ListMP or NULL to start at the end
503 *
504 * @return previous element in ListMP or NULL if empty.
505 */
506 Ptr ListMP_prev(ListMP_Handle handle, ListMP_Elem *elem);
508 /*!
509 * @brief Put an element at head of a ListMP instance
510 *
511 * Atomically places the element at the front of a ListMP instance.
512 * Uses #ListMP_Params.gate for critical region management.
513 *
514 * @param handle a ListMP handle
515 * @param elem pointer to new ListMP element
516 *
517 * @return Status
518 * - #ListMP_S_SUCCESS: if operation was successful
519 * - #ListMP_E_FAIL: if operation failed
520 */
521 Int ListMP_putHead(ListMP_Handle handle, ListMP_Elem *elem);
523 /*!
524 * @brief Put an element at back of a ListMP instance
525 *
526 * Atomically places the element at the back of a ListMP instance.
527 * Uses #ListMP_Params.gate for critical region management.
528 *
529 * @param handle a ListMP handle
530 * @param elem pointer to new ListMP element
531 *
532 * @return Status
533 * - #ListMP_S_SUCCESS: if operation was successful
534 * - #ListMP_E_FAIL: if operation failed
535 */
536 Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem);
538 /*!
539 * @brief Remove an element from a ListMP instance
540 *
541 * Atomically removes an element from a ListMP.
542 *
543 * The @c elem parameter is a pointer to an existing element to be removed
544 * from a ListMP instance.
545 *
546 * @param handle a ListMP handle
547 * @param elem element in ListMP
548 *
549 * @return Status
550 * - #ListMP_S_SUCCESS: if operation was successful
551 * - #ListMP_E_FAIL: if operation failed
552 */
553 Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem);
555 #if defined (__cplusplus)
556 }
557 #endif /* defined (__cplusplus) */
559 #endif /* ti_ipc_ListMP__include */