⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pthreadlib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* pthreadLib.c - POSIX 1003.1c thread library interfaces *//* Copyright 1984-2001 Wind River Systems, Inc.  *//* Copyright (c) 1995 by Dot4, Inc. */#include "copyright_wrs.h"/*modification history--------------------01i,03may02,gls  updated pthread_attr_setstackaddr documentaion (SPR #76769)01h,22apr02,gls  removed references to AE (SPR #75799)01g,05nov01,gls  merged in code from AE01f,24oct01,jgn  correct scheduling policy inheritance (SPR #71125)		 (docs update - main change in _pthreadLib.c)01e,04apr01,pfl  doc update (SPR #63976)01d,11sep00,jgn  split into user and system level components (SPR #33375)01c,22aug00,jgn  remove dependency on TCB spare4 field (SPR #33815) +		 fix some memory handling & memory leaks (SPR #33554) +		 move readdir_r() to dirLib.c (SPR #34056)01b,15aug00,jgn  add bug fixes from DOT-401a,17jul00,jgn  created from DOT-4 version 1.17*//*DESCRIPTIONThis library provides an implementation of POSIX 1003.1c threads for VxWorks.This provides an increased level of compatibility between VxWorks applicationsand those written for other operating systems that support the POSIX threadsmodel (often called <pthreads>).VxWorks is a task based operating system, rather than one implementing theprocess model in the POSIX sense. As a result of this, there are a fewrestrictions in the implementation, but in general, since tasks are roughlyequivalent to threads, the <pthreads> support maps well onto VxWorks.The restrictions are explained in more detail in the following paragraphs.CONFIGURATIONTo add POSIX threads support to a system, the component INCLUDE_POSIX_PTHREADSmust be added.Threads support also requires the POSIX scheduler to be included (seeschedPxLib for more detail). THREADSA thread is essentially a VxWorks task, with some additional characteristics.The first is detachability, where the creator of a thread can optionally blockuntil the thread exits. The second is cancelability, where one task or threadcan cause a thread to exit, possibly calling cleanup handlers. The next isprivate data, where data private to a thread is created, accessed and deletedvia keys. Each thread has a unique ID. A thread's ID is different than it'sVxWorks task ID.MUTEXESIncluded with the POSIX threads facility is a mutual exclusion facility, or<mutex>. These are functionally similar to the VxWorks mutex semaphores (see'semMLib' for more detail), and in fact are implemented using a VxWorksmutex semaphore. The advantage they offer, like all of the POSIX libraries,is the ability to run software designed for POSIX platforms under VxWorks.There are two types of locking protocols available, PTHREAD_PRIO_INHERIT andPTHREAD_PRIO_PROTECT. PTHREAD_PRIO_INHERIT maps to a semaphore create withSEM_PRIO_INHERIT set (see 'semMCreate' for more detail). A thread locking amutex created with its protocol attribute set to PTHREAD_PRIO_PROTECT has itspriority elevated to that of of the prioceiling attribute of the mutex. Whenthe mutex is unlocked, the priority of the calling thread is restored to itsprevious value.CONDITION VARIABLESCondition variables are another synchronization mechanism that is includedin the POSIX threads library. A condition variable allows threadsto block until some condition is met. There are really only two basicoperations that a condition variable can be involved in: waiting andsignalling. Condition variables are always associated with a mutex.A thread can wait for a condition to become true by taking the mutex andthen calling pthread_cond_wait(). That function will release the mutex andwait for the condition to be signalled by another thread. When the conditionis signalled, the function will re-acquire the mutex and return to the caller.Condition variable support two types of signalling: single thread wake-up usingpthread_cond_signal(), and multiple thread wake-up usingpthread_cond_broadcast(). The latter of these will unblock all threads thatwere waiting on the specified condition variable.It should be noted that condition variable signals are not related to POSIXsignals. In fact, they are implemented using VxWorks semaphores.RESOURCE COMPETITIONAll tasks, and therefore all POSIX threads, compete for CPU time together. Forthat reason the contention scope thread attribute is always'PTHREAD_SCOPE_SYSTEM'.NO VXWORKS EQUIVALENTSince there is no notion of a process (in the POSIX sense), there is nonotion of sharing of locks (mutexes) and condition variables between processes.As a result, the POSIX symbol '_POSIX_THREAD_PROCESS_SHARED' is not defined inthis implementation, and the routines pthread_condattr_getpshared(),pthread_condattr_setpshared(), pthread_mutexattr_getpshared() are notimplemented.Also, since there are no processes in VxWorks, fork(), wait(), andpthread_atfork() are unimplemented.VxWorks does not have password, user, or group databases, therefore there areno implementations of getlogin(), getgrgid(), getpwnam(), getpwuid(),getlogin_r(), getgrgid_r(), getpwnam_r(),  and getpwuid_r().SCHEDULINGThe default scheduling policy for a created thread is inherited from the systemsetting at the time of creation.Scheduling policies under VxWorks are global; they are not set per-thread,as the POSIX model describes. As a result, the <pthread> scheduling routines,as well as the POSIX scheduling routines native to VxWorks, do not allow youto change the scheduling policy. Under VxWorks you may set the schedulingpolicy in a thread, but if it does not match the system's scheduling policy,an error is returned.The detailed explanation for why this error occurs is a bit convoluted:technically the scheduling policy is an attribute of a thread (in that thereare pthread_attr_getschedpolicy() and pthread_attr_setschedpolicy() functionsthat define what the thread's scheduling policy will be once it is created,and not what any thread should do at the time they are called). A situationarises where the scheduling policy in force at the time of a thread'screation is not the same as set in its attributes. In this casepthread_create() fails with an otherwise undocumented error 'ENOTTY'.The bottom line is that under VxWorks, if you wish to specify the schedulingpolicy of a thread, you must set the desired global scheduling policy to match.Threads must then adhere to that scheduling policy, or use thePTHREAD_INHERIT_SCHED mode to inherit the current mode and creator's priority.CREATION AND CANCELLATIONEach time a thread is created, the <pthreads> library allocates resources onbehalf of it. Each time a VxWorks task (i.e. one not created by thepthread_create() function) uses a POSIX threads feature such as threadprivate data or pushes a cleanup handler, the <pthreads> library createsresources on behalf of that task as well.Asynchronous thread cancellation is accomplished by way of a signal. Aspecial signal, SIGCANCEL, has been set aside in this version of VxWorks forthis purpose. Applications should take care not to block or handle SIGCANCEL.SUMMARY MATRIX.TStab (|);l l l.'<pthread> function' | 'Implemented?' | 'Note(s)'_pthread_attr_destroy | Yes |pthread_attr_getdetachstate | Yes |pthread_attr_getinheritsched | Yes |pthread_attr_getschedparam | Yes |pthread_attr_getschedpolicy | Yes |pthread_attr_getscope | Yes |pthread_attr_getstackaddr | Yes |pthread_attr_getstacksize | Yes |pthread_attr_init | Yes |pthread_attr_setdetachstate | Yes |pthread_attr_setinheritsched | Yes |pthread_attr_setschedparam | Yes |pthread_attr_setschedpolicy | Yes |pthread_attr_setscope | Yes | 2pthread_attr_setstackaddr | Yes |pthread_attr_setstacksize | Yes |pthread_atfork | No | 1pthread_cancel | Yes | 5pthread_cleanup_pop | Yes |pthread_cleanup_push | Yes |pthread_condattr_destroy | Yes |pthread_condattr_getpshared | No | 3pthread_condattr_init | Yes |pthread_condattr_setpshared | No | 3pthread_cond_broadcast | Yes |pthread_cond_destroy | Yes |pthread_cond_init | Yes |pthread_cond_signal | Yes |pthread_cond_timedwait | Yes |pthread_cond_wait | Yes |pthread_create | Yes |pthread_detach | Yes |pthread_equal | Yes |pthread_exit | Yes |pthread_getschedparam | Yes | 4pthread_getspecific | Yes |pthread_join | Yes |pthread_key_create | Yes |pthread_key_delete | Yes |pthread_kill | Yes |pthread_once | Yes |pthread_self | Yes |pthread_setcancelstate | Yes |pthread_setcanceltype | Yes |pthread_setschedparam | Yes | 4pthread_setspecific | Yes |pthread_sigmask | Yes |pthread_testcancel | Yes |pthread_mutexattr_destroy | Yes |pthread_mutexattr_getprioceiling | Yes |pthread_mutexattr_getprotocol | Yes |pthread_mutexattr_getpshared | No | 3pthread_mutexattr_init | Yes |pthread_mutexattr_setprioceiling | Yes |pthread_mutexattr_setprotocol | Yes |pthread_mutexattr_setpshared | No | 3pthread_mutex_destroy | Yes |pthread_mutex_getprioceiling | Yes |pthread_mutex_init | Yes |pthread_mutex_lock | Yes |pthread_mutex_setprioceiling | Yes |pthread_mutex_trylock | Yes |pthread_mutex_unlock | Yes |getlogin_r | No | 6getgrgid_r | No | 6getpwnam_r | No | 6getpwuid_r | No | 6.TENOTES.iP 1 4The pthread_atfork() function is not implemented since fork() is notimplemented in VxWorks..iP 2The contention scope thread scheduling attribute is alwaysPTHREAD_SCOPE_SYSTEM, since threads (i.e. tasks) contend for resourceswith all other threads in the system..iP 3The routines pthread_condattr_getpshared(), pthread_attr_setpshared(),pthread_mutexattr_getpshared() and pthread_mutexattr_setpshared() are notsupported, since these interfaces describe how condition variables andmutexes relate to a process, and VxWorks does not implement a process model..iP 4The default scheduling policy is inherited from the current system setting.The POSIX model of per-thread scheduling policies is not supported, since abasic tenet of the design of VxWorks is a system-wide scheduling policy..iP 5Thread cancellation is supported in appropriate <pthread> routines andthose routines already supported by VxWorks. However, the complete list ofcancellation points specified by POSIX is not supported because routinessuch as msync(), fcntl(), tcdrain(), and wait() are not implemented byVxWorks..iP 6The routines getlogin_r(), getgrgid_r(), getpwnam_r(), and getpwuid_r() arenot implemented..LPINCLUDE FILES: pthread.hSEE ALSO: taskLib, semMLib, semPxLib,<VxWorks Programmer's Guide: Multitasking>*//* includes */#include "vxWorks.h"#include "semLib.h"#include "taskLib.h"#include "timers.h"#include "taskArchLib.h"#include "private/timerLibP.h"#include "types/vxTypesOld.h"#include "private/taskLibP.h"#include "kernelLib.h"#include "taskHookLib.h"#include "signal.h"#include "stdio.h"#include "string.h"#include "errno.h"#include "memLib.h"#include "fcntl.h"#include "ioLib.h"#include "logLib.h"#include "sched.h"#include "private/schedP.h"#ifndef _WRS_VXWORKS_5_X#include "private/pdLibP.h"#include "pdLib.h"#endif#define __PTHREAD_SRC#include "pthread.h"#undef PTHREADS_DEBUG#ifdef PTHREADS_DEBUG#undef LOCAL#define LOCAL#endif/* defines */#define INIT_MUTEX(pMutex)						\    do									\	{								\	if (!pthreadLibInited)						\	    return (EINVAL);						\	if ((pMutex)->mutexInitted == FALSE)				\	    {								\	    if (vxTas(&(pMutex)->mutexIniting) == TRUE)			\		{							\		taskLock();  /* may not be necessary */			\									\		(pMutex)->mutexSemId = semMCreate(			\		      (pMutex->mutexAttr.mutexAttrProtocol ==		\		       PTHREAD_PRIO_INHERIT ? SEM_INVERSION_SAFE : 0) |	\		       SEM_Q_PRIORITY);					\									\		if ((pMutex)->mutexSemId == NULL)			\		    {							\		    taskUnlock ();					\		    return (EINVAL);	/* internal error */		\		    }							\									\		(pMutex)->mutexInitted = TRUE;				\					   				\		taskUnlock();	/* may not be necessary */		\		}							\	    else							\		{							\	        while ((pMutex)->mutexInitted == FALSE)			\		    ;    /* pound sand */				\		}							\	    }								\	}								\    while (0)#define INIT_COND(pCond)						\    do									\	{								\	if (!pthreadLibInited)						\	    return (EINVAL);						\	if ((pCond)->condInitted == FALSE)				\	    {								\	    if (vxTas(&(pCond)->condIniting) == TRUE)			\		{							\		taskLock();  /* may not be necessary */			\									\		(pCond)->condSemId = semBCreate(SEM_Q_PRIORITY,		\						SEM_EMPTY);		\									\		if ((pCond)->condSemId == NULL)				\		    {							\		    taskUnlock ();					\		    return (EINVAL); /* internal error */		\		    }							\									\		(pCond)->condInitted = TRUE;				\									\		taskUnlock(); /* may not be necessary */		\		}							\	    else							\		{							\	    	while ((pCond)->condInitted == FALSE)			\		    ;    /* pound sand */				\		}							\	    }								\	}								\    while (0)#ifndef _WRS_VXWORKS_5_X#define VALID_PTHREAD(pThread, pLcb) \		((pThread) && ((pThread)->flags & VALID) && \		((pLcb) = taskLcbGet((pThread)->taskId)) && \		(pLcb)->pPthread && \		(pLcb)->pPthread == (pThread))#else#define VALID_PTHREAD(pThread, pTcb) \		((pThread) && ((pThread)->flags & VALID) && \		((pTcb) = (WIND_TCB *)(pThread)->taskId) && \		(pTcb)->pPthread && \		(pTcb)->pPthread == (pThread))#endif#define MY_PTHREAD ((internalPthread *)(taskIdCurrent->pPthread))#define LOCK_PTHREAD(pThread)   semTake((pThread)->mutexSemId, WAIT_FOREVER)#define UNLOCK_PTHREAD(pThread) semGive((pThread)->mutexSemId)#define CANCEL_LOCK(pThread)    semTake((pThread)->cancelSemId, WAIT_FOREVER)#define CANCEL_UNLOCK(pThread)  semGive((pThread)->cancelSemId)/* numeric boundary check for priority. no mention of meaning of value */#define PRIO_LOWER_BOUND 0#define PRIO_UPPER_BOUND 255#define VALID_PRIORITY(pri)     (PRIO_LOWER_BOUND <= (pri) && \				 (pri) <= PRIO_UPPER_BOUND)#define DEF_PRIORITY	(PRIO_LOWER_BOUND + \		      		(PRIO_UPPER_BOUND - PRIO_LOWER_BOUND) / 2)/* * Make sure we free memory from the PD's heap, even when called from a kernel * task, or a delete hook... *//* typedefs */typedef struct    {    pthread_mutex_t    mutex;    long               count;    void               (*destructor)();    } pthread_key;/* globals *//* * This is a common. DO NOT INITIALISE IT - doing so will break the scalability * that relies on its status as a common. */FUNCPTR _pthread_setcanceltype;/* locals */LOCAL pthread_key	key_table[_POSIX_THREAD_KEYS_MAX];LOCAL SEM_ID		key_mutex		= NULL;LOCAL BOOL		pthreadLibInited	= FALSE;/* The default mutex, condition variable and thread creation attribute objects * and initializers - either POSIX or implementation-defined. * Used by: *  pthread_mutex_init() *  pthread_cond_init() *  pthread_create() * * For mutexes and condition variables, * only the 'process-shared' attribute is defined. */LOCAL pthread_mutexattr_t defaultMutexAttr =    {    PTHREAD_INITIALIZED, PTHREAD_PRIO_INHERIT, 0    };/* forward declarations */LOCAL void self_become_pthread(void);LOCAL void pthreadDeleteTask (internalPthread * pThread);LOCAL void threadExitCleanup (internalPthread * pThread);LOCAL void cleanupPrivateData (internalPthread * pThread);/* externals */IMPORT BOOL	vxTas (void *addr);/********************************************************************************* pthreadLibInit - initialize POSIX threads support** This routine initializes the POSIX threads (<pthreads>) support for* VxWorks. It should be called before any POSIX threads functions are used;* normally it will be called as part of the kernel's initialization sequence.** RETURNS: N/A*/void pthreadLibInit (void)    {    if (_pthreadLibInit ((FUNCPTR) pthreadDeleteTask) != ERROR)	{	/* Create the thread specific data key */	key_mutex = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);	/*	 * Initialise the function pointer for user level access to this

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -