IntrOS
Loading...
Searching...
No Matches
ostask.h
1/******************************************************************************
2
3 @file IntrOS: ostask.h
4 @author Rajmund Szymanski
5 @date 18.11.2025
6 @brief This file contains definitions for IntrOS.
7
8 ******************************************************************************
9
10 Copyright (c) 2018-2022 Rajmund Szymanski. All rights reserved.
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to
14 deal in the Software without restriction, including without limitation the
15 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 sell copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 IN THE SOFTWARE.
29
30 ******************************************************************************/
31
32#ifndef __INTROS_TSK_H
33#define __INTROS_TSK_H
34
35#include "oskernel.h"
36#include "osclock.h"
37
43
44/* -------------------------------------------------------------------------- */
45
47#define STK_SIZE( size ) \
48 ALIGNED_SIZE((size_t)( size ) + (OS_GUARD_SIZE), sizeof(stk_t))
49
50#define STK_OVER( size ) \
51 ALIGNED((size_t)( size ) + (OS_GUARD_SIZE), sizeof(stk_t))
52
53#define STK_CROP( base, size ) \
54 LIMITED((size_t)( base ) + (size_t)( size ), sizeof(stk_t))
55
59
60struct __tsk
61{
62 obj_t obj;
63 hdr_t hdr;
64
65 fun_t * proc;
66 void * arg;
67 cnt_t start;
68 cnt_t delay;
69 cnt_t period;
70
71 stk_t * stack;
72 size_t size;
73
74 tsk_t ** guard;
75 int event;
76
77 struct {
78 mtx_t * list;
79 } mtx;
80
81 union {
82
83 struct {
84 unsigned event;
85 } evt;
86
87 struct {
88 unsigned sigset;
89 unsigned signo;
90 } sig;
91
92 struct {
93 unsigned flags;
94 unsigned mode;
95 } flg;
96
97 struct {
98 void * data;
99 } lst;
100
101 struct {
102 union {
103 const
104 char * out;
105 char * in;
106 } data;
107 size_t size;
108 } raw;
109
110 struct {
111 union {
112 const
113 char * out;
114 char * in;
115 } data;
116 size_t size;
117 } msg;
118
119 struct {
120 union {
121 const
122 void * out;
123 void * in;
124 } data;
125 } box;
126
127 struct {
128 unsigned event;
129 } evq;
130
131 struct {
132 fun_t * fun;
133 } job;
134
135 } tmp;
136
137 union {
138 ctx_t reg;
139 jmp_buf buf;
140 } ctx;
141};
142
143typedef struct __tsk tsk_id [];
144
145/******************************************************************************
146 *
147 * Name : _TSK_INIT
148 *
149 * Description : create and initialize a task object
150 *
151 * Parameters
152 * proc : task proc (initial task function) doesn't have to be noreturn-type
153 * it will be executed into an infinite system-implemented loop
154 * stack : base of task's private stack storage
155 * size : size of task private stack (in bytes)
156 *
157 * Return : task object
158 *
159 * Note : for internal use
160 *
161 ******************************************************************************/
162
163#define _TSK_INIT( _proc, _stack, _size ) \
164 { _OBJ_INIT(), _HDR_INIT(), _proc, NULL, 0, 0, 0, _stack, _size, \
165 NULL, 0, { NULL }, { { 0 } }, { _CTX_INIT() } }
166
167/******************************************************************************
168 *
169 * Name : _TSK_STACK
170 *
171 * Description : create task's private stack storage
172 *
173 * Parameters
174 * size : size of task's private stack storage (in bytes)
175 *
176 * Return : base of task's private stack storage
177 *
178 * Note : for internal use
179 *
180 ******************************************************************************/
181
182#ifndef __cplusplus
183#define _TSK_STACK( _size ) (stk_t [STK_SIZE( _size )]) { 0 }
184#endif
185
186/******************************************************************************
187 *
188 * Name : _VA_STK
189 *
190 * Description : calculate stack size from optional parameter
191 *
192 * Note : for internal use
193 *
194 ******************************************************************************/
195
196#define _VA_STK( _size ) ((_size + 0) ? (_size + 0) : (OS_STACK_SIZE))
197
205#define OS_TSK_STACK( stk, ... ) \
206 stk_t stk[ STK_SIZE( _VA_STK(__VA_ARGS__) ) ] __STKALIGN
207
208/** static alias of OS_TSK_STACK() */
209#define static_TSK_STACK( stk, ... ) \
210 static stk_t stk[ STK_SIZE( _VA_STK(__VA_ARGS__) ) ] __STKALIGN
211
221#define OS_WRK( tsk, proc, size ) \
222 static stk_t tsk##__stk[STK_SIZE( size )] __STKALIGN; \
223 tsk_t tsk[] = { _TSK_INIT( proc, tsk##__stk, STK_OVER( size ) ) }
224
225/** static alias of OS_WRK() */
226#define static_WRK( tsk, proc, size ) \
227 static stk_t tsk##__stk[STK_SIZE( size )] __STKALIGN; \
228 static tsk_t tsk[] = { _TSK_INIT( proc, tsk##__stk, STK_OVER( size ) ) }
229
239#define OS_TSK( tsk, proc, ... ) \
240 OS_WRK( tsk, proc, _VA_STK(__VA_ARGS__) )
241
242/** static alias of OS_TSK() */
243#define static_TSK( tsk, proc, ... ) \
244 static_WRK( tsk, proc, _VA_STK(__VA_ARGS__) )
245
255#define OS_WRK_DEF( tsk, size ) \
256 static void tsk##__fun( void ); \
257 OS_WRK( tsk, tsk##__fun, size ); \
258 void tsk##__fun( void )
259
260/** static alias of OS_WRK_DEF() */
261#define static_WRK_DEF( tsk, size ) \
262 static void tsk##__fun( void ); \
263 static_WRK( tsk, tsk##__fun, size ); \
264 static void tsk##__fun( void )
265
275#define OS_TSK_DEF( tsk, ... ) \
276 OS_WRK_DEF( tsk, _VA_STK(__VA_ARGS__) )
277
278/** static alias of OS_TSK_DEF() */
279#define static_TSK_DEF( tsk, ... ) \
280 static_WRK_DEF( tsk, _VA_STK(__VA_ARGS__) )
281
292
293#ifdef __CONSTRUCTOR
294#define OS_WRK_START( tsk, size ) \
295 static void tsk##__fun( void ); \
296 OS_WRK( tsk, tsk##__fun, size ); \
297 __CONSTRUCTOR static void tsk##__run( void ) { tsk_start(tsk); } \
298 static void tsk##__fun( void )
299#endif
300
301#ifdef __CONSTRUCTOR
302/** static alias of OS_WRK_START() */
303#define static_WRK_START( tsk, size ) \
304 static void tsk##__fun( void ); \
305 static_WRK( tsk, tsk##__fun, size ); \
306 __CONSTRUCTOR static void tsk##__run( void ) { tsk_start(tsk); } \
307 static void tsk##__fun( void )
308#endif
309
320
321#ifdef __CONSTRUCTOR
322#define OS_TSK_START( tsk, ... ) \
323 OS_WRK_START( tsk, _VA_STK(__VA_ARGS__) )
324#endif
325
326#ifdef __CONSTRUCTOR
327/** static alias of OS_TSK_START() */
328#define static_TSK_START( tsk, ... ) \
329 static_WRK_START( tsk, _VA_STK(__VA_ARGS__) )
330#endif
331
343
344#ifndef __cplusplus
345#define WRK_INIT( proc, size ) \
346 _TSK_INIT( proc, _TSK_STACK( size ), STK_OVER( size ) )
347#endif
348
360
361#ifndef __cplusplus
362#define WRK_CREATE( proc, size ) \
363 { WRK_INIT ( proc, size ) }
364/** alias of WRK_CREATE() */
365#define WRK_NEW \
366 WRK_CREATE
367#endif
368
380
381#ifndef __cplusplus
382#define TSK_INIT( proc, ... ) \
383 WRK_INIT( proc, _VA_STK(__VA_ARGS__) )
384#endif
385
397
398#ifndef __cplusplus
399#define TSK_CREATE( proc, ... ) \
400 WRK_CREATE( proc, _VA_STK(__VA_ARGS__) )
401/** alias of TSK_CREATE() */
402#define TSK_NEW \
403 TSK_CREATE
404#endif
405
406#ifdef __cplusplus
407extern "C" {
408#endif
409
415
416__STATIC_INLINE
417tsk_t *tsk_this( void ) { return System.cur; }
418
420__STATIC_INLINE
421tsk_t *cur_task( void ) { return System.cur; }
422
424#define SELF ( System.cur )
425
438void wrk_init( tsk_t *tsk, fun_t *proc, stk_t *stack, size_t size );
439
451void tsk_init( tsk_t *tsk, fun_t *proc, stk_t *stack, size_t size );
452
459void tsk_start( tsk_t *tsk );
460
469void tsk_startFrom( tsk_t *tsk, fun_t *proc );
470
479void tsk_startWith( tsk_t *tsk, fun_a *proc, void *arg );
480
486
487__NO_RETURN
488void tsk_stop( void );
489
491__STATIC_INLINE
492void tsk_exit( void ) { tsk_stop(); }
493
508void tsk_reset( tsk_t *tsk );
509
511__STATIC_INLINE
512void tsk_kill( tsk_t *tsk ) { tsk_reset(tsk); }
513
517
518__STATIC_INLINE
519void tsk_yield( void ) { core_ctx_switch(); }
520
522__STATIC_INLINE
523void tsk_pass ( void ) { core_ctx_switch(); }
524
532
533__NO_RETURN
534void tsk_flip( fun_t *proc );
535
544void tsk_sleepFor( cnt_t delay );
545
547__STATIC_INLINE
548void tsk_delay( cnt_t delay ) { tsk_sleepFor(delay); }
549
560void tsk_sleepNext( cnt_t delay );
561
569void tsk_sleepUntil( cnt_t time );
570
576
577__STATIC_INLINE
578void tsk_sleep( void ) { tsk_sleepFor(INFINITE); }
579
593int tsk_suspend( tsk_t *tsk );
594
606int tsk_resume( tsk_t *tsk );
607
614
615__STATIC_INLINE
616size_t tsk_stackSpace( void )
617{
618#ifdef DEBUG
619 assert_tsk_context();
620 return core_stk_space(System.cur);
621#else
622 return 0;
623#endif
624}
625
626#ifdef __cplusplus
627}
628#endif
629
630/* -------------------------------------------------------------------------- */
631
632#if defined(__cplusplus)
633namespace intros {
634
635/******************************************************************************
636 *
637 * Class : baseStack
638 *
639 * Description : create base class for stack storage object
640 *
641 * Constructor parameters
642 * size : size of stack (in bytes)
643 *
644 * Note : for internal use
645 *
646 ******************************************************************************/
647
648template<size_t size_>
649struct baseStack
650{
651 static_assert(size_>0, "incorrect stack size");
652#if __cplusplus >= 201703L && !defined(__ICCARM__)
653 stk_t stack_[STK_SIZE(size_)] __STKALIGN;
654#else
655 stk_t stack_[STK_SIZE(size_)];
656#endif
657};
658
659/******************************************************************************
660 *
661 * Class : baseTask
662 *
663 * Description : create and initialize base class for task objects
664 *
665 * Constructor parameters
666 * proc : task proc (initial task function) doesn't have to be noreturn-type
667 * it will be executed into an infinite system-implemented loop
668 * stack : base of task's private stack storage
669 * size : size of task private stack (in bytes)
670 *
671 * Note : for internal use
672 *
673 ******************************************************************************/
674
675struct baseTask : public __tsk
676{
677#if __cplusplus >= 201402L
678 template<class F>
679 baseTask( F&& _proc, stk_t * const _stack, const size_t _size ): __tsk _TSK_INIT(fun_, _stack, _size), fun{_proc} {}
680#else
681 baseTask( fun_t *_proc, stk_t * const _stack, const size_t _size ): __tsk _TSK_INIT(_proc, _stack, _size) {}
682#endif
683
684 void start () { tsk_start (this); }
685#if __cplusplus >= 201402L
686 template<class F>
687 void startFrom( F&& _proc )
688 {
689 if (__tsk::hdr.id == ID_STOPPED) // active tasks cannot be started
690 {
691 fun = Fun_t(_proc);
692 tsk_startFrom(this, fun_);
693 }
694 }
695#else
696 void startFrom( fun_t * _proc ) { tsk_startFrom(this, _proc); }
697#endif
698 void reset () { tsk_reset (this); }
699 void kill () { tsk_kill (this); }
700 int suspend () { return tsk_suspend (this); }
701 int resume () { return tsk_resume (this); }
702 explicit
703 operator bool () const { return __tsk::hdr.id != ID_STOPPED; }
704
705 template<class T = baseTask> static
706 T * current () { return static_cast<T *>(tsk_this()); }
707
708#if __cplusplus >= 201402L
709 static
710 void fun_ () { current()->fun(); }
711 Fun_t fun;
712#endif
713
717
718 struct Current
719 {
720 static
721 void stop () { tsk_stop (); }
722 static
723 void exit () { tsk_exit (); }
724 static
725 void reset () { tsk_reset (current()); }
726 static
727 void kill () { tsk_kill (current()); }
728 static
729 void yield () { tsk_yield (); }
730 static
731 void pass () { tsk_pass (); }
732#if __cplusplus >= 201402L
733 template<class F> static
734 void flip ( F&& _proc ) { current()->fun = Fun_t(_proc);
735 tsk_flip (fun_); }
736#else
737 static
738 void flip ( fun_t * _proc ) { tsk_flip (_proc); }
739#endif
740 template<typename T> static
741 void sleepFor ( const T& _delay ) { tsk_sleepFor (Clock::count(_delay)); }
742 template<typename T> static
743 void sleepNext ( const T& _delay ) { tsk_sleepNext (Clock::count(_delay)); }
744 template<typename T> static
745 void sleepUntil( const T& _time ) { tsk_sleepUntil(Clock::until(_time)); }
746 static
747 void sleep () { tsk_sleep (); }
748 template<typename T> static
749 void delay ( const T& _delay ) { tsk_delay (Clock::count(_delay)); }
750 static
751 void suspend () { tsk_suspend (current()); }
752 };
753};
754
755using thisTask = baseTask::Current;
756using this_task = baseTask::Current;
757
766
767template<size_t size_>
768struct TaskT : public baseTask, public baseStack<size_>
769{
771 template<class F>
772 TaskT( F&& _proc ):
773 baseTask{_proc, baseStack<size_>::stack_, sizeof(baseStack<size_>::stack_)} {}
774
775#if __cplusplus >= 202002L
777 template<typename F, typename... A>
778 TaskT( F&& _proc, A&&... _args ):
779 TaskT<size_>{[proc = std::forward<F>(_proc), ...args = std::forward<A>(_args)]() mutable
780 { std::invoke(std::move(proc), std::unwrap_reference_t<A>(std::move(args))...); }} {}
781#else
782#if __cplusplus >= 201402L
784 template<typename F, typename... A>
785 TaskT( F&& _proc, A&&... _args ):
786 TaskT<size_>{std::bind(std::forward<F>(_proc), std::forward<A>(_args)...)} {}
787#endif
788#endif
789
790 ~TaskT() { assert(__tsk::hdr.id == ID_STOPPED); }
791
792#if __cplusplus >= 201402L
793 /// move constructor
794 TaskT( TaskT<size_>&& _src ):
795 baseTask{_src.fun, baseStack<size_>::stack_, sizeof(baseStack<size_>::stack_)}
796#else
798 TaskT( TaskT<size_>&& _src ):
799 baseTask{_src.proc, baseStack<size_>::stack_, sizeof(baseStack<size_>::stack_)}
800#endif
801 {
802 assert(_src.hdr.id == ID_STOPPED); // obj.queue of a task is only the link in the queue it waited in
803 (void) _src;
804 }
805
806 TaskT( const TaskT<size_>& ) = delete;
807 TaskT<size_>& operator=( TaskT<size_>&& ) = delete;
808 TaskT<size_>& operator=( const TaskT<size_>& ) = delete;
809
810private:
811 struct Starter {}; // Start functions return the task started in place: a started task must not be moved
812 template<typename... A>
813 TaskT( Starter, A&&... _args ): TaskT<size_>{static_cast<A&&>(_args)...} { this->start(); }
814public:
815
827
828 template<class F> static
829 TaskT<size_> Make( F&& _proc )
830 {
831 return { _proc };
832 }
833
834#if __cplusplus >= 201402L
836 template<typename F, typename... A> static
837 TaskT<size_> Make( F&& _proc, A&&... _args )
838 {
839 return { std::forward<F>(_proc), std::forward<A>(_args)... };
840 }
841#endif
842
854
855 template<class F> static
856 TaskT<size_> Start( F&& _proc )
857 {
858 return { Starter{}, _proc };
859 }
860
861#if __cplusplus >= 201402L
863 template<typename F, typename... A> static
864 TaskT<size_> Start( F&& _proc, A&&... _args )
865 {
866 return { Starter{}, std::forward<F>(_proc), std::forward<A>(_args)... };
867 }
868#endif
869};
870
876
877using Task = TaskT<OS_STACK_SIZE>;
878
879} // namespace
880#endif//__cplusplus
881
882/* -------------------------------------------------------------------------- */
883
885
886#endif//__INTROS_TSK_H
void fun_a(void *)
timer/task procedure with argument
Definition osbase.h:143
#define INFINITE
infinite waiting
Definition osbase.h:250
void fun_t(void)
timer/task procedure
Definition osbase.h:142
char data[]
message data
Definition osmessagequeue.h:54
void tsk_startWith(tsk_t *tsk, fun_a *proc, void *arg)
start previously defined/created/stopped task object
void tsk_exit(void)
alias of tsk_stop()
Definition ostask.h:491
void tsk_start(tsk_t *tsk)
start previously defined/created/stopped task object
void tsk_reset(tsk_t *tsk)
stop execution of given task
int tsk_suspend(tsk_t *tsk)
delay indefinitely execution of given task
void tsk_flip(fun_t *proc)
restart current task with the new proc (task function)
void tsk_sleep(void)
delay indefinitely execution of current task
Definition ostask.h:577
void tsk_yield(void)
yield system control to the next task
Definition ostask.h:518
void tsk_sleepUntil(cnt_t time)
delay execution of current task until given timepoint
void tsk_init(tsk_t *tsk, fun_t *proc, stk_t *stack, size_t size)
initialize complete work area for task object and start the task, if proc != NULL
void tsk_delay(cnt_t delay)
alias of tsk_sleepFor()
Definition ostask.h:547
size_t tsk_stackSpace(void)
chack water mark of the stack of the current task
Definition ostask.h:615
tsk_t * cur_task(void)
alias of tsk_this()
Definition ostask.h:420
void wrk_init(tsk_t *tsk, fun_t *proc, stk_t *stack, size_t size)
initialize complete work area for task object
void tsk_pass(void)
alias of tsk_yield()
Definition ostask.h:522
void tsk_stop(void)
stop execution of current task
void tsk_sleepFor(cnt_t delay)
delay execution of current task for given duration of time
void tsk_startFrom(tsk_t *tsk, fun_t *proc)
start previously defined/created/stopped task object
int tsk_resume(tsk_t *tsk)
resume execution of given suspended task
tsk_t * tsk_this(void)
return current task object
Definition ostask.h:416
void tsk_kill(tsk_t *tsk)
alias of tsk_reset()
Definition ostask.h:511
void tsk_sleepNext(cnt_t delay)
delay execution of current task for given duration of time
#define STK_SIZE(size)
size of the task stack in stk_t units: the size in bytes (rounded up) with the guard area
Definition ostask.h:47
static constexpr rep until(const std::chrono::time_point< Clock, _Duration > &_time)
time point in ticks, rounded up to whole ticks (only a time point of this clock)
Definition osclock.h:109
static constexpr rep count(const std::chrono::duration< _Rep, _Period > &_delay)
delay in ticks, rounded up to whole ticks; negative delay: IMMEDIATE, delay out of range: INFINITE
Definition osclock.h:102
create and initialize complete work area for task object
Definition ostask.h:768
static TaskT< size_ > Start(F &&_proc)
Definition ostask.h:855
static TaskT< size_ > Make(F &&_proc)
Definition ostask.h:828
TaskT(F &&_proc)
constructor, see the constructor parameters of the class
Definition ostask.h:771