#include "libepc.h" #include "os_cpu.h" #include "os_cfg.h" #include "ucos_ii.h" #include #define STACK_SIZE 1000 #define THREADS 2 /* No more than 6 */ #define RESOURCES 2 /* No more than 8 */ typedef enum { DORMANT = 0, PENDING = 1, READY = 2, RUNNING = 3, SLEEPING= 4 } THREAD_STATE ; extern void AcquireResources(int, int) ; extern void ReleaseResources(int, int) ; BOOL Acquire1Resource(int, int) ; void Release1Resource(int, int) ; PRIVATE void Analyze(void) ; PRIVATE OS_STK * CreateStack(void) ; PRIVATE BOOL Deadlock(int) ; PRIVATE void Monitor() ; PRIVATE void Thread() ; PRIVATE OS_EVENT * semaphore[RESOURCES] ; PRIVATE THREAD_STATE thread_state[THREADS] ; PRIVATE BOOL pending[THREADS][RESOURCES] ; PRIVATE BOOL acquired[THREADS][RESOURCES] ; PRIVATE BOOL waiting[THREADS][THREADS] ; PRIVATE unsigned executions[THREADS] ; int main() { int resource, priority ; srandom((int) CPU_Clock_Cycles()) ; ClearScreen(0x07) ; SetCursorVisible(FALSE) ; OSInit() ; for (resource = 0; resource < RESOURCES; resource++) { semaphore[resource] = OSSemCreate(1) ; } for (priority = 0; priority < THREADS; priority++) { OSTaskCreate(Thread, NULL, CreateStack(), priority) ; } OSTaskCreate(Monitor, NULL, CreateStack(), priority) ; OSStart() ; return 0 ; } BOOL Acquire1Resource(int thread, int resource) { if (!acquired[thread][resource]) { BYTE8 err ; OSSemPend(semaphore[resource], 1, &err) ; OSTimeDly(random() % 50) ; if (err != OS_NO_ERR) { pending[thread][resource] = TRUE ; thread_state[thread] = PENDING ; return FALSE ; } acquired[thread][resource] = TRUE ; pending[thread][resource] = FALSE ; return TRUE ; } return FALSE ; } void Release1Resource(int thread, int resource) { OSSemPost(semaphore[resource]) ; acquired[thread][resource] = FALSE ; } PRIVATE void Thread(void) { static int threads = 0 ; int thread = threads++ ; executions[thread] = 0 ; for (;;) { DWORD32 timer ; thread_state[thread] = SLEEPING ; OSTimeDly(random() % 1000) ; AcquireResources(thread, RESOURCES) ; thread_state[thread] = RUNNING ; /* Simulate doing some work for up to 1 sec */ timer = OSTimeGet() + (random() % 1000) ; while (OSTimeGet() < timer) OSTimeDly(1) ; ReleaseResources(thread, RESOURCES) ; ++executions[thread] ; } } PRIVATE void Analyze(void) { int t1, t2, r ; memset(waiting, FALSE, sizeof(waiting)) ; for (r = 0; r < RESOURCES; r++) { for (t2 = 0; t2 < THREADS; t2++) { if (!acquired[t2][r]) continue ; for (t1 = 0; t1 < THREADS; t1++) { if (!pending[t1][r]) continue ; waiting[t1][t2] = TRUE ; } break ; } } } PRIVATE BOOL Deadlock(int thread) { int t1, t2, cycles ; if (thread_state[thread] != PENDING) return FALSE ; t1 = thread ; for (cycles = 0; cycles < THREADS; cycles++) { for (t2 = 0; t2 < THREADS; t2++) { if (waiting[t1][t2]) break ; } if (t2 == THREADS) return FALSE ; if (t2 == thread) break ; t1 = t2 ; } return TRUE ; } PRIVATE void Monitor(void) { # define THREAD_SPACING 10 int thread, resource, row, col, row1, col1 ; SetCursorPosition(24, 35) ; PutString("Updates: ") ; row1 = (25 - (6 + 2 * RESOURCES)) / 2 ; col1 = (80 - (13 + THREAD_SPACING * THREADS)) / 2 ; row = row1 ; col = col1 + 14 ; for (thread = 0; thread < THREADS; thread++) { SetCursorPosition(row1, col) ; PutString("Thread ") ; PutUnsigned(thread + 1, 10, 0) ; col += THREAD_SPACING ; } SetCursorPosition(row += 2, col1) ; PutString("Executions:") ; SetCursorPosition(row += 2, col1) ; PutString(" State:") ; for (resource = 0; resource < RESOURCES; resource++) { SetCursorPosition(row += 2, col1) ; PutString("Resource ") ; PutUnsigned(resource + 1, 10, 0) ; PutString(":") ; } for (;;) { static unsigned counter = 0 ; static char *states[] = { "DORMANT ", "PENDING ", "READY ", "RUNNING ", "SLEEPING" } ; OSSchedLock() ; SetCursorPosition(24, 44) ; PutUnsigned(++counter, 10, 0) ; row = row1 + 2 ; col = col1 + 18 ; for (thread = 0; thread < THREADS; thread++) { SetCursorPosition(row, col) ; PutUnsigned(executions[thread], 10, 0) ; col += THREAD_SPACING ; } row += 2 ; col = col1 + 15 ; Analyze() ; for (thread = 0; thread < THREADS; thread++) { SetCursorPosition(row, col) ; if (Deadlock(thread)) PutString("DEADLOCK") ; else PutString(states[thread_state[thread]]) ; col += THREAD_SPACING ; } for (resource = 0; resource < RESOURCES; resource++) { row += 2 ; col = col1 + 15 ; for (thread = 0; thread < THREADS; thread++) { SetCursorPosition(row, col) ; if (acquired[thread][resource]) PutString("ACQUIRED") ; else if (pending[thread][resource]) PutString("PENDING ") ; else PutString(" ") ; col += THREAD_SPACING ; } } OSSchedUnlock() ; OSTimeDly(50) ; } } PRIVATE OS_STK *CreateStack(void) { OS_STK *top = (OS_STK *) malloc(STACK_SIZE) + STACK_SIZE ; if (!top) for (;;) ; return top ; }