Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

Crash and semaphores

Altera_Forum
Honored Contributor II
1,743 Views

Hi, 

 

when I make three tasks synchronized by semaphores (the tasks do nothing, they only make a Post and then a Pend to pass the control each other), after a number of iterations (this number is ever the same) the program is blocked. If I put a delay after the Pend, the number of iterations grew, but after this number of iterations the program crash. Why?? 

 

Thanks
0 Kudos
15 Replies
Altera_Forum
Honored Contributor II
1,020 Views

Nobody had the same problem? I don't understand why the program crashes, it make nothing, there are only three tasks and each launches the other between semaphores: task A launches task B that launches task C that launches task A, and so on. After 107 iterations, the program crashes!

0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

could you post your code?

0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

Thank you for the interesting. 

The code is: 

 

#include "includes.h" 

#include <iostream> 

 

 

using namespace std; 

 

 

#define OS_TASK_STAT_EN 1 

#define OS_MAX_TASKS 8 

 

#define TASK_STK_SIZE 1024 

 

 

 

OS_STK TaskStartStk[TASK_STK_SIZE]; 

OS_STK TaskStartStk1[TASK_STK_SIZE]; 

OS_STK TaskStartStk2[TASK_STK_SIZE]; 

OS_STK TaskStartStk3[TASK_STK_SIZE]; 

 

 

OS_EVENT* sem_sync0; 

OS_EVENT* sem_sync1; 

OS_EVENT* sem_sync2; 

OS_EVENT* sem_sync3; 

 

 

