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++

Error in the NIOS port?

Altera_Forum
Honored Contributor II
1,082 Views

I have found what I think is an error in the malloc_lock-routine protecting the heap in the NIOS port of the µC/OS-II system. 

 

If you are using the technique of priority inheritance, implemented in the µC/OS-II the system could go into a deadlocked state due to an error in the malloc_lock: 

 

The system has several threads, and they use a shared mutex with priority to access a shared resource. The different threads have different (low) priority, and the mutex is created with a unique (high) priority as well: 

 

Thread A Priority 62 

Thread B Priority 61 

G_mutex = OSMutexCreate( 2, g_err ) 

 

When the thread with the lowest priority (A) owns the g_mutex, and another thread _B_ with a higher priority tries to get access to the mutex, the priority of the first thread is “boosted” to the priority of the in order to finish the work. Now thread A runs with priority 2. 

 

The error occurs if Thread A have accessed the malloc-function before getting the priority boosted, and then access the malloc-function again (recursively), i.e. through the realloc(). Thread A will now go trough the following code (from the nios-port: alt_malloc_lock.c): 

 

 

/* use our priority as a task id */ 

 

err = OSTaskQuery( OS_PRIO_SELF, &tcb ); 

if (err != OS_NO_ERR) 

return; 

 

id = tcb.OSTCBPrio; 

 

/* see if we own the heap already */ 

 

OSSemQuery( alt_heapsem, &semdata ); 

 

if( !semdata.OSCnt && id == lockid ) // id == 2, lockid == 62  

/* we do; just count the recursion */ 

 

locks++; 

else  

/* wait on the other task to yield the heap, then claim ownership of it */ 

 

OSSemPend( alt_heapsem, 0, &err ); 

locks = 1; 

lockid = id; 

 

 

The if statement checks whether the thread already has the heap, but this check fails, since Thread A had priority 62 when it originally claimed the heap, and has now been boosted to priority 2. 

 

This results in a deadlock in the system, since thread A is waiting to gain access to a semaphore that can only be released by thread A. And thread B waits to gain access to g_mutex that can only be released by thread A witch is waiting…. 

 

 

I know that release 5.1 of the NIOS IDE fixed a previous problem with the realloc mechanism, but it seems there is still a problem. 

 

A possible fix could be to check on the task-id, and set the variable lockid=taskID instead of using the task priority as ID.  

(The Task-ID is set by using the OSTaskCreateExt(), NOTE id MUST be uinique)
0 Kudos
1 Reply
Altera_Forum
Honored Contributor II
322 Views

Each time a description of the change, there is always plenty to talk about around the world. They are not exempt. A statement usually is: "i have to change almost immediately versions, so do not expect me to date continue to attack ...

0 Kudos
Reply