dspbios-osal.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. /*
  2. * psp_osal.h
  3. *
  4. * Description:
  5. *
  6. * --------------------------------------------------------------------------
  7. *
  8. * Pthreads-embedded (PTE) - POSIX Threads Library for embedded systems
  9. * Copyright(C) 2008 Jason Schmidlapp
  10. *
  11. * Contact Email: [email protected]
  12. *
  13. * This library is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU Lesser General Public
  15. * License as published by the Free Software Foundation; either
  16. * version 2 of the License, or (at your option) any later version.
  17. *
  18. * This library is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  21. * Lesser General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Lesser General Public
  24. * License along with this library in the file COPYING.LIB;
  25. * if not, write to the Free Software Foundation, Inc.,
  26. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  27. */
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <std.h>
  31. #include <clk.h>
  32. #include <lck.h>
  33. #include <mbx.h>
  34. #include <pthread.h>
  35. #include "tls-helper.h"
  36. #include "pte_osal.h"
  37. #define POLLING_DELAY_IN_ticks 10
  38. #define DSPBIOS_MAX_TLS 32
  39. #define DEFAULT_STACK_SIZE_BYTES 4096
  40. /*
  41. * Data stored on a per-thread basis - allocated in pte_osThreadCreate
  42. * and freed in pte_osThreadDelete.
  43. */
  44. typedef struct dspbiosThreadData
  45. {
  46. /* Semaphore used to wait for threads to end. Posted to in pte_osThreadExit() */
  47. SEM_Handle joinSem;
  48. /* Semaphore used for cancellation. Posted to by pte_osThreadCancel, polled in pte_osSemaphoreCancellablePend */
  49. SEM_Handle cancelSem;
  50. /* Initial priority of the thread. */
  51. int priority;
  52. } dspbiosThreadData;
  53. /* Task and mailbox used for cleaning up detached threads */
  54. static TSK_Handle gcTaskHandle;
  55. static MBX_Handle gcMailbox;
  56. /* TLS key used to access dspbiosThreadData struct for reach thread. */
  57. static unsigned int threadDataKey;
  58. /*
  59. *
  60. * Helper functions
  61. *
  62. */
  63. /* Returns a pointer to the per thread control info */
  64. static dspbiosThreadData * getThreadData(TSK_Handle threadHandle)
  65. {
  66. dspbiosThreadData *pThreadData;
  67. void * pTls;
  68. pTls = (void *) TSK_getenv(threadHandle);
  69. pThreadData = (dspbiosThreadData *) pteTlsGetValue(pTls, threadDataKey);
  70. return pThreadData;
  71. }
  72. /* Converts milliseconds to system ticks (for TSK_sleep, SEM_pend, etc) */
  73. static int msecsToSysTicks(int msecs)
  74. {
  75. int ticks = CLK_countspms() / CLK_getprd() * msecs;
  76. ticks = ticks / 100; // sim only
  77. return ticks;
  78. }
  79. /* Garbage collector thread to free resources from detached threads */
  80. void dspbiosGarbageCollectorMain()
  81. {
  82. gcMailbox = MBX_create(sizeof(void*), 10, NULL);
  83. while (1)
  84. {
  85. Bool status;
  86. void * pTask;
  87. /* Wait for dying threads to post their handles to our mailbox */
  88. status = MBX_pend(gcMailbox, &pTask, SYS_FOREVER);
  89. if (status)
  90. {
  91. TSK_delete((TSK_Handle) pTask);
  92. }
  93. }
  94. /* Never returns */
  95. }
  96. /****************************************************************************
  97. *
  98. * Initialization
  99. *
  100. ***************************************************************************/
  101. /*
  102. * Initializes the OSAL.
  103. *
  104. * 1. Initialize TLS support.
  105. * 2. Allocate control data TLS key.
  106. * 3. Start garbage collector thread.
  107. */
  108. pte_osResult pte_osInit(void)
  109. {
  110. pte_osResult result;
  111. TSK_Attrs attrs;
  112. /* Allocate and initialize TLS support */
  113. result = pteTlsGlobalInit(DSPBIOS_MAX_TLS);
  114. if (result == PTE_OS_OK)
  115. {
  116. /* Allocate a key that we use to store control information (e.g. cancellation semaphore) per thread */
  117. result = pteTlsAlloc(&threadDataKey);
  118. if (result == PTE_OS_OK)
  119. {
  120. /* Create a low priority task to free resources for detached threads */
  121. attrs = TSK_ATTRS;
  122. attrs.priority = 1; /* just above idle task */
  123. attrs.name = "pthread-gc";
  124. gcTaskHandle = TSK_create((Fxn) dspbiosGarbageCollectorMain, &attrs);
  125. /* Give the garbage collector task a chance to run and create the mailbox */
  126. TSK_sleep(1);
  127. if (gcTaskHandle == NULL)
  128. {
  129. result = PTE_OS_NO_RESOURCES;
  130. }
  131. }
  132. }
  133. return result;
  134. }
  135. /****************************************************************************
  136. *
  137. * Threads
  138. *
  139. ***************************************************************************/
  140. /* Entry point for new threads */
  141. void dspbiosStubThreadEntry (void *argv, pte_osThreadEntryPoint entryPoint)
  142. {
  143. (*(entryPoint))(argv);
  144. return;
  145. }
  146. /*
  147. * Creates a new thread, allocates resources, etc.
  148. *
  149. * The thread is created in a suspended state; execution will actually start
  150. * when pte_osThreadStart() is called. Setting the priority to a -1 will start the
  151. * thread in a suspended state. pte_osThreadStart then sets the real priority which
  152. * will start the thread executing.
  153. *
  154. * In order for dynamic tasks to work, you must set up a heap for DSP/BIOS to allocate their
  155. * stacks from. This should be done in the projects tcf or cdb file.
  156. *
  157. */
  158. pte_osResult pte_osThreadCreate(pte_osThreadEntryPoint entryPoint,
  159. int stackSize,
  160. int initialPriority,
  161. void *argv,
  162. pte_osThreadHandle* ppte_osThreadHandle)
  163. {
  164. TSK_Handle handle;
  165. TSK_Attrs attrs;
  166. void *pTls;
  167. pte_osResult result;
  168. dspbiosThreadData *pThreadData;
  169. /* Make sure that the stack we're going to allocate is big enough */
  170. if (stackSize < DEFAULT_STACK_SIZE_BYTES)
  171. {
  172. stackSize = DEFAULT_STACK_SIZE_BYTES;
  173. }
  174. /* Allocate TLS structure for this thread. */
  175. pTls = pteTlsThreadInit();
  176. if (pTls == NULL)
  177. {
  178. result = PTE_OS_NO_RESOURCES;
  179. goto FAIL0;
  180. }
  181. /* Allocate some memory for our per-thread control data. We use this for:
  182. * 1. join semaphore (used to wait for thread termination)
  183. * 2. cancellation semaphore (used to signal a thread to cancel)
  184. * 3. initial priority (used in stub entry point)
  185. */
  186. pThreadData = (dspbiosThreadData*) malloc(sizeof(dspbiosThreadData));
  187. if (pThreadData == NULL)
  188. {
  189. pteTlsThreadDestroy(pTls);
  190. result = PTE_OS_NO_RESOURCES;
  191. goto FAIL0;
  192. }
  193. /* Save a pointer to our per-thread control data as a TLS value */
  194. pteTlsSetValue(pTls, threadDataKey, pThreadData);
  195. /* Create semaphores and save handles */
  196. pThreadData->joinSem = SEM_create(0, NULL);
  197. pThreadData->cancelSem = SEM_create(0, NULL);
  198. /* Save the initial priority - we need it when we
  199. * actually start the thread */
  200. pThreadData->priority = initialPriority;
  201. /*
  202. * Fill out parameters for TSK_create:
  203. */
  204. attrs = TSK_ATTRS;
  205. /* Use value specified by user */
  206. attrs.stacksize = stackSize;
  207. attrs.priority = -1;
  208. /* Save our TLS structure as the task's environment. */
  209. attrs.environ = pTls;
  210. handle = TSK_create((Fxn) dspbiosStubThreadEntry, &attrs, argv, entryPoint);
  211. if (handle != NULL)
  212. {
  213. /* Everything worked, return handle to caller */
  214. *ppte_osThreadHandle = handle;
  215. result = PTE_OS_OK;
  216. }
  217. else
  218. {
  219. /* Something went wrong - assume that it was due to lack of resources. */
  220. free(pThreadData);
  221. pteTlsThreadDestroy(pTls);
  222. result = PTE_OS_NO_RESOURCES;
  223. }
  224. FAIL0:
  225. return result;
  226. }
  227. /* Start executing a thread.
  228. *
  229. * Get the priority that the user specified when they called
  230. * pte_osThreadCreate and set the priority of the thread. This
  231. * will start the thread executing.
  232. */
  233. pte_osResult pte_osThreadStart(pte_osThreadHandle osThreadHandle)
  234. {
  235. dspbiosThreadData *pThreadData;
  236. pThreadData = getThreadData(osThreadHandle);
  237. TSK_setpri(osThreadHandle, pThreadData->priority);
  238. return PTE_OS_OK;
  239. }
  240. /*
  241. * Exit from a thread.
  242. *
  243. * Post to the join semaphore in case a pthread_join is
  244. * waiting for us to exit.
  245. */
  246. void pte_osThreadExit()
  247. {
  248. TSK_Handle thisTask;
  249. dspbiosThreadData *pThreadData;
  250. thisTask = TSK_self();
  251. pThreadData = getThreadData(thisTask);
  252. if (pThreadData != NULL)
  253. {
  254. SEM_post(pThreadData->joinSem);
  255. }
  256. TSK_exit();
  257. }
  258. pte_osResult pte_osThreadExitAndDelete(pte_osThreadHandle handle)
  259. {
  260. dspbiosThreadData *pThreadData;
  261. void * pTls;
  262. pThreadData = getThreadData(handle);
  263. pTls = (void *) TSK_getenv(handle);
  264. /* Free the per thread data (join & cancel semaphores, etc) */
  265. SEM_delete(pThreadData->joinSem);
  266. SEM_delete(pThreadData->cancelSem);
  267. free(pThreadData);
  268. /* Free the TLS data structure */
  269. pteTlsThreadDestroy(pTls);
  270. /* Send thread handle to garbage collector task so it can free
  271. * resources from a different context */
  272. MBX_post(gcMailbox, &handle, SYS_FOREVER);
  273. TSK_exit();
  274. return PTE_OS_OK;
  275. }
  276. /* Clean up a thread.
  277. *
  278. * If this is called from the thread itself, instead of actually freeing up
  279. * resources, post the thread handle to a mailbox which will be picked
  280. * up by the garbage collector thread. Resources will be freed from there.
  281. * This is necessary because DSP/BIOS does not free resources when a
  282. * thread exits.
  283. */
  284. pte_osResult pte_osThreadDelete(pte_osThreadHandle handle)
  285. {
  286. dspbiosThreadData *pThreadData;
  287. void * pTls;
  288. pThreadData = getThreadData(handle);
  289. pTls = (void *) TSK_getenv(handle);
  290. /* Free the per thread data (join & cancel semaphores, etc) */
  291. SEM_delete(pThreadData->joinSem);
  292. SEM_delete(pThreadData->cancelSem);
  293. free(pThreadData);
  294. /* Free the TLS data structure */
  295. pteTlsThreadDestroy(pTls);
  296. TSK_delete(handle);
  297. return PTE_OS_OK;
  298. }
  299. /* Wait for a thread to exit.
  300. *
  301. * Since DSP/BIOS doesn't have a explicit system call for this, we
  302. * emulate it using a semaphore that is posted to when the thread
  303. * exits.
  304. */
  305. pte_osResult pte_osThreadWaitForEnd(pte_osThreadHandle threadHandle)
  306. {
  307. TSK_Stat taskStats;
  308. pte_osResult result;
  309. /* Prevent context switches to prevent the thread from
  310. * changing states */
  311. TSK_disable();
  312. /* First, check if the thread has already terminated. */
  313. TSK_stat(threadHandle, &taskStats);
  314. if (taskStats.mode != TSK_TERMINATED)
  315. {
  316. dspbiosThreadData *pThreadData;
  317. dspbiosThreadData *pSelfThreadData;
  318. pThreadData = getThreadData(threadHandle);
  319. pSelfThreadData = getThreadData(TSK_self());
  320. TSK_enable();
  321. /* This needs to be cancellable, so poll instead of block,
  322. * similar to what we do for pte_OsSemaphoreCancellablePend. */
  323. while (1)
  324. {
  325. if (SEM_count(pThreadData->joinSem) > 0)
  326. {
  327. /* The thread has exited. */
  328. result = PTE_OS_OK;
  329. break;
  330. }
  331. else if ((pSelfThreadData != NULL) && SEM_count(pSelfThreadData->cancelSem) > 0)
  332. {
  333. /* The thread was cancelled */
  334. result = PTE_OS_INTERRUPTED;
  335. break;
  336. }
  337. else
  338. {
  339. /* Nothing found and not timed out yet; let's yield so we're not
  340. * in busy loop. */
  341. TSK_sleep(POLLING_DELAY_IN_ticks);
  342. }
  343. }
  344. }
  345. else
  346. {
  347. /* Thread is already terminated, just return OK */
  348. TSK_enable();
  349. result = PTE_OS_OK;
  350. }
  351. return result;
  352. }
  353. /* Cancels the specified thread. This will 1) make pte_osSemaphoreCancellablePend return if it is currently
  354. * blocked and will make pte_osThreadCheckCancel return TRUE.
  355. *
  356. * To accomplish this, we post to the cancellation semaphore for the specified thread.
  357. */
  358. pte_osResult pte_osThreadCancel(pte_osThreadHandle threadHandle)
  359. {
  360. dspbiosThreadData *pThreadData;
  361. pThreadData = getThreadData(threadHandle);
  362. if (pThreadData != NULL)
  363. {
  364. SEM_post(pThreadData->cancelSem);
  365. }
  366. return PTE_OS_OK;
  367. }
  368. /*
  369. * Checks to see if pte_osThreadCancel has been called for the specified thread. Just check the
  370. * value of the cancellation semaphore associated with the thread.
  371. */
  372. pte_osResult pte_osThreadCheckCancel(pte_osThreadHandle threadHandle)
  373. {
  374. dspbiosThreadData *pThreadData;
  375. pThreadData = getThreadData(threadHandle);
  376. if (pThreadData != NULL)
  377. {
  378. if (SEM_count(pThreadData->cancelSem) > 0)
  379. {
  380. return PTE_OS_INTERRUPTED;
  381. }
  382. else
  383. {
  384. return PTE_OS_OK;
  385. }
  386. }
  387. else
  388. {
  389. /* We're being called from a pure OS thread which can't be cancelled. */
  390. return PTE_OS_OK;
  391. }
  392. }
  393. void pte_osThreadSleep(unsigned int msecs)
  394. {
  395. int ticks = msecsToSysTicks(msecs);
  396. TSK_sleep(ticks);
  397. }
  398. pte_osThreadHandle pte_osThreadGetHandle(void)
  399. {
  400. return TSK_self();
  401. }
  402. int pte_osThreadGetPriority(pte_osThreadHandle threadHandle)
  403. {
  404. return TSK_getpri(threadHandle);
  405. }
  406. pte_osResult pte_osThreadSetPriority(pte_osThreadHandle threadHandle, int newPriority)
  407. {
  408. TSK_setpri(threadHandle, newPriority);
  409. return PTE_OS_OK;
  410. }
  411. int pte_osThreadGetMinPriority()
  412. {
  413. return TSK_MINPRI;
  414. }
  415. int pte_osThreadGetMaxPriority()
  416. {
  417. return TSK_MAXPRI;
  418. }
  419. int pte_osThreadGetDefaultPriority()
  420. {
  421. /* Pick something in the middle */
  422. return ((TSK_MINPRI + TSK_MAXPRI) / 2);
  423. }
  424. /****************************************************************************
  425. *
  426. * Mutexes
  427. *
  428. ***************************************************************************/
  429. pte_osResult pte_osMutexCreate(pte_osMutexHandle *pHandle)
  430. {
  431. *pHandle = LCK_create(NULL);
  432. if (*pHandle == NULL)
  433. {
  434. return PTE_OS_NO_RESOURCES;
  435. }
  436. else
  437. {
  438. return PTE_OS_OK;
  439. }
  440. }
  441. pte_osResult pte_osMutexDelete(pte_osMutexHandle handle)
  442. {
  443. LCK_delete(handle);
  444. return PTE_OS_OK;
  445. }
  446. pte_osResult pte_osMutexLock(pte_osMutexHandle handle)
  447. {
  448. LCK_pend(handle, SYS_FOREVER);
  449. return PTE_OS_OK;
  450. }
  451. pte_osResult pte_osMutexUnlock(pte_osMutexHandle handle)
  452. {
  453. LCK_post(handle);
  454. return PTE_OS_OK;
  455. }
  456. /****************************************************************************
  457. *
  458. * Semaphores
  459. *
  460. ***************************************************************************/
  461. pte_osResult pte_osSemaphoreCreate(int initialValue, pte_osSemaphoreHandle *pHandle)
  462. {
  463. *pHandle = SEM_create(initialValue, NULL);
  464. if (*pHandle == NULL)
  465. {
  466. return PTE_OS_NO_RESOURCES;
  467. }
  468. else
  469. {
  470. return PTE_OS_OK;
  471. }
  472. }
  473. pte_osResult pte_osSemaphoreDelete(pte_osSemaphoreHandle handle)
  474. {
  475. SEM_delete(handle);
  476. return PTE_OS_OK;
  477. }
  478. pte_osResult pte_osSemaphorePost(pte_osSemaphoreHandle handle, int count)
  479. {
  480. int i;
  481. for (i=0;i<count;i++)
  482. {
  483. SEM_post(handle);
  484. }
  485. return PTE_OS_OK;
  486. }
  487. pte_osResult pte_osSemaphorePend(pte_osSemaphoreHandle handle, unsigned int *pTimeoutMsecs)
  488. {
  489. Bool status;
  490. unsigned int timeoutTicks;
  491. if (pTimeoutMsecs == NULL)
  492. {
  493. timeoutTicks = SYS_FOREVER;
  494. }
  495. else
  496. {
  497. timeoutTicks = msecsToSysTicks(*pTimeoutMsecs);
  498. }
  499. status = SEM_pend(handle, timeoutTicks);
  500. if (status)
  501. {
  502. return PTE_OS_OK;
  503. }
  504. else
  505. {
  506. return PTE_OS_TIMEOUT;
  507. }
  508. }
  509. /*
  510. * Pend on a semaphore- and allow the pend to be cancelled.
  511. *
  512. * DSP/BIOS provides no functionality to asynchronously interrupt a blocked call. We simulte
  513. * this by polling on the main semaphore and the cancellation semaphore and sleeping in a loop.
  514. */
  515. pte_osResult pte_osSemaphoreCancellablePend(pte_osSemaphoreHandle semHandle, unsigned int *pTimeout)
  516. {
  517. clock_t start_time;
  518. clock_t current_time;
  519. pte_osResult result = PTE_OS_OK;
  520. int timeout;
  521. dspbiosThreadData *pThreadData;
  522. pThreadData = getThreadData(TSK_self());
  523. start_time = CLK_getltime();
  524. if (pTimeout == NULL)
  525. {
  526. timeout = -1;
  527. }
  528. else
  529. {
  530. timeout = msecsToSysTicks(*pTimeout);
  531. }
  532. while (1)
  533. {
  534. Bool semTimeout;
  535. int status;
  536. /* Poll semaphore */
  537. semTimeout = 0;
  538. current_time = CLK_getltime();
  539. status = SEM_pend(semHandle, semTimeout);
  540. if (status == TRUE)
  541. {
  542. /* The user semaphore was posted to */
  543. result = PTE_OS_OK;
  544. break;
  545. }
  546. else if ((timeout != -1) && ((current_time - start_time) > timeout))
  547. {
  548. /* The timeout expired */
  549. result = PTE_OS_TIMEOUT;
  550. break;
  551. }
  552. else
  553. {
  554. if ((pThreadData != NULL) && SEM_count(pThreadData->cancelSem) > 0)
  555. {
  556. /* The thread was cancelled */
  557. result = PTE_OS_INTERRUPTED;
  558. break;
  559. }
  560. else
  561. {
  562. /* Nothing found and not timed out yet; let's yield so we're not
  563. * in busy loop. */
  564. TSK_sleep(POLLING_DELAY_IN_ticks);
  565. }
  566. }
  567. }
  568. return result;
  569. }
  570. /****************************************************************************
  571. *
  572. * Atomic Operations
  573. *
  574. ***************************************************************************/
  575. int pte_osAtomicExchange(int *ptarg, int val)
  576. {
  577. long origVal;
  578. Uns oldCSR;
  579. oldCSR = HWI_disable();
  580. origVal = *ptarg;
  581. *ptarg = val;
  582. HWI_restore(oldCSR);
  583. return origVal;
  584. }
  585. int pte_osAtomicCompareExchange(int *pdest, int exchange, int comp)
  586. {
  587. int origVal;
  588. Uns oldCSR;
  589. oldCSR = HWI_disable();
  590. origVal = *pdest;
  591. if (*pdest == comp)
  592. {
  593. *pdest = exchange;
  594. }
  595. HWI_restore(oldCSR);
  596. return origVal;
  597. }
  598. int pte_osAtomicExchangeAddInt(int volatile* pAddend, int value)
  599. {
  600. int origVal;
  601. Uns oldCSR;
  602. oldCSR = HWI_disable();
  603. origVal = *pAddend;
  604. *pAddend += value;
  605. HWI_restore(oldCSR);
  606. return origVal;
  607. }
  608. int pte_osAtomicExchangeAdd(int volatile* pAddend, int value)
  609. {
  610. int origVal;
  611. Uns oldCSR;
  612. oldCSR = HWI_disable();
  613. origVal = *pAddend;
  614. *pAddend += value;
  615. HWI_restore(oldCSR);
  616. return origVal;
  617. }
  618. int pte_osAtomicDecrement(int *pdest)
  619. {
  620. int val;
  621. Uns oldCSR;
  622. oldCSR = HWI_disable();
  623. (*pdest)--;
  624. val = *pdest;
  625. HWI_restore(oldCSR);
  626. return val;
  627. }
  628. int pte_osAtomicIncrement(int *pdest)
  629. {
  630. int val;
  631. Uns oldCSR;
  632. oldCSR = HWI_disable();
  633. (*pdest)++;
  634. val = *pdest;
  635. HWI_restore(oldCSR);
  636. return val;
  637. }
  638. /****************************************************************************
  639. *
  640. * Thread Local Storage
  641. *
  642. ***************************************************************************/
  643. pte_osResult pte_osTlsSetValue(unsigned int index, void * value)
  644. {
  645. void *pTls;
  646. pTls = (void *) TSK_getenv(TSK_self());
  647. if (pTls == NULL)
  648. {
  649. // Apparently no TLS structure has been allocated for this thread
  650. // Probably because this is a native OS thread
  651. pTls = pteTlsThreadInit();
  652. TSK_setenv(TSK_self(), pTls);
  653. }
  654. return pteTlsSetValue(pTls, index, value);
  655. }
  656. void * pte_osTlsGetValue(unsigned int index)
  657. {
  658. void *pTls;
  659. pTls = (void *) TSK_getenv(TSK_self());
  660. return (void *) pteTlsGetValue(pTls, index);
  661. }
  662. // Note that key value must be > 0
  663. pte_osResult pte_osTlsAlloc(unsigned int *pKey)
  664. {
  665. return pteTlsAlloc(pKey);
  666. }
  667. pte_osResult pte_osTlsFree(unsigned int index)
  668. {
  669. return pteTlsFree(index);
  670. }
  671. int ftime(struct timeb *tp)
  672. {
  673. int ltime = (CLK_getltime() * CLK_cpuCyclesPerLtime()) / CLK_cpuCyclesPerLtime();
  674. int secs = ltime / 1000;
  675. int msecs = ltime % 1000;
  676. tp->dstflag = 0;
  677. tp->timezone = 0;
  678. tp->time = secs;
  679. tp->millitm = msecs;
  680. return 0;
  681. }