Hello,
I'd like to write some reusabel code module to handle e.g. UART ports. Therefore I'd like to create a variable number (based on some kind of define...) of threads dealing with UART port 1,2,3 ... since it is possible to declare CMSIS-RTOS threads with a variable number of instances it could look like this:
#define UART_PORT_NUM 3 osThreadDef(uart_thread, osPriorityNormal, UART_PORT_NUM, 0)
my problem: If I need any kind of inter-thread communication (ITC) object, like mutexes or mail queues, for each of this threads I don't know how to declare them, since osMailQDef, osMutexDef and so on, are not designed with a "variable" number of instances...
Any suggestions?
I had a similar need for reusable code involving mutexes. The way the macros are defined in cmsis_os.h make that difficult, but after some study it appears all that's needed is a control block of uint32_t[4] and a temporary pointer.
The osMutexDef(x) goes away, as does osMutex(x). I've replaced those with:
typedef struct _osMutexCb { uint32_t cb[4]; // this is the actual control block void *pCb; // pointer to the control block. Only needed during osMutexCreate } osMutexCb_t;
You should be able to allocate space for that statically or dynamically, as many of them as you need.
I've created a wrapper for the create. This could also be done as a macro or inline, but I have some portability issues with the latter.
osMutexId osMutexCreate2(osMutexCb_t *MutexCb) { MutexCb->pCb = (void *) MutexCb->cb; return osMutexCreate((const osMutexDef_t *) &MutexCb->pCb); }
The other mutex functions only use the osMutexId (which is just a pointer to the control block, so why couldn't osMutexCreate just use it in the first place?). Duh.
That's an awfully lot of monkey motion for a relatively simple thing. It's also a redundant level of indirection where we're sending osMutexCreate a pointer to a pointer. In the standard cmsis syntax using osMutexDef macro, that pointer space is only used once for the create. I tested this using an auto variable, demonstrating it does not need to be retained.
The old Keil programmers would have never permanently wasted those 4 bytes, or the redundant level of indirection. They were careful of CPU clocks and space efficiency.
I've seen some claims posted here that the standard osMutexDef() and osMutex() macros make code more readable. Nonsense. Wrapping a simple block of storage in a macro that references a typedef is less readable, not more. It took several hours to conclude that all you needed was 16 bytes of storage and send osMutexCreate a pointer to a pointer to that storage and you're finished.
I'm at a loss to understand why Keil created these macros that make it difficult to write reusable code. The only reasonable answer might be that programmers will be less likely to "lose" control blocks by deallocating them from dynamic memory, or some other accident.
Ok. But they could have easily protected dumb programmers by retaining the control block within OS static memory and allocating it during mutex create. Yes, that would mean a fixed number of mutexes would be allowed, but that's no different than the static memory allocated for the stack, or the fixed number of threads, etc.
The bottom line is cmsis should have been similar to other OSes, and allow programmers to control their own mutexes and other OS objects. This would make portability and re-learning issues easier. I'm sure whomever designed this thing believes they were doing someone a favor. Sorry, no. It made things much more difficult, and in the end I've just rewritten a chunk of cmsis_os.h to let me do what I need to do. No doubt I'll rewrite more of it. That's time I've wasted merely because the convoluted multi-layer syntax in cmsis_os_h wouldn't allow me to do what is easily done with other OSes.
I have the same issue. I need to create a generic buffer function that can safely pass data between threads using a Mutex. I want this to be reusable code, so I have no idea how many such buffers I will have. What I DO NOT want to do is create one set of buffer storage areas, and a matching set of osMutexDef definitions that I must coordinate. Yes, that would work, but I should not need to do so.
So I have a typedef something like:
typedef struct _SAFE_BUFFER { unsigned char *pBuffer; unsigned long iIndex; osMutexDef (SafeMutex); } SAFE_BUFFER;
That won't work. The osMutexDef gives a syntax error.
So I looked through cmsis_os.h and it appears all I need to do is create a const uint32_t variable and create the mutex with a cast to (const osMutexDef_t *) to a pointer to it.
That actually compiles without error, but it does not work. I even ensured the variable was allocated in the same storage area, etc. but no work. I mangled the name with the "os_mutex_def_" prefix the way that cmsis_os.h does, still no work.
I don't need a lecture about why I don't need to do this. I don't need to be told another ways of passing buffer data is better. I want a result with straight C reusable code that's simple and works like all the other code I have.
The OS needs a place to store the actual mutex. I should be able to do that in a struct and then specify n number of them and initialize them individually. If CMSIS can't do that, then it was written incorrectly.
I'll say it again. I don't care if some other way is better or more preferred. I want to do it like I have above. How can I make that work?
It is not at all safe to just make them temporary.
See my example for just supplying a struct to the tread, informing it what queues etc to associate with.
Ok, that's what I need, thank you! I have to adapt it (I forgot to mention, that I am using C, the mentioned C++ thread was just to demonstrate, that there is a need for such an implementation) I was also thinking about avoiding the typical osXyzDef() macros and to do all the stuff manually. The only question, which you also have mentioned in your comment: Is it really save/recommendable to create the osXyzDef_t structures (e.g. osMutexDef_t) temporary? The macros are creating them as const, so I thought, the kernel needs it that way.
Here is 1 exammple - very specific to Keil's CMSIS RTOS implementation.
namespace OsRTX { // uint32_t os_mutex_cb_##name[4] = { 0 }; becomes.. struct Mutex { uint32_t _private_[4]; }; } class OsMutex { private: OsRTX::Mutex m_rtxMutex; osMutexId m_MutexId; void Create() { osMutexDef_t temp; // Note: not all osDef_t items can be temporary temp.mutex = &m_rtxMutex; m_MutexId = osMutecCreate( (const osMutexDef_t *) &temp); } public: OsMutex() { Create(); } // Initialized at construction! // Note: not all os items can be initialized // before the OS is running. ~OsMutex() {} osStatus Wait(uint32_t millis) { return osMutexWait(m_MutexId, millis); } osStatus Release() { return osMutexRelease(m_MutexId); } }; // 2 Instances of Mutex Objects OsMutex Uart1Mutex; osMutex Uart2Mutex; // Usage status = Uart1Mutex.Wait(100); status = Uart1Mutex.Release();
You can do something like this
class Uart : public UartBase { UART* m_uart; OsMutex m_mutex; public: Uart(UART* uart) : m_uart(uart) {} ~Uart() {} osStatus Acquire(uint32_t millis) { return m_mutex.Wait(millis); } osStatus Release() }; Uart GPS_Uart(UART1); Uart GSM_Uart(UART2); Uart Debug_Uart(UART3);
Combining MANY items you can
Class GenericObjectUsingTaskAndUart { static const uint32_t mbxitems = 10; UartBase *m_uart; OsThread A1; OsThread A2; // Usually the object IS-A thread, but if you want multiple threads // tied together, you would have the class contain them... OsMbx<mbxitems,DataType_t> InQueue// Mailbox with 10 entries of type DataType_t public: GenericObjectUsingTaskAndUart(UartBase *uart) : m_uart(uart) {} ~GenericObjectUsingTaskAndUart() {} osStatus InitTask() { // Init and start threads, other stuff, that must happen // After OS is running. Could break into InitTask and Start } OsMbxBase<DataType_t> *GetInQueue() { return &InQueue; } }; // We now have an object that contains what it needs and knows about then, but is not // specifically tied to something GenericObjectUsingTaskAndUart Gen1(UART1); GenericObjectUsingTaskAndUart Gen2(UART2); GenericObjectUsingTaskAndUart Gen3(UART3);
You may create objects for every os item type (mailbox,message,timer,thread) They can be generically combined in any way imagined (for good or bad)
This is just an example for thought. I am not suggesting that it is a way anyone should use it. Just posting it as an actual answer the original question. I am certainly not requesting any kind of critique.
And you are so eloquent.
Wow, you sir, are a huge JACKASS!
If I have such a terminal server, I wouldn't want it to increase the priority, since I would want each connection to be fair.
If your advanced pump driver needs multiple threads, then it is a very, very low probability that you would talk about identical threads. So you would want to set up multiple, specific, threads. And you each thread would want to know what specific input/output/synchronization objects to use.
So I would normally do:
create_thread(id_pump1,pump1_addr,pump1_event,pump1_prio,pump1_listener); create_thread(id_pump2,pump2_addr,pump2_event,pump2_prio,pump2_listener); ...
and would not have a need for multiple, identical, threads operating in an anonymous way on some anonymous pool of other ITC objects.
If a user wants to increase the speed of pump 5, the user needs to be able to address pump 5. So the user needs to have a specific pump 5 control object.
Same if the user wants to get an alarm because pump 2 fails to keep the intended rpm - then the user needs the thread operating pump 2 to know exactly where to send the reports.
That is why you would normally not see a need for an anonymous group of mutex objects. Or of event objects. Or of mail boxes. But while there is regularly a need for an anonymous group of threads.
You are constantly trying to invent some random system that would need a mutex pool. But you aren't managing to move from an invented system to instead describe a real, existing, usage case. While it's trivial to list thousands upon thousands of existing implementations needing a thread pool.
And look back one more time on osThreadDef().
It takes the parameters:
name name of the thread function. priority initial priority of the thread function. instances number of possible thread instances. stacksz stack size (in bytes) requirements for the thread function.
So you specify one (1) priority. But you can specify multiple instances.
But that terminal server solution can then perform multiple osThreadCreate() in which the last parameter allows each thread to know which UART it is responsible for. And that parameter can be a pointer to a struct that can look like:
struct term_port { uint32_t addr; // Base address of UART. osMessageQId send_queue_id; // Where to pick up outgoing messages. osMessageQId recv_queue_id; // Where to send received data. ... };
In the end, the rest of the world needs to know where to send data. And where to pick up data. And how to flag events. So the rest of the program needs well defined objects to operate on. So what reason would there be to have a osMutexDef() that takes a parameter "instances"? I either wants to send my output to a specific printer ("office floor 2") or I want to send it to a generic pool and have the first free printer pick up the data. So either I want each printer to have a named queue. Or I want all printers to look in a common queue and the first to grab the data wins.
With the common queue, I expect the printers to be supplying the same service. With the separate queues, I would expect each printer to be able to have different capabilities so I may select a printer that has duplex support. Or photo colors.
In the end, I have to repeat the same thing I said in the previous post. Don't ask for anonymous mutex pools, anonymous queue pools, ... until you actually have managed to find a problem that would be able to take good advantage of such functionality.
The world have had pthreads for a great many years, without anyone actually getting stuck because of such needs.
When you make posts to this thread, you aren't making the posts to an arbitrary pool of queues or trying to take one mutex from an arbitrary pool of mutexes. You post an addresses message reaching a specific queue affecting a specific mutex. The server may be redundant or load-sharing, in which case there is a pool of symmetrical threads listening for incomming data from that queue.
So in the end, the bulk of all functionality around you just happens to be designed around the two basic variants: - multiple workers load-sharing tasks received from a single boss. - multiple companies with individual email addresses or phone numbers.
Spend some time with computer-science books and you'll see lots of generic examples of producer-consumer systems, or publisher-subscriber systems. And the thread implementations are designed around these two concepts.
The only companies who likes "random mailboxes" are the spam companies. But the normal need is to have either an addressed push or an addressed pull.
Ok, last try:
Think of a device driver, e.g. to control a pump connected over a fieldbus. Depending on the complexity of such a driver module, it could even consist of multiple threads. You don't know in which project this driver will be included, but there could be multiple pumps, with different priorities (e.g. because the application knows that one pump has to be adjusted more frequently). Each driver instance would need its own message/mail queues to get input data from the application (for example a superordinate synchronization thread) and to send its output back. And as I said: If this module realy consists of multiple threads, it could be possible that it needs internally hidden, anonymous ITC objects.
About your own example: if you have such a terminal server and you know that there is one client talking a lot more than the others, it could be usefull to increase its priority
Perhaps we are talking past each other, but when I ask "I have a problem xy, any suggestions how to fix it?", aswers like "I can't imagine why you need this" are not really helpfull.
If you make a terminal server, for example handling a number of serially connected RFID readers, then you have a situation where each reader - i.e. each UART - produces identical data.
Then it would be meaningful to use identical code to process the actual data. But each thread would need to know exactly what interface it is associated with, so it would need to know exactly what mutex to use or what queue to listen to. So the threads wouldn't be anonymous and there would still not really be a need for a pool of mutex objects or queue objects.
And in the above case, each RFID reader would also be expected to have the same priority. So no need to control that per thread or per port or per queue.
In the other diretion, you can find many examples where there is a need for a pool of anonymous threads. Each taking input from the same queue. Each producing an output to place into another queue. Each with the same priority. The code implemented as a thread pool just because the input data requires some processing that involves a delay (possibly slow hardware like having to wait for a file operation) or because the processor has multiple cores. So multiple, symmetrical threads, are used to get higher concurrency.
But back to you - can you show any single situation where there would be a need for multiple, anonymous, mutex objects? Or multiple, anonymous, queues?
Start looking for this functionality first after you have a design that would actually work better with this type of functionality - I have never seen such a concept really needed. The closest thing would be a load balancer taking input requests and forwarding them to multiple stupid work units that aren't able to pickup requests from a single queue but has to be tricked into thinking they are alone. But such a situation still really don't need a pool of anonymous queues, since the balancer would like to actually look at queue lengths or response times to figure out which of the output queues that is best suited to get more work.
Symmetrical thread pools are a very common design concept, as an alternative to multiplexed code which requires less resources but instead adds more complexity. But symmetrical means same priority and same input/output.
If I create multiple copies/instances of such a function I have to make multiple copies/instances of its data input and output interfaces as well. If all of them have to share the same input or output source/sink, the priority concept is useless.
So why should I have the possibility to create multiple thread instances if I have no possibility to create separate communication channels?
Could you give me another practical example of using the feature of creating multiple instances of a thread?
And by the way: "One of the interesting possibilities of an RTOS is that you can create multiple running instances of the same base thread code. So, for example, you could write a thread to control a UART and then create two running instances of the same thread code. Here each instance of the UART code could manage a different UART." Quote Trevor Martin, "The Designer's Guide to the Cortex-M Processor Family", Capter 6, page 178
Maybe there shouldn't be an answer because there isn't any real design that needs it?
A function that knows what it is doing would also be expected to know where to pick up data or where to forward data. So the function would be expected to know what mutex to use.
As I said, it really doesn't matter if this example is the best approach handling UART ports.
I am still struggling with my actual question:
Has anyone a suitable approach to implement a mechanism to create multiple instances of an ITC object?
btw.: I saw a thread asking a similar question (about ITC objects in C++ classes...), unfortunately I can't find it anymore. There were no answers...
But you would normally not use any thread at all to write out already formatted data. You would just use a queue of some kind, and have the interrupt pick up more data as the UART requests it.
Threads are best suited for either producing data that can be enqueued for transmission, or for picking up received data and processing it.
So you would normally have one thread that picks up received NMEA data, and decodes it so your program knows if there is a valid position and what that position is.
And you might have a different thread interfacing with a modem, inserting AT commands or data to the send queue and picking up responses from the receive queue.
And a third thread that decode monitor commands from a third UART and produce responses.
And maybe a third thread that might pick up received RFID strings, and validate them and store in some database.
So four almost identical interrupt handlers that only differs in what queue to pick up data from and what queue to post data to.
While four completely different threads with the actual business logic for the data expected to be sent and/or received for that specific UART.
So why would you want to insert a generic thread in the middle, that doesn't know anything about data protocols but just moves data to/from the different UART? Does interrupt handlers do this too well so you feel a need to complicate the design, while consuming extra resources?
View all questions in Keil forum