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
Collaboratore onorario II
1.861Visualizzazioni

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 Risposte
Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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!

Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

could you post your code?

Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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(); 

 

Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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.

Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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

Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

If I put the semaphore in this way: 

 

OSSemPend(sem); 

cout << "Hello world" << endl; 

OSSemPost(sem, 0, err); 

 

does it become thread safe? 

 

Thanks
Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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?
Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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
Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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?
Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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?

Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

It should work, yes

Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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
Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

 

--- 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
Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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().

Altera_Forum
Collaboratore onorario II
1.138Visualizzazioni

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
Rispondere