void handle_sync(void* pdata) { 

 

INT8U err_sync3; 

 

pdata = pdata; 

 

for(;;) {  

 

cout << "I'm in handle_sync" << endl; 

fflush(0); 

 

OSSemPost(sem_sync1); 

OSSemPend(sem_sync3, 0, &err_sync3);  

 

 

void processing(void* pdata) { 

 

INT8U err_sync1;  

 

pdata = pdata; 

 

for(;;) {  

 

cout << "I'm in processing" << endl; 

fflush(0); 

 

OSSemPost(sem_sync2);  

OSSemPend(sem_sync1, 0, &err_sync1);  

 

 

void monitoring(void* pdata) { 

 

INT8U err_sync2; 

 

pdata = pdata; 

 

for(;;) { 

 

cout << "I'm in monitoring" << endl; 

fflush(0); 

 

OSSemPost(sem_sync3);  

OSSemPend(sem_sync2, 0, &err_sync2);  

 

 

 

static void TaskStartCreateTask(void) { 

 

cout << "I'm in TaskStartCreateTask" << endl;  

fflush(0); 

 

 

OSTaskCreate(handle_sync, (void*) 0, &TaskStartStk1 [TASK_STK_SIZE - 1], 11);  

 

OSTaskCreate(processing, (void*) 0, &TaskStartStk2[TASK_STK_SIZE - 1], 12);  

 

OSTaskCreate(monitoring, (void*) 0, &TaskStartStk3[TASK_STK_SIZE - 1], 15); 

 

 

 

void TaskStart(void* pdata) {  

 

INT8U err_sync0; 

 

cout << "I'm in TaskStart" << endl;  

fflush(0); 

 

pdata = pdata; 

 

OSStatInit(); 

 

 

OSTaskCreate(handle_sync, (void*) 0, &TaskStartStk1[TASK_STK_SIZE - 1], 11); 

 

 

OSTaskCreate(processing, (void*) 0, &TaskStartStk2[TASK_STK_SIZE - 1], 6); 

 

 

OSTaskCreate(monitoring, (void*) 0, &TaskStartStk3[TASK_STK_SIZE - 1], 15); 

 

 

for(;;) {  

OSSemPost(sem_sync3); 

OSSemPend(sem_sync0, 0, &err_sync0);  

 

 

int main() 

OSInit(); 

 

sem_sync0 = OSSemCreate(0); 

sem_sync1 = OSSemCreate(0); 

sem_sync2 = OSSemCreate(0); 

sem_sync3 = OSSemCreate(0); 

 

cout << "I'm in the main" << endl;  

fflush(0); 

 

 

OSTaskCreate(TaskStart, (void*) 0, &TaskStartStk[TASK_STK_SIZE - 1], 18); 

 

 

OSStart(); 

 

0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

I'm pretty sure the standard output drivers aren't thread safe, so if you write from several threads at the same time you can crash. It's better either to only print out from one task, or use something else, such as leds, to monitor the threads activities.

0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

Thanks for the answer, but now, because hardware's problems, I can't verify if your idea is right.

0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

If I put the semaphore in this way: 

 

OSSemPend(sem); 

cout << "Hello world" << endl; 

OSSemPost(sem, 0, err); 

 

does it become thread safe? 

 

Thanks
0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

Yes, as long as you do that in every thread that uses the standard output, and that you use the same semaphore on each, obviously. 

I re-read your code and I'm wondering something... where do you post your semaphore sem_sync0 ? 

What are you trying to achieve in this code?
0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

I don't post sem_sync0 because I want that TaskStart creates the other tasks and stops: sem_sync0 never becomes 1, then TaskStart never runs, only at the beginning. But I don' think that this is the problem, because the same problem is verified when the three tasks are created in the main and not in TaskStart, i.e. when there isn't the thread TaskStart. 

Thanks
0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

A task can kill itself with OsTaskDel(OS_PRIO_SELF); 

After this call the task will be deleted. 

Did you see any improvement by using this semaphore to make the standard output thread safe?
0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

Unfortunately now I've not the hardware, and then I can't try if it runs. According to you, with the semaphores to make the cout thread safe, must it function?

0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

It should work, yes

0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

Hi Italian, 

I know that this post is a bit old, but if you didn't already solved your problem I have a suggest for you. I took a look to your code and I saw the call to OSInit() function: :evil: you don't have to call it because it is already called within alt_main() function that is called before your main()! If you do it, that function initialize os structure, included semaphre, mailbox, queue, etc... If you call it a second time after one in alt_main() you will re-assign all previously initialized semaphore (e.g. uart one, jtag one, etc)!!! 

 

Ciao
0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

 

--- Quote Start ---  

Hi Italian, 

I know that this post is a bit old, but if you didn't already solved your problem I have a suggest for you. I took a look to your code and I saw the call to OSInit() function: :evil: you don't have to call it because it is already called within alt_main() function that is called before your main()! If you do it, that function initialize os structure, included semaphre, mailbox, queue, etc... If you call it a second time after one in alt_main() you will re-assign all previously initialized semaphore (e.g. uart one, jtag one, etc)!!! 

 

Ciao 

--- Quote End ---  

 

 

Ho letto solo ora il tuo post, grazie per la risposta. Il problema l'ho risolto cambiando strategia di programmazione: un solo loop infinito senza sistema operativo. Però mi interessa capire il perché del malfunzionamento. Ho chiamato OSInit() perché ho seguito le indicazioni del libro su MicroC/OS-II. Dici che è già chiamata dentro alt_main()? Ma cos'è questa alt_main()? 

Grazie 

Ciao
0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

alt_main() is the first C code called from the assembler startup code, it initialises things like stdin and stdout, then calls the uses's main().

0 Kudos
Altera_Forum
Honored Contributor II
1,020 Views

Moreover alt_sys_init() also instantiate and init all device you foreseen in your pld (e.g. ALTERA_AVALON_UART_INSTANCE and ALTERA_AVALON_UART_INIT); this has the consequence that isr function for uart is anyway linked and included in your firmware also if you provide another one written by yourself.  

 

alt_sys_init() function is in your source file named as alt_sys_init().c and you can find it within syslib folder or bsp folder. 

 

Ciao
0 Kudos
Reply