📄 _pthreadlib.c
字号:
/* _pthreadLib.c - POSIX 1003.1c thread library kernel support *//* Copyright 1984-2002 Wind River Systems, Inc. *//* Copyright (c) 1995 by Dot4, Inc. */#include "copyright_wrs.h"/*modification history--------------------01f,03may02,gls fixed memory leak when user specifies stack (SPR #76769)01e,22apr02,gls removed references to AE in comments (SPR #75799)01d,26nov01,gls changed stackAddr to char * for DIAB support01c,31oct01,jgn fix rounding of stack size (SPR #71350)01b,22oct01,jgn correct scheduling policy inheritance (SPR #71125)01a,10sep00,jgn created from pthreadLib.c version 01c (SPR #33375) + ensure TCB pdId set always (SPR #33711)*//*DESCRIPTIONKernel support routines for the VxWorks pthreads implementation. NOMANUAL*//* includes */#include "vxWorks.h"#include "intLib.h"#include "kernelLib.h"#include "private/schedP.h"#include "private/taskLibP.h"#include "pthread.h"#include "semLib.h"#include "string.h"#include "taskLib.h"#include "taskArchLib.h"#include "taskHookLib.h"#include "limits.h"#undef PTHREADS_DEBUG#ifdef PTHREADS_DEBUG#undef LOCAL#define LOCAL#endif/* defines */#define DEF_STACK_SIZE (20 * 1024)#define MY_PTHREAD ((internalPthread *)(taskIdCurrent->pPthread))#define CANCEL_LOCK(pThread) semTake((pThread)->cancelSemId, WAIT_FOREVER)#define CANCEL_UNLOCK(pThread) semGive((pThread)->cancelSemId)/* * Need copies of these since we are going to have to pass in the current * PD's numbering scheme to _pthreadCreate() and can't use the existing * global variable that the original macros use... */#define PX_VX_PRI_CONV(mode,pri) (mode ? (POSIX_HIGH_PRI - pri) : pri)/* locals */LOCAL BOOL pthreadLibInited = FALSE;LOCAL FUNCPTR pthreadDeleteTaskEntry = NULL;LOCAL pthread_attr_t defaultPthreadAttr = \ { \ PTHREAD_INITIALIZED, /* object status */ \ ((size_t) 0), /* stacksize */ \ NULL, /* stackaddr */ \ PTHREAD_CREATE_JOINABLE, /* detachstate */ \ PTHREAD_SCOPE_SYSTEM, /* contentionscope */ \ PTHREAD_INHERIT_SCHED, /* inheritsched */ \ SCHED_RR, /* schedpolicy */ \ NULL, /* name */ \ {0}, /* struct sched_param */ \ };/* externals */IMPORT BOOL vxTas (void *addr);IMPORT BOOL roundRobinOn;IMPORT ULONG roundRobinSlice;/* forward references */LOCAL void deleteHook (WIND_TCB *pTcb);/********************************************************************************* _pthreadLibInit - initialize POSIX threads support** This routine initializes the POSIX threads (<pthreads>) support for* VxWorks. It should only be called via pthreadLibInit() since it needs to* register the delete hook's user level function.** Multiple attempts to initialise are ignored, but the delete hook function will* be changed. This is to ensure that if the user level code is replaced then* the new function pointer will be available.** RETURNS: N/A** NOMANUAL*/STATUS _pthreadLibInit ( FUNCPTR deleteTask /* user level code for delete hook */ ) { /* Always store this in case it is simply being changed */ pthreadDeleteTaskEntry = deleteTask; taskLock(); if (pthreadLibInited) { taskUnlock(); return OK; } if (taskDeleteHookAdd((FUNCPTR) deleteHook) == ERROR) { if (_func_logMsg != NULL) _func_logMsg ("taskDeleteHookAdd of pthread deleteHook failed!\n", 0, 0, 0, 0, 0, 0); } else { pthreadLibInited = TRUE; _func_pthread_setcanceltype = _pthreadSetCancelType; } taskUnlock(); return ((pthreadLibInited == TRUE) ? OK : ERROR); }/* * Section 16 - Thread Management *//********************************************************************************* _pthreadCreate - create a thread (POSIX)** This is the actual thread creation function. It is called by the user level* pthread_create() function.** NOMANUAL*/int _pthreadCreate ( pthread_t * pThread, const pthread_attr_t * pAttr, void * (*wrapperFunc)(void *), void * (*start_routine)(void *), void * arg, int priNumMode ) { char name[NAME_MAX]; char * pBufStart; /* points to temp name buffer start */ char * pBufEnd; /* points to temp name buffer end */ char temp; /* working character */ int value; /* working value to convert to ascii */ int nPreBytes; /* nameless prefix string length */ int nBytes = 0; /* working nameless name string length */ static int namecntr = {0}; static char * prefix = "pthr"; static char *digits = "0123456789"; WIND_TCB * pTcb; internalPthread * pMyThread; char * stackaddr = NULL; int stacksize; if (!pThread) return (EINVAL); if (!pthreadLibInited) return (EINVAL); if (pAttr && pAttr->threadAttrStatus != PTHREAD_INITIALIZED) return (EINVAL); else if (!pAttr) pAttr = &defaultPthreadAttr; /* * Make sure that sched policy is supported, valid, and matches global * policy. Only perform this test if the inheritsched attribute is set * to PTHREAD_EXPLICIT_SCHED though; if we are inheriting then we'll get * it right by definition (no need to worry about finding out the current * policy since for VxWorks it is system-wide). */ if (pAttr->threadAttrInheritsched == PTHREAD_EXPLICIT_SCHED) { if ((pAttr->threadAttrSchedpolicy == SCHED_OTHER) || ((roundRobinOn == TRUE) && (pAttr->threadAttrSchedpolicy != SCHED_RR)) || ((roundRobinOn == FALSE) && (pAttr->threadAttrSchedpolicy != SCHED_FIFO))) { errno = ENOTTY; return (ENOTTY); } } if (!(pMyThread = malloc(sizeof (internalPthread)))) return (EAGAIN); bzero((char *)pMyThread, sizeof (internalPthread)); /* * If zero is specified, use the default stack size, otherwise use the * specified size, rounded up to PTHREAD_STACK_MIN if necessary. */ if (pAttr->threadAttrStacksize == 0) { stacksize = DEF_STACK_SIZE; } else { stacksize = max(pAttr->threadAttrStacksize, PTHREAD_STACK_MIN); } if (pAttr->threadAttrStackaddr) { pMyThread->flags |= STACK_PASSED_IN; stackaddr = pAttr->threadAttrStackaddr; } if (pAttr->threadAttrDetachstate == PTHREAD_CREATE_JOINABLE) { pMyThread->flags |= JOINABLE; if ((pMyThread->exitJoinSemId = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY)) == NULL) { free(pMyThread); return (EAGAIN); } } if ((pMyThread->mutexSemId = semMCreate(SEM_Q_PRIORITY|SEM_INVERSION_SAFE)) == NULL) { semDelete(pMyThread->exitJoinSemId); free(pMyThread); return (EAGAIN); } if ((pMyThread->cancelSemId = semMCreate(SEM_Q_PRIORITY|SEM_INVERSION_SAFE)) == NULL) { semDelete(pMyThread->mutexSemId); semDelete(pMyThread->exitJoinSemId); free(pMyThread); return (EAGAIN); } /* create name for the task */ if (pAttr && pAttr->threadAttrName == NULL) { strcpy (name, prefix); /* copy in prefix */ nBytes = strlen (name); /* calculate prefix length */ nPreBytes = nBytes; /* remember prefix strlen() */ value = ++ namecntr; /* bump the nameless count */ do /* crank out digits backwards */ { name [nBytes++] = digits [value % 10]; value /= 10; /* next digit */ } while (value != 0); /* until no more digits */ pBufStart = name + nPreBytes; /* start reverse after prefix */ pBufEnd = name + nBytes - 1; /* end reverse at EOS */ while (pBufStart < pBufEnd) /* reverse the digits */ { temp = *pBufStart; *pBufStart = *pBufEnd; *pBufEnd = temp; pBufEnd--; pBufStart++; } name[nBytes] = EOS; /* EOS terminate string */ } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -