Lines Matching full:this
21 * The embedded OS only sees one of this thread executing at a time.
24 * instance of this module, and nct_clean_up() once it desires to destroy it.
26 * For SOCs with several micro-controllers (AMP) one instance of this module
54 * This implementation is meant to be portable in between fully compatible
57 * An index in this table is used to identify threads in the IF to the
97 int thread_idx; /* Index of this element in the threads_table*/
100 bool running; /* Is this the currently running thread */
129 static void nct_exit_and_cleanup(struct te_status_t *this);
130 static struct threads_table_el *ttable_get_element(struct te_status_t *this, int index);
135 static void abort_tail(struct te_status_t *this, int this_th_nbr) in abort_tail() argument
137 struct threads_table_el *tt_el = ttable_get_element(this, this_th_nbr); in abort_tail()
146 nct_exit_and_cleanup(this); in abort_tail()
150 * Helper function to block this thread until it is allowed again
152 * Note that we go out of this function (the while loop below)
153 * with the mutex locked by this particular thread.
157 static void nct_wait_until_allowed(struct te_status_t *this, int this_th_nbr) in nct_wait_until_allowed() argument
159 struct threads_table_el *tt_el = ttable_get_element(this, this_th_nbr); in nct_wait_until_allowed()
168 while (this_th_nbr != this->currently_allowed_thread) { in nct_wait_until_allowed()
169 pthread_cond_wait(&this->cond_threads, &this->mtx_threads); in nct_wait_until_allowed()
172 abort_tail(this, this_th_nbr); in nct_wait_until_allowed()
189 static void nct_let_run(struct te_status_t *this, int next_allowed_th) in nct_let_run() argument
192 struct threads_table_el *tt_el = ttable_get_element(this, next_allowed_th); in nct_let_run()
200 this->currently_allowed_thread = next_allowed_th; in nct_let_run()
209 NSI_SAFE_CALL(pthread_cond_broadcast(&this->cond_threads)); in nct_let_run()
215 static void nct_exit_and_cleanup(struct te_status_t *this) in nct_exit_and_cleanup() argument
220 NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_threads)); in nct_exit_and_cleanup()
229 * Let the ready thread run and block this managed thread until it is allowed again
231 * The hosted OS shall call this when it has decided to swap in/out two of its threads,
235 * managed by this nct instance, it will behave like nct_first_thread_start(),
240 * this_arg: Pointer to this thread emulator instance as returned by nct_init()
245 struct te_status_t *this = (struct te_status_t *)this_arg; in nct_swap_threads() local
246 int this_th_nbr = this->currently_allowed_thread; in nct_swap_threads()
248 nct_let_run(this, next_allowed_thread_nbr); in nct_swap_threads()
250 if (this_th_nbr == -1) { /* This is the first time a thread was swapped in */ in nct_swap_threads()
253 nct_exit_and_cleanup(this); in nct_swap_threads()
256 struct threads_table_el *tt_el = ttable_get_element(this, this_th_nbr); in nct_swap_threads()
263 abort_tail(this, this_th_nbr); in nct_swap_threads()
265 nct_wait_until_allowed(this, this_th_nbr); in nct_swap_threads()
270 * Let the very first hosted thread run, and exit this thread.
272 * The hosted OS shall call this when it has decided to swap in into another
276 * This function allows to emulate a hosted OS doing its first swapping into one
282 struct te_status_t *this = (struct te_status_t *)this_arg; in nct_first_thread_start() local
284 nct_let_run(this, next_allowed_thread_nbr); in nct_first_thread_start()
287 nct_exit_and_cleanup(this); in nct_first_thread_start()
296 struct te_status_t *this = element->ts_status; in nct_cleanup_handler() local
299 * If we are not terminating, this is just an aborted thread, in nct_cleanup_handler()
305 if (!this->terminate) { in nct_cleanup_handler()
314 NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_threads)); in nct_cleanup_handler()
323 * this thread.
328 struct te_status_t *this = tt_el->ts_status; in nct_thread_starter() local
341 NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_threads)); in nct_thread_starter()
344 * The program may have been finished before this thread ever got to run in nct_thread_starter()
347 if (!this->threads_table || this->terminate) { in nct_thread_starter()
364 nct_wait_until_allowed(this, thread_idx); in nct_thread_starter()
366 this->fptr(tt_el->payload); in nct_thread_starter()
369 * We only reach this point if the thread actually returns which should in nct_thread_starter()
387 static struct threads_table_el *ttable_get_element(struct te_status_t *this, int index) in ttable_get_element() argument
389 struct threads_table_el *threads_table = this->threads_table; in ttable_get_element()
391 if (index >= this->threads_table_size) { /* LCOV_EXCL_BR_LINE */ in ttable_get_element()
394 index, this->threads_table_size); /* LCOV_EXCL_LINE */ in ttable_get_element()
406 static int ttable_get_empty_slot(struct te_status_t *this) in ttable_get_empty_slot() argument
408 struct threads_table_el *tt_el = this->threads_table; in ttable_get_empty_slot()
410 for (int i = 0; i < this->threads_table_size; i++, tt_el = tt_el->next) { in ttable_get_empty_slot()
431 tt_el = ttable_get_element(this, this->threads_table_size-1); in ttable_get_empty_slot()
434 this->threads_table_size += NCT_ALLOC_CHUNK_SIZE; in ttable_get_empty_slot()
443 return this->threads_table_size - NCT_ALLOC_CHUNK_SIZE; in ttable_get_empty_slot()
450 * to refer to this thread for future calls to the thread emulator.
457 * (or nct_first_thread_start()) is called with this newly created
462 struct te_status_t *this = (struct te_status_t *)this_arg; in nct_new_thread() local
466 t_slot = ttable_get_empty_slot(this); in nct_new_thread()
467 tt_el = ttable_get_element(this, t_slot); in nct_new_thread()
471 tt_el->thead_cnt = this->thread_create_count++; in nct_new_thread()
473 tt_el->ts_status = this; in nct_new_thread()
494 * This pointer shall be passed to all subsequent calls of the
495 * threading emulator when interacting with this particular instance.
503 struct te_status_t *this; in nct_init() local
506 * Note: This (and the calloc below) won't be free'd by this code in nct_init()
508 * This is a conscious choice, see nct_clean_up() for more info. in nct_init()
512 this = calloc(1, sizeof(struct te_status_t)); in nct_init()
513 if (this == NULL) { /* LCOV_EXCL_BR_LINE */ in nct_init()
517 this->fptr = fptr; in nct_init()
518 this->thread_create_count = 0; in nct_init()
519 this->currently_allowed_thread = -1; in nct_init()
521 NSI_SAFE_CALL(pthread_cond_init(&this->cond_threads, NULL)); in nct_init()
522 NSI_SAFE_CALL(pthread_mutex_init(&this->mtx_threads, NULL)); in nct_init()
524 this->threads_table = calloc(NCT_ALLOC_CHUNK_SIZE, in nct_init()
526 if (this->threads_table == NULL) { /* LCOV_EXCL_BR_LINE */ in nct_init()
530 this->threads_table_size = NCT_ALLOC_CHUNK_SIZE; in nct_init()
533 this->threads_table[i].next = &this->threads_table[i+1]; in nct_init()
535 this->threads_table[NCT_ALLOC_CHUNK_SIZE - 1].next = NULL; in nct_init()
537 NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_threads)); in nct_init()
539 return (void *)this; in nct_init()
544 * Note that this function cannot be called from a SW thread
547 * Note: This function cannot guarantee the threads will be cancelled before the HW
550 * convoluted cases; as a call to this function can come due to a hosted OS
557 struct te_status_t *this = (struct te_status_t *)this_arg; in nct_clean_up() local
559 if (!this || !this->threads_table) { /* LCOV_EXCL_BR_LINE */ in nct_clean_up()
563 this->terminate = true; in nct_clean_up()
566 struct threads_table_el *tt_el = this->threads_table; in nct_clean_up()
568 for (int i = 0; i < this->threads_table_size; i++, tt_el = tt_el->next) { in nct_clean_up()
583 * This is the cleanup we do not do: in nct_clean_up()
585 * free(this->threads_table); in nct_clean_up()
587 * this->threads_table = NULL; in nct_clean_up()
589 * (void)pthread_cond_destroy(&this->cond_threads); in nct_clean_up()
590 * (void)pthread_mutex_destroy(&this->mtx_threads); in nct_clean_up()
592 * free(this); in nct_clean_up()
598 * Mark a thread as being aborted. This will result in the underlying pthread
609 struct te_status_t *this = (struct te_status_t *)this_arg; in nct_abort_thread() local
610 struct threads_table_el *tt_el = ttable_get_element(this, thread_idx); in nct_abort_thread()
612 if (thread_idx == this->currently_allowed_thread) { in nct_abort_thread()
639 * Return a unique thread identifier for this thread for this
640 * run. This identifier is only meant for debug purposes
646 struct te_status_t *this = (struct te_status_t *)this_arg; in nct_get_unique_thread_id() local
647 struct threads_table_el *tt_el = ttable_get_element(this, thread_idx); in nct_get_unique_thread_id()
654 struct te_status_t *this = (struct te_status_t *)this_arg; in nct_thread_name_set() local
655 struct threads_table_el *tt_el = ttable_get_element(this, thread_idx); in nct_thread_name_set()
665 * This condition will only be triggered in very unlikely cases
674 * This emulator normally keeps only 1 thread executing at a time.
680 * Only when the hosted kernel attempts to swap to a new thread does this
688 * In this unlikely cases the initialization or cleanup of the thread follows
690 * This code paths are there to ensure things work always, no matter
708 * In this, the cancelled thread cleanup overtakes the pthread_cancel() code, and frees the
713 * Therefore we do not do this, to avoid this very rare crashes.