Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
19 years ago

Error in the NIOS port?

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)

1 Reply

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

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