39 #ifndef DOXYGEN_INPROGRESS
41 #include <pip/pip_machdep.h>
44 #define PIP_SYNC_AUTO (0x0001U)
45 #define PIP_SYNC_BUSYWAIT (0x0002U)
46 #define PIP_SYNC_YIELD (0x0004U)
47 #define PIP_SYNC_BLOCKING (0x0008U)
49 #define PIP_SYNC_MASK (PIP_SYNC_AUTO | \
54 #define PIP_TASK_INACTIVE (0x01000U)
55 #define PIP_TASK_ACTIVE (0x02000U)
57 #define PIP_TASK_MASK \
58 (PIP_TASK_INACTIVE|PIP_TASK_ACTIVE)
60 #define PIP_TASK_ALL (-1)
62 #define PIP_YIELD_DEFAULT (0x0U)
63 #define PIP_YIELD_USER (0x1U)
64 #define PIP_YIELD_SYSTEM (0x2U)
66 #define PIP_ENV_SYNC "PIP_SYNC"
67 #define PIP_ENV_SYNC_AUTO "auto"
68 #define PIP_ENV_SYNC_BUSY "busy"
69 #define PIP_ENV_SYNC_BUSYWAIT "busywait"
70 #define PIP_ENV_SYNC_YIELD "yield"
71 #define PIP_ENV_SYNC_BLOCK "block"
72 #define PIP_ENV_SYNC_BLOCKING "blocking"
74 typedef struct pip_task {
75 struct pip_task *next;
76 struct pip_task *prev;
79 #define PIP_TASKQ_NEXT(L) (((pip_task_t*)(L))->next)
80 #define PIP_TASKQ_PREV(L) (((pip_task_t*)(L))->prev)
81 #define PIP_TASKQ_PREV_NEXT(L) (((pip_task_t*)(L))->prev->next)
82 #define PIP_TASKQ_NEXT_PREV(L) (((pip_task_t*)(L))->next->prev)
84 #define PIP_TASKQ_INIT(L) \
85 do { PIP_TASKQ_NEXT(L) = PIP_TASKQ_PREV(L) = \
86 (pip_task_t*)(L); } while(0)
88 #define PIP_TASKQ_ENQ_FIRST(L,E) \
89 do { PIP_TASKQ_NEXT(E) = PIP_TASKQ_NEXT(L); \
90 PIP_TASKQ_PREV(E) = (pip_taskt*)(L); \
91 PIP_TASKQ_NEXT_PREV(L) = (pip_task_t*)(E); \
92 PIP_TASKQ_NEXT(L) = (pip_task_t*)(E); } while(0)
94 #define PIP_TASKQ_ENQ_LAST(L,E) \
95 do { PIP_TASKQ_NEXT(E) = (pip_task_t*)(L); \
96 PIP_TASKQ_PREV(E) = PIP_TASKQ_PREV(L); \
97 PIP_TASKQ_PREV_NEXT(L) = (pip_task_t*)(E); \
98 PIP_TASKQ_PREV(L) = (pip_task_t*)(E); } while(0)
100 #define PIP_TASKQ_DEQ(E) \
101 do { PIP_TASKQ_NEXT_PREV(E) = PIP_TASKQ_PREV(E); \
102 PIP_TASKQ_PREV_NEXT(E) = PIP_TASKQ_NEXT(E); \
103 PIP_TASKQ_INIT(E); } while(0)
105 #define PIP_TASKQ_APPEND(P,Q) \
106 do { if( !PIP_TASKQ_ISEMPTY(Q) ) { \
107 PIP_TASKQ_NEXT_PREV(Q) = PIP_TASKQ_PREV(P); \
108 PIP_TASKQ_PREV_NEXT(Q) = (P); \
109 PIP_TASKQ_PREV_NEXT(P) = PIP_TASKQ_NEXT(Q); \
110 PIP_TASKQ_PREV(P) = PIP_TASKQ_PREV(Q); \
111 PIP_TASKQ_INIT(Q); } } while(0)
113 #define PIP_TASKQ_ISEMPTY(L) \
114 ( PIP_TASKQ_NEXT(L) == (L) && PIP_TASKQ_PREV(L) == (pip_task_t*)(L) )
116 #define PIP_TASKQ_FOREACH(L,E) \
117 for( (E)=PIP_TASKQ_NEXT(L); (pip_task_t*)(L)!=(E); \
118 (E)=PIP_TASKQ_NEXT(E) )
120 #define PIP_TASKQ_FOREACH_SAFE(L,E,TV) \
121 for( (E)=PIP_TASKQ_NEXT(L), (TV)=PIP_TASKQ_NEXT(E); \
122 (pip_task_t*)(L)!=(E); \
123 (E)=(TV), (TV)=PIP_TASKQ_NEXT(TV) )
125 #define PIP_TASKQ_MOVE(D,S) \
126 do { if( PIP_TASKQ_ISEMPTY(S) ) { \
129 (D)->next = (S)->next; \
130 (D)->prev = (S)->prev; \
131 PIP_TASKQ_INIT(S); } } while(0)
134 typedef pip_task_t pip_list_t;
137 #define PIP_LIST_INIT(L) PIP_TASKQ_INIT(L)
138 #define PIP_LIST_ISEMPTY(L) PIP_TASKQ_ISEMPTY(L)
139 #define PIP_LIST_ADD(L,E) PIP_TASKQ_ENQ_LAST(L,E)
140 #define PIP_LIST_DEL(E) PIP_TASKQ_DEQ(E)
141 #define PIP_LIST_FOREACH(L,E) PIP_TASKQ_FOREACH(L,E)
142 #define PIP_LIST_FOREACH_SAFE(L,E,F) PIP_TASKQ_FOREACH_SAFE(L,E,F)
143 #define PIP_LIST_MOVE(D,S) PIP_TASKQ_MOVE(D,S)
145 struct pip_task_queue_methods;
147 typedef struct pip_task_queue {
148 volatile pip_task_t queue;
149 struct pip_task_queue_methods *methods;
151 volatile uint32_t length;
155 typedef void(*pip_enqueue_callback_t)(
void*);
157 #define PIP_CB_UNLOCK_AFTER_ENQUEUE ((pip_enqueue_callback_t)1)
159 typedef int (*pip_task_queue_init_t) (
void*);
160 typedef void (*pip_task_queue_lock_t) (
void*);
161 typedef int (*pip_task_queue_trylock_t) (
void*);
162 typedef void (*pip_task_queue_unlock_t) (
void*);
163 typedef int (*pip_task_queue_isempty_t) (
void*);
164 typedef int (*pip_task_queue_count_t) (
void*,
int*);
165 typedef void (*pip_task_queue_enqueue_t) (
void*, pip_task_t*);
166 typedef pip_task_t *(*pip_task_queue_dequeue_t) (
void*);
167 typedef void (*pip_task_queue_describe_t) (
void*,FILE*);
168 typedef int (*pip_task_queue_fin_t) (
void*);
170 typedef struct pip_task_queue_methods {
171 pip_task_queue_init_t init;
172 pip_task_queue_lock_t lock;
173 pip_task_queue_trylock_t trylock;
174 pip_task_queue_unlock_t unlock;
175 pip_task_queue_isempty_t isempty;
176 pip_task_queue_count_t count;
177 pip_task_queue_enqueue_t enqueue;
178 pip_task_queue_dequeue_t dequeue;
179 pip_task_queue_fin_t fin;
180 pip_task_queue_describe_t describe;
181 } pip_task_queue_methods_t;
183 typedef struct pip_barrier {
184 pip_atomic_t count_init;
186 pip_task_queue_t queue;
189 typedef struct pip_mutex {
191 pip_task_queue_t queue;
194 #define PIP_QUEUE_TYPEDEF(N,B) \
196 pip_task_queue_t pip_queue; \
200 #define PIP_MUTEX_TYPEDEF(N,B) \
202 pip_mutex_t pip_mutex; \
206 #define PIP_BARTIER_TYPEDEF(N,B) \
208 pip_barrier_t pip_barrier; \
214 #ifdef DOXYGEN_INPROGRESS
220 #define INLINE inline static
224 #ifndef DOXYGEN_INPROGRESS
229 int pip_task_str(
char*,
size_t, pip_task_t* );
349 #ifdef DOXYGEN_INPROGRESS
355 pip_task_queue_t *queue,
356 pip_spawn_hook_t *hookp );
358 int pip_blt_spawn_( pip_spawn_program_t *progp,
363 pip_task_queue_t *queue,
364 pip_spawn_hook_t *hookp );
365 #define pip_blt_spawn( progp, coreno, opts, pipid, bltp, queue, hookp ) \
366 pip_blt_spawn_( (progp), (coreno), (opts), (pipid), (bltp), \
367 (pip_task_queue_t*) (queue), (hookp) )
459 #ifdef DOXYGEN_INPROGRESS
461 pip_task_queue_methods_t *methods );
463 INLINE
int pip_task_queue_init_( pip_task_queue_t *queue,
464 pip_task_queue_methods_t *methods ) {
465 if( queue == NULL )
return EINVAL;
466 queue->methods = methods;
467 if( methods == NULL || methods->init == NULL) {
468 PIP_TASKQ_INIT( &queue->queue );
469 pip_spin_init( &queue->lock );
470 queue->methods = NULL;
475 return methods->init( queue );
478 #define pip_task_queue_init( Q, M ) \
479 pip_task_queue_init_( (pip_task_queue_t*)(Q), (M) )
495 #ifdef DOXYGEN_INPROGRESS
498 INLINE
int pip_task_queue_trylock_( pip_task_queue_t *queue ) {
499 if( queue == NULL )
return EINVAL;
500 if( queue->methods == NULL || queue->methods->trylock == NULL ) {
501 return pip_spin_trylock( &queue->lock );
503 return queue->methods->trylock( (
void*) queue );
506 #define pip_task_queue_trylock( Q ) \
507 pip_task_queue_trylock_( (pip_task_queue_t*)(Q) )
523 #ifdef DOXYGEN_INPROGRESS
526 INLINE
void pip_task_queue_lock_( pip_task_queue_t *queue ) {
527 if( queue == NULL )
return;
528 if( queue->methods == NULL || queue->methods->lock == NULL ) {
529 while( !pip_spin_trylock( &queue->lock ) ) {
533 queue->methods->lock( queue );
536 #define pip_task_queue_lock( Q ) \
537 pip_task_queue_lock_( (pip_task_queue_t*)(Q) )
553 #ifdef DOXYGEN_INPROGRESS
556 INLINE
void pip_task_queue_unlock_( pip_task_queue_t *queue ) {
557 if( queue == NULL )
return;
558 if( queue->methods == NULL || queue->methods->unlock == NULL ) {
559 pip_spin_unlock( &queue->lock );
561 queue->methods->unlock( (
void*) queue );
564 #define pip_task_queue_unlock( Q ) \
565 pip_task_queue_unlock_( (pip_task_queue_t*)(Q) )
582 #ifdef DOXYGEN_INPROGRESS
585 INLINE
int pip_task_queue_isempty_( pip_task_queue_t *queue ) {
586 if( queue->methods == NULL || queue->methods->isempty == NULL ) {
587 return PIP_TASKQ_ISEMPTY( &queue->queue );
589 return queue->methods->isempty( (
void*) queue );
592 #define pip_task_queue_isempty( Q ) \
593 pip_task_queue_isempty_( (pip_task_queue_t*)(Q) )
612 #ifdef DOXYGEN_INPROGRESS
616 pip_task_queue_count_( pip_task_queue_t *queue,
int *np ) {
618 if( queue == NULL )
return EINVAL;
619 if( np == NULL )
return EINVAL;
620 if( queue->methods == NULL || queue->methods->count == NULL ) {
623 err = queue->methods->count( queue, np );
627 #define pip_task_queue_count( Q, NP ) \
628 pip_task_queue_count_( (pip_task_queue_t*)(Q), (NP) )
647 #ifdef DOXYGEN_INPROGRESS
651 pip_task_queue_enqueue_( pip_task_queue_t *queue, pip_task_t *task ) {
652 if( queue == NULL )
return;
653 if( queue->methods == NULL || queue->methods->enqueue == NULL ) {
654 PIP_TASKQ_ENQ_LAST( &queue->queue, task );
657 queue->methods->enqueue( (
void*) queue, task );
660 #define pip_task_queue_enqueue( Q, T ) \
661 pip_task_queue_enqueue_( (pip_task_queue_t*) (Q), (T) )
681 #ifdef DOXYGEN_INPROGRESS
685 pip_task_queue_dequeue_( pip_task_queue_t *queue ) {
686 if( queue == NULL )
return NULL;
687 if( queue->methods == NULL || queue->methods->dequeue == NULL ) {
689 if( PIP_TASKQ_ISEMPTY( &queue->queue ) )
return NULL;
690 first = PIP_TASKQ_NEXT( &queue->queue );
691 PIP_TASKQ_DEQ( first );
695 return queue->methods->dequeue( (
void*) queue );
698 #define pip_task_queue_dequeue( Q ) \
699 pip_task_queue_dequeue_( (pip_task_queue_t*) (Q) )
714 #ifdef DOXYGEN_INPROGRESS
718 pip_task_queue_describe_( pip_task_queue_t *queue,
char *tag, FILE *fp ) {
719 if( queue == NULL )
return;
720 if( queue->methods == NULL || queue->methods->describe == NULL ) {
721 if( PIP_TASKQ_ISEMPTY( &queue->queue ) ) {
722 fprintf( fp,
"%s: Queue is (EMPTY)\n", tag );
727 PIP_TASKQ_FOREACH( &queue->queue, task ) {
728 (void) pip_task_str( msg,
sizeof(msg), task );
729 fprintf( fp,
"%s: Queue[%d/%d]:%s\n", tag, i++, queue->length, msg );
733 queue->methods->describe( (
void*) queue, fp );
736 #define pip_task_queue_describe( Q, T, F ) \
737 pip_task_queue_describe_( (pip_task_queue_t*)(Q), (T), (F) )
753 #ifdef DOXYGEN_INPROGRESS
756 INLINE
int pip_task_queue_fin_( pip_task_queue_t *queue ) {
757 if( queue == NULL )
return EINVAL;
758 if( queue->methods == NULL || queue->methods->fin == NULL ) {
759 if( !PIP_TASKQ_ISEMPTY( &queue->queue ) )
return EBUSY;
762 return queue->methods->fin( (
void*) queue );
765 #define pip_task_queue_fin( Q ) \
766 pip_task_queue_fin_( (pip_task_queue_t*)(Q) )
813 #ifdef DOXYGEN_INPROGRESS
815 pip_enqueue_callback_t callback,
818 int pip_suspend_and_enqueue_( pip_task_queue_t *queue,
819 pip_enqueue_callback_t callback,
821 #define pip_suspend_and_enqueue( Q, C, A ) \
822 pip_suspend_and_enqueue_( (pip_task_queue_t*)(Q), (C), (A) )
855 #ifdef DOXYGEN_INPROGRESS
857 pip_enqueue_callback_t callback,
860 int pip_suspend_and_enqueue_nolock_( pip_task_queue_t *queue,
861 pip_enqueue_callback_t callback,
863 #define pip_suspend_and_enqueue_nolock( Q, C, A ) \
864 pip_suspend_and_enqueue_nolock_( (pip_task_queue_t*)(Q), (C), (A) )
888 #ifdef DOXYGEN_INPROGRESS
891 int pip_dequeue_and_resume_( pip_task_queue_t *queue, pip_task_t *sched );
892 #define pip_dequeue_and_resume( Q, S ) \
893 pip_dequeue_and_resume_( (pip_task_queue_t*)(Q), (S) )
923 #ifdef DOXYGEN_INPROGRESS
927 int pip_dequeue_and_resume_nolock_( pip_task_queue_t *queue,
929 #define pip_dequeue_and_resume_nolock( Q, S ) \
930 pip_dequeue_and_resume_nolock_( (pip_task_queue_t*)(Q), (S) )
968 #ifdef DOXYGEN_INPROGRESS
973 int pip_dequeue_and_resume_N_( pip_task_queue_t *queue,
976 #define pip_dequeue_and_resume_N( Q, S, N ) \
977 pip_dequeue_and_resume_N_( (pip_task_queue_t*)(Q), (S), (N) )
1013 #ifdef DOXYGEN_INPROGRESS
1018 int pip_dequeue_and_resume_N_nolock_( pip_task_queue_t *queue,
1019 pip_task_t *sched,
int *np );
1020 #define pip_dequeue_and_resume_N_nolock( Q, S, N ) \
1021 pip_dequeue_and_resume_N_nolock_( (pip_task_queue_t*)(Q), (S), (N) )
1138 #ifdef DOXYGEN_INPROGRESS
1141 int pip_barrier_init_( pip_barrier_t *barrp,
int n );
1142 #define pip_barrier_init( B, N ) \
1143 pip_barrier_init_( (pip_barrier_t*)(B), (N) )
1166 #ifdef DOXYGEN_INPROGRESS
1169 int pip_barrier_wait_( pip_barrier_t *barrp );
1170 #define pip_barrier_wait( B ) \
1171 pip_barrier_wait_( (pip_barrier_t*)(B) )
1194 #ifdef DOXYGEN_INPROGRESS
1197 int pip_barrier_fin_( pip_barrier_t *queue );
1198 #define pip_barrier_fin( B ) \
1199 pip_barrier_fin_( (pip_barrier_t*)(B) )
1232 #ifdef DOXYGEN_INPROGRESS
1235 int pip_mutex_init_( pip_mutex_t *mutex );
1236 #define pip_mutex_init( M ) \
1237 pip_mutex_init_( (pip_mutex_t*)(M) )
1259 #ifdef DOXYGEN_INPROGRESS
1262 int pip_mutex_lock_( pip_mutex_t *mutex );
1263 #define pip_mutex_lock( M ) \
1264 pip_mutex_lock_( (pip_mutex_t*)(M) )
1286 #ifdef DOXYGEN_INPROGRESS
1289 int pip_mutex_unlock_( pip_mutex_t *mutex );
1290 #define pip_mutex_unlock( M ) \
1291 pip_mutex_unlock_( (pip_mutex_t*)(M) )
1313 #ifdef DOXYGEN_INPROGRESS
1316 int pip_mutex_fin_( pip_mutex_t *mutex );
1317 #define pip_mutex_fin( M ) \
1318 pip_mutex_fin_( (pip_mutex_t*)(M) )
1370 #ifndef DOXYGEN_INPROGRESS
int pip_get_task_by_pipid(int pipid, pip_task_t **taskp)
get PiP task from PiP ID
int pip_mutex_fin(pip_mutex_t *mutex)
Finalize PiP mutex.
int pip_suspend_and_enqueue_nolock(pip_task_queue_t *queue, pip_enqueue_callback_t callback, void *cbarg)
suspend the curren task and enqueue it without locking the queue
void pip_task_queue_describe(pip_task_queue_t *queue, FILE *fp)
Describe queue.
int pip_mutex_init(pip_mutex_t *mutex)
Initialize PiP mutex.
int pip_couple(void)
Couple the curren task with the original kernel thread.
pip_task_t * pip_task_queue_dequeue(pip_task_queue_t *queue)
Dequeue a task from a task queue.
int pip_task_queue_count(pip_task_queue_t *queue, int *np)
Count the length of task queue.
int pip_get_task_pipid(pip_task_t *task, int *pipidp)
Return PIPID of a PiP task.
int pip_mutex_lock(pip_mutex_t *mutex)
Lock PiP mutex.
int pip_dequeue_and_resume_nolock(pip_task_queue_t *queue, pip_task_t *sched)
dequeue a task and make it runnable
int pip_dequeue_and_resume_N_nolock(pip_task_queue_t *queue, pip_task_t *sched, int *np)
dequeue tasks and resume the execution of them
int pip_task_queue_isempty(pip_task_queue_t *queue)
Query function if the current task has some tasks to be scheduled with.
int pip_mutex_unlock(pip_mutex_t *mutex)
Unlock PiP mutex.
int pip_dequeue_and_resume(pip_task_queue_t *queue, pip_task_t *sched)
dequeue a task and make it runnable
int pip_get_sched_domain(pip_task_t **domainp)
Return the task representing the scheduling domain.
int pip_barrier_wait(pip_barrier_t *barrp)
wait on barrier synchronization in a busy-wait way int pip_barrier_wait( pip_barrier_t *barrp ); ...
int pip_task_queue_init(pip_task_queue_t *queue, pip_task_queue_methods_t *methods)
Initialize task queue.
void pip_task_queue_enqueue(pip_task_queue_t *queue, pip_task_t *task)
Enqueue a BLT.
int pip_suspend_and_enqueue(pip_task_queue_t *queue, pip_enqueue_callback_t callback, void *cbarg)
suspend the curren task and enqueue it with lock
int pip_dequeue_and_resume_N(pip_task_queue_t *queue, pip_task_t *sched, int *np)
dequeue multiple tasks and resume the execution of them
int pip_decouple(pip_task_t *task)
Decouple the curren task from the kernel thread.
int pip_blt_spawn(pip_spawn_program_t *progp, uint32_t coreno, uint32_t opts, int *pipidp, pip_task_t **bltp, pip_task_queue_t *queue, pip_spawn_hook_t *hookp)
spawn a PiP BLT/ULP (Bi-Level Task / User-Level Process)
int pip_yield(int flag)
Yield.
pip_task_t * pip_task_self(void)
Return the current task.
int pip_barrier_fin(pip_barrier_t *barrp)
finalize barrier synchronization structure
int pip_barrier_init(pip_barrier_t *barrp, int n)
initialize barrier synchronization structure
void pip_task_queue_unlock(pip_task_queue_t *queue)
Unlock task queue.
int pip_task_queue_fin(pip_task_queue_t *queue)
Finalize a task queue.
int pip_task_queue_trylock(pip_task_queue_t *queue)
Try locking task queue.
int pip_yield_to(pip_task_t *task)
Yield to the specified PiP task.
void pip_task_queue_lock(pip_task_queue_t *queue)
Lock task queue.