static PHB_TASKINFO hb_taskSwitchLock( PHB_TASKMTX pMutex ) { PHB_TASKINFO pTask = pMutex->lockers; if( pTask ) { pMutex->lockers = pTask->pBlockNext; #ifdef HB_TASK_DEBUG if( pTask->locking != pMutex ) hb_errInternal( HB_EI_ERRUNRECOV, "TaskSwitchLock: broken lock", NULL, NULL ); #endif pTask->locking = NULL; pTask->locked++; pMutex->task = pTask; pMutex->count = 1; if( pTask->state == TASK_SLEEPING ) { hb_taskWakeUp( pTask ); pTask->state = TASK_RUNNING; } else if( pTask->state != TASK_RUNNING ) hb_errInternal( HB_EI_ERRUNRECOV, "TaskSwitchLock: task resumed", NULL, NULL ); } return pTask; }
/* TODO: do not start task immediately */ void hb_taskResume( void * pTaskPtr ) { PHB_TASKINFO pTask = ( PHB_TASKINFO ) pTaskPtr, pCurrTask; if( s_currTask != pTask ) { pCurrTask = s_currTask; switch( pTask->state ) { #if ! defined( HB_HAS_UCONTEXT ) case TASK_INIT: /* save current execution context */ if( setjmp( s_currTask->context ) == 0 ) { s_currTask = pTask; hb_taskStart(); /* unreachable code */ } break; #endif case TASK_SLEEPING: hb_taskWakeUp( pTask ); /* no break */ #if defined( HB_HAS_UCONTEXT ) case TASK_INIT: #endif case TASK_SUSPEND: pTask->state = TASK_RUNNING; /* no break */ case TASK_RUNNING: #if defined( HB_HAS_UCONTEXT ) s_currTask = pTask; /* save current execution context and switch to the new one */ swapcontext( &pCurrTask->context, &pTask->context ); #else /* save current execution context */ if( setjmp( s_currTask->context ) == 0 ) { s_currTask = pTask; /* switch execution context */ longjmp( pTask->context, 1 ); /* unreachable code */ } #endif break; case TASK_DONE: break; case TASK_ZOMBIE: /* It should not happen - it's bug in user code */ hb_errInternal( HB_EI_ERRUNRECOV, "TaskResume: zombie", NULL, NULL ); /* default: hb_errInternal( HB_EI_ERRUNRECOV, "TaskResume: corrupt", NULL, NULL ); */ } } }
static void hb_taskFinalize( PHB_TASKINFO pTask ) { pTask->data = NULL; if( pTask->joiners ) { PHB_TASKINFO * pSleep = &s_taskSleep, pJoiner; while( *pSleep ) { if( ( *pSleep )->joining == pTask ) { pJoiner = *pSleep; pJoiner->joining = NULL; *pSleep = ( *pSleep )->pSleepNext; pJoiner->wakeup = 0; pJoiner->pSleepNext = s_taskSleep; s_taskSleep = pJoiner; if( --pTask->joiners == 0 ) break; } else pSleep = &( *pSleep )->pSleepNext; } #ifdef HB_TASK_DEBUG if( pTask->joiners ) hb_errInternal( HB_EI_ERRUNRECOV, "TaskFinalize: dummy joiners", NULL, NULL ); #endif } /* it cannot happen for runing threads */ /* remove from mutex lockers queue */ if( pTask->locking ) { PHB_TASKINFO * pLock = &pTask->locking->lockers; while( *pLock ) { if( *pLock == pTask ) { *pLock = pTask->pBlockNext; pTask->locking = NULL; break; } else pLock = &( *pLock )->pBlockNext; } #ifdef HB_TASK_DEBUG if( pTask->locking ) hb_errInternal( HB_EI_ERRUNRECOV, "TaskFinalize: dummy lock", NULL, NULL ); #endif } /* remove from condition queue */ if( pTask->waiting ) { PHB_TASKINFO * pWait = &pTask->waiting->waiters; while( *pWait ) { if( *pWait == pTask ) { *pWait = pTask->pWaitNext; pTask->waiting = NULL; break; } else pWait = &( *pWait )->pWaitNext; } #ifdef HB_TASK_DEBUG if( pTask->waiting ) hb_errInternal( HB_EI_ERRUNRECOV, "TaskFinalize: dummy cond", NULL, NULL ); #endif } if( pTask->state == TASK_SLEEPING ) hb_taskWakeUp( pTask ); pTask->state = TASK_DONE; if( pTask->locked ) { PHB_TASKMTX pMutex = s_mutexList; while( pMutex ) { if( pMutex->task == pTask && pMutex->count ) { pTask->locked--; pMutex->task = NULL; pMutex->count = 0; hb_taskSwitchLock( pMutex ); } pMutex = pMutex->next; } #ifdef HB_TASK_DEBUG if( pTask->locked ) hb_errInternal( HB_EI_ERRUNRECOV, "TaskFinalize: dummy lock", NULL, NULL ); #endif } if( pTask->detached ) { pTask->state = TASK_ZOMBIE; if( pTask == s_currTask ) { /* switch to next active task */ hb_taskYield(); /* unreachable code */ } else hb_taskFree( pTask ); } }