mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Add ability to request a shared event queue
To allow components with a simple need to schedule a few events to not have to create their own threads, with all the associated memory overhead, add 2 central calls to get shared normal and an interrupt-deferral event queues, each dispatched on their own shared threads. For non-RTOS systems, just the normal event queue is provided, and the application would have to dispatch this itself. This application-dispatch is also available via a config option, to potentially save memory by reusing the main thread. Possible future improvement: the ability for separate components to request a minimum stack size, and have the JSON combine these requests. (Analogous tooling has already been mooted for mbed TLS config options like key size).pull/4406/head
							parent
							
								
									4978a08ae2
								
							
						
					
					
						commit
						eb80c25398
					
				| 
						 | 
				
			
			@ -28,6 +28,8 @@
 | 
			
		|||
#include "events/EventQueue.h"
 | 
			
		||||
#include "events/Event.h"
 | 
			
		||||
 | 
			
		||||
#include "events/mbed_shared_queues.h"
 | 
			
		||||
 | 
			
		||||
using namespace events;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,26 @@
 | 
			
		|||
{
 | 
			
		||||
    "name": "events",
 | 
			
		||||
    "config": {
 | 
			
		||||
        "present": 1
 | 
			
		||||
        "present": 1,
 | 
			
		||||
        "shared-stacksize": {
 | 
			
		||||
            "help": "Stack size (bytes) for shared event queue thread",
 | 
			
		||||
            "value": 1024
 | 
			
		||||
        },
 | 
			
		||||
        "shared-eventsize": {
 | 
			
		||||
            "help": "Event buffer size (bytes) for shared event queue",
 | 
			
		||||
            "value": 256
 | 
			
		||||
        },
 | 
			
		||||
        "shared-dispatch-from-application": {
 | 
			
		||||
            "help": "No thread created for shared event queue - application will call dispatch from another thread (eg dispatch_forever at end of main)",
 | 
			
		||||
            "value": false
 | 
			
		||||
        },
 | 
			
		||||
        "shared-highprio-stacksize": {
 | 
			
		||||
            "help": "Stack size (bytes) for shared high-priority event queue thread",
 | 
			
		||||
            "value": 1024
 | 
			
		||||
        },
 | 
			
		||||
        "shared-highprio-eventsize": {
 | 
			
		||||
            "help": "Event buffer size (bytes) for shared high-priority event queue",
 | 
			
		||||
            "value": 256
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
/* events
 | 
			
		||||
 * Copyright (c) 2017 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "events/mbed_shared_queues.h"
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
 | 
			
		||||
using namespace events;
 | 
			
		||||
 | 
			
		||||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
#ifdef MBED_CONF_RTOS_PRESENT
 | 
			
		||||
/* Create an event queue, and start the thread that dispatches it. Static
 | 
			
		||||
 * variables mean this happens once the first time each template instantiation
 | 
			
		||||
 * is called. This is currently instantiated no more than twice.
 | 
			
		||||
 */
 | 
			
		||||
template
 | 
			
		||||
<osPriority Priority, size_t QueueSize, size_t StackSize>
 | 
			
		||||
EventQueue *do_shared_event_queue_with_thread()
 | 
			
		||||
{
 | 
			
		||||
    static uint64_t queue_buffer[QueueSize / sizeof(uint64_t)];
 | 
			
		||||
    static EventQueue queue(sizeof queue_buffer, (unsigned char *) queue_buffer);
 | 
			
		||||
 | 
			
		||||
    static uint64_t stack[StackSize / sizeof(uint64_t)];
 | 
			
		||||
    static Thread thread(Priority, StackSize, (unsigned char *) stack);
 | 
			
		||||
 | 
			
		||||
    Thread::State state = thread.get_state();
 | 
			
		||||
    if (state == Thread::Inactive || state == Thread::Deleted) {
 | 
			
		||||
        osStatus status = thread.start(callback(&queue, &EventQueue::dispatch_forever));
 | 
			
		||||
        MBED_ASSERT(status == osOK);
 | 
			
		||||
        if (status != osOK) {
 | 
			
		||||
            return NULL;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return &queue;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
EventQueue *mbed_event_queue()
 | 
			
		||||
{
 | 
			
		||||
#if MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION || !defined MBED_CONF_RTOS_PRESENT
 | 
			
		||||
    /* Only create the EventQueue, but no dispatching thread */
 | 
			
		||||
    static unsigned char queue_buffer[MBED_CONF_EVENTS_SHARED_EVENTSIZE];
 | 
			
		||||
    static EventQueue queue(sizeof queue_buffer, queue_buffer);
 | 
			
		||||
 | 
			
		||||
    return &queue;
 | 
			
		||||
#else
 | 
			
		||||
    return do_shared_event_queue_with_thread<osPriorityNormal, MBED_CONF_EVENTS_SHARED_EVENTSIZE, MBED_CONF_EVENTS_SHARED_STACKSIZE>();
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef MBED_CONF_RTOS_PRESENT
 | 
			
		||||
EventQueue *mbed_highprio_event_queue()
 | 
			
		||||
{
 | 
			
		||||
    return do_shared_event_queue_with_thread<osPriorityHigh, MBED_CONF_EVENTS_SHARED_HIGHPRIO_EVENTSIZE, MBED_CONF_EVENTS_SHARED_HIGHPRIO_STACKSIZE>();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
 | 
			
		||||
/** \addtogroup events */
 | 
			
		||||
/** @{*/
 | 
			
		||||
/* events
 | 
			
		||||
 * Copyright (c) 2017 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef MBED_SHARED_QUEUES_H
 | 
			
		||||
#define MBED_SHARED_QUEUES_H
 | 
			
		||||
 | 
			
		||||
#include "events/EventQueue.h"
 | 
			
		||||
 | 
			
		||||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Return a pointer to an EventQueue, on which normal tasks can be queued.
 | 
			
		||||
 *
 | 
			
		||||
 * All calls to this return the same EventQueue - it and its dispatch thread
 | 
			
		||||
 * are created on the first call to this function. The dispatch thread
 | 
			
		||||
 * runs at default priority (currently osPriorityNormal).
 | 
			
		||||
 *
 | 
			
		||||
 * The EventQueue returned may be used to call() Events, or to chain() other
 | 
			
		||||
 * EventQueues so that they are run in the same context.
 | 
			
		||||
 *
 | 
			
		||||
 * Events (or chained EventQueues) executing on the normal event queue should
 | 
			
		||||
 * normally take less than 10ms to execute, to avoid starving other users. As
 | 
			
		||||
 * such, users can expect that event latency will typically be 10ms or less,
 | 
			
		||||
 * but could occasionally be significantly higher if many events are queued.
 | 
			
		||||
 *
 | 
			
		||||
 * If an RTOS is not present or the configuration option
 | 
			
		||||
 * `events.shared-dispatch-from-application` is set to true, then this
 | 
			
		||||
 * does not create a dedicated dispatch thread - instead the application is
 | 
			
		||||
 * expected to run the EventQueue's dispatch, eg from main. This is necessary
 | 
			
		||||
 * for the event loop to work without an RTOS, or an RTOS system can can save
 | 
			
		||||
 * memory by reusing the main stack.
 | 
			
		||||
 *
 | 
			
		||||
 * @return pointer to event queue
 | 
			
		||||
 */
 | 
			
		||||
events::EventQueue *mbed_event_queue();
 | 
			
		||||
 | 
			
		||||
#ifdef MBED_CONF_RTOS_PRESENT
 | 
			
		||||
/**
 | 
			
		||||
 * Return a pointer to an EventQueue, on which small high-priority tasks can
 | 
			
		||||
 * be queues, such as simple deferrals from interrupt.
 | 
			
		||||
 *
 | 
			
		||||
 * All calls to this return the same EventQueue - it and its thread are
 | 
			
		||||
 * created on the first call to this function. The dispatch thread
 | 
			
		||||
 * runs at a high priority (currently osPriorityHigh).
 | 
			
		||||
 *
 | 
			
		||||
 * The EventQueue returned may be used to call() Events, or to chain() other
 | 
			
		||||
 * EventQueues so that they are run in the same context.
 | 
			
		||||
 *
 | 
			
		||||
 * Events (or chained EventQueues) executing on the high-priority event queue
 | 
			
		||||
 * should normally take less than 100us to execute, to avoid starving other
 | 
			
		||||
 * users. As such, users can expect that event latency will typically be 100us
 | 
			
		||||
 * or less, but could occasionally be significantly higher if many events are
 | 
			
		||||
 * queued.
 | 
			
		||||
 *
 | 
			
		||||
 * @return pointer to high-priority event queue
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
events::EventQueue *mbed_highprio_event_queue();
 | 
			
		||||
 | 
			
		||||
#endif // MBED_CONF_RTOS_PRESENT
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @}*/
 | 
			
		||||
		Loading…
	
		Reference in New Issue