/* * ======== GateMutexPri_Instance_finalize ======== */ Void GateMutexPri_Instance_finalize(GateMutexPri_Object *obj) { Queue_Handle pendQ; pendQ = GateMutexPri_Instance_State_pendQ(obj); Queue_destruct(Queue_struct(pendQ)); }
/* * ======== Semaphore_Instance_finalize ======== */ Void Semaphore_Instance_finalize(Semaphore_Object *sem) { Queue_Handle pendQ; pendQ = Semaphore_Instance_State_pendQ(sem); Queue_destruct(Queue_struct(pendQ)); if (Semaphore_supportsEvents && (sem->event != NULL)) { Semaphore_eventSync(sem->event, sem->eventId, 0); } }
/* * ======== pthread_exit ======== */ void pthread_exit(void *retval) { pthread_Obj *thread = (pthread_Obj *)pthread_self(); /* * This function terminates the calling thread and returns * a value via retval that (if the thread is joinable) is available to * another thread that calls pthread_join(). * * Any clean-up handlers that have not yet been popped, are popped * (in the reverse of the order in which they were pushed) and executed. */ thread->ret = retval; /* * Don't bother disabling the Task scheduler while the thread * is exiting. It will be up to the application to not make * such calls as pthread_cancel() or pthread_detach() while the * thread is exiting. */ /* Pop and execute the cleanup handlers */ while (thread->cleanupList != NULL) { _pthread_cleanup_pop(thread->cleanupList, 1); } /* Cleanup any pthread specific data */ _pthread_removeThreadKeys((pthread_t)thread); if (!thread->detached) { Semaphore_post(Semaphore_handle(&(thread->joinSem))); /* Set this task's priority to -1 to stop it from running. */ Task_setPri(thread->task, -1); } else { /* Free memory */ #if ti_sysbios_posix_Settings_supportsMutexPriority__D Queue_destruct(&(thread->mutexList)); #endif Semaphore_destruct(&(thread->joinSem)); Memory_free(Task_Object_heap(), thread, sizeof(pthread_Obj)); /* * Don't call Task_delete on the calling thread. Task_exit() * will put the task on the terminated queue, and if * Task_deleteTerminatedTasks is TRUE, the task will be cleaned * up automatically. */ Task_exit(); } }
/* * ======== GIO_Instance_finalize ======== */ Void GIO_Instance_finalize(GIO_Object *obj, Int status) { Queue_Handle freeList; SyncSemThread_Handle sync; IOM_Fxns *iomFxns; iomFxns = (IOM_Fxns *)obj->fxns; /* fall through in switch below is intentional */ switch (status) { case 0: /* GIO_delete() */ if (obj->submitCount > 0) { GIO_flush(obj); } iomFxns->mdDeleteChan(obj->mdChan); /* OK to fall through */ case 4: /* mdCreateChan failed */ /* OK to fall through */ case 3: /* name not found */ Memory_free(NULL, obj->packets, sizeof(IOM_Packet) * obj->numPackets); /* OK to fall through */ case 2: /* alloc packets failed */ freeList = GIO_Instance_State_freeList(obj); Queue_destruct(Queue_struct(freeList)); if (obj->userSync == FALSE) { sync = SyncSemThread_Handle_downCast(obj->sync); SyncSemThread_delete(&sync); } /* OK to fall through */ case 1: /* Sync_create failed */ /* OK to fall through */ default: break; } }
/* * ======== pthread_cancel ======== * The specification of this API is that it be used as a means for one thread * to termintate the execution of another thread. There is no mention of * returning an error if the argument, pthread, is the same thread as the * calling thread. */ int pthread_cancel(pthread_t pthread) { pthread_Obj *thread = (pthread_Obj *)pthread; UInt key; /* * Cancel the thread. Only asynchronous cancellation is supported, * since functions that would normally be cancellation points (eg, * printf()), are not cancellation points for BIOS. */ key = Task_disable(); /* Indicate that cancellation is requested. */ thread->cancelPending = 1; if (thread->cancelState == PTHREAD_CANCEL_ENABLE) { /* Set this task's priority to -1 to stop it from running. */ Task_setPri(thread->task, -1); Task_restore(key); /* Pop and execute the cleanup handlers */ while (thread->cleanupList != NULL) { _pthread_cleanup_pop(thread->cleanupList, 1); } /* Cleanup any pthread specific data */ _pthread_removeThreadKeys(pthread); if (thread->detached) { /* Free memory */ #if ti_sysbios_posix_Settings_supportsMutexPriority__D Queue_destruct(&(thread->mutexList)); #endif Semaphore_destruct(&(thread->joinSem)); Task_delete(&(thread->task)); Memory_free(Task_Object_heap(), thread, sizeof(pthread_Obj)); } else { /* pthread_join() will clean up. */ thread->ret = PTHREAD_CANCELED; Semaphore_post(Semaphore_handle(&(thread->joinSem))); } } else { Task_restore(key); } return (0); }
/* * ======== _pthread_runStub ======== */ static void _pthread_runStub(UArg arg0, UArg arg1) { UInt key; Ptr arg; pthread_Obj *thread = (pthread_Obj *)(xdc_uargToPtr(arg1)); arg = Task_getEnv(thread->task); thread->ret = thread->fxn(arg); /* Pop and execute the cleanup handlers */ while (thread->cleanupList != NULL) { _pthread_cleanup_pop(thread->cleanupList, 1); } /* Cleanup any pthread specific data */ _pthread_removeThreadKeys((pthread_t)thread); key = Task_disable(); if (!thread->detached) { Semaphore_post(Semaphore_handle(&(thread->joinSem))); /* * Set this task's priority to -1 to prevent it from being put * on the terminated queue (and deleted if Task.deleteTerminatedTasks * is true). pthread_join() will delete the Task object. */ Task_setPri(thread->task, -1); Task_restore(key); } else { Task_restore(key); /* Free memory */ #if ti_sysbios_posix_Settings_supportsMutexPriority__D Queue_destruct(&(thread->mutexList)); #endif Semaphore_destruct(&(thread->joinSem)); Memory_free(Task_Object_heap(), thread, sizeof(pthread_Obj)); /* The system will have to clean up the Task object */ } /* Task_exit() is called when returning from this function */ }
/* * ======== pthread_join ======== * Wait for thread to terminate. * * If multiple threads simultaneously try to join with the same * thread, the results are undefined. We will return an error. * * If the thread calling pthread_join() is canceled, then the target * thread will remain joinable (i.e., it will not be detached). */ int pthread_join(pthread_t pthread, void **thread_return) { pthread_Obj *thread = (pthread_Obj *)pthread; UInt key; key = Task_disable(); if ((thread->joinThread != NULL) || (thread->detached != 0)) { /* * Error - Another thread has already called pthread_join() * for this thread, or the thread is in the detached state. */ Task_restore(key); return (EINVAL); } if (pthread == pthread_self()) { Task_restore(key); return (EDEADLK); } /* * Allow pthread_join() to be called from a BIOS Task. If we * set joinThread to pthread_self(), we could get NULL if the * Task arg1 is 0. All we need is a non-NULL value for joinThread. */ thread->joinThread = Task_self(); Task_restore(key); Semaphore_pend(Semaphore_handle(&(thread->joinSem)), BIOS_WAIT_FOREVER); if (thread_return) { *thread_return = thread->ret; } #if ti_sysbios_posix_Settings_supportsMutexPriority__D Queue_destruct(&(thread->mutexList)); #endif Semaphore_destruct(&(thread->joinSem)); Task_delete(&(thread->task)); Memory_free(Task_Object_heap(), thread, sizeof(pthread_Obj)); return (0); }
/* * ======== pthread_create ======== */ int pthread_create(pthread_t *newthread, const pthread_attr_t *attr, void *(*startroutine)(void *), void *arg) { Semaphore_Params semParams; Task_Params taskParams; pthread_Obj *thread = NULL; Error_Block eb; pthread_attr_t *pAttr; Error_init(&eb); Task_Params_init(&taskParams); *newthread = NULL; thread = (pthread_Obj *)Memory_alloc(Task_Object_heap(), sizeof(pthread_Obj), 0, &eb); if (thread == NULL) { return (ENOMEM); } pAttr = (attr == NULL) ? &defaultPthreadAttrs : (pthread_attr_t *)attr; taskParams.priority = pAttr->priority; taskParams.stack = pAttr->stack; taskParams.stackSize = pAttr->stacksize + pAttr->guardsize; /* Save the function in arg0 for ROV */ taskParams.arg0 = (UArg)startroutine; taskParams.arg1 = (UArg)thread; taskParams.env = arg; taskParams.priority = -1; thread->detached = (pAttr->detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : 1; thread->fxn = startroutine; thread->joinThread = NULL; thread->cancelState = PTHREAD_CANCEL_ENABLE; thread->cancelPending = 0; thread->priority = pAttr->priority; thread->cleanupList = NULL; #if ti_sysbios_posix_Settings_supportsMutexPriority__D thread->blockedMutex = NULL; Queue_elemClear((Queue_Elem *)thread); Queue_construct(&(thread->mutexList), NULL); #endif Semaphore_Params_init(&semParams); semParams.mode = Semaphore_Mode_BINARY; Semaphore_construct(&(thread->joinSem), 0, &semParams); thread->task = Task_create((Task_FuncPtr)_pthread_runStub, &taskParams, &eb); if (thread->task == NULL) { Semaphore_destruct(&(thread->joinSem)); #if ti_sysbios_posix_Settings_supportsMutexPriority__D Queue_destruct(&(thread->mutexList)); #endif Memory_free(Task_Object_heap(), thread, sizeof(pthread_Obj)); return (ENOMEM); } *newthread = (pthread_t)thread; Task_setPri(thread->task, pAttr->priority); return (0); }