Thread.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /*******************************************************************************
  2. * Copyright (c) 2009, 2022 IBM Corp. and Ian Craggs
  3. *
  4. * All rights reserved. This program and the accompanying materials
  5. * are made available under the terms of the Eclipse Public License v2.0
  6. * and Eclipse Distribution License v1.0 which accompany this distribution.
  7. *
  8. * The Eclipse Public License is available at
  9. * https://www.eclipse.org/legal/epl-2.0/
  10. * and the Eclipse Distribution License is available at
  11. * http://www.eclipse.org/org/documents/edl-v10.php.
  12. *
  13. * Contributors:
  14. * Ian Craggs - initial implementation
  15. * Ian Craggs, Allan Stockdill-Mander - async client updates
  16. * Ian Craggs - bug #415042 - start Linux thread as disconnected
  17. * Ian Craggs - fix for bug #420851
  18. * Ian Craggs - change MacOS semaphore implementation
  19. * Ian Craggs - fix for clock #284
  20. *******************************************************************************/
  21. /**
  22. * @file
  23. * \brief Threading related functions
  24. *
  25. * Used to create platform independent threading functions
  26. */
  27. #include "Thread.h"
  28. #if defined(THREAD_UNIT_TESTS)
  29. #define NOSTACKTRACE
  30. #endif
  31. #include "Log.h"
  32. #include "StackTrace.h"
  33. #undef malloc
  34. #undef realloc
  35. #undef free
  36. #if !defined(_WIN32) && !defined(_WIN64)
  37. #include <errno.h>
  38. #include <unistd.h>
  39. #include <sys/time.h>
  40. #include <fcntl.h>
  41. #include <stdio.h>
  42. #include <sys/stat.h>
  43. #include <limits.h>
  44. #endif
  45. #include <stdlib.h>
  46. #include "OsWrapper.h"
  47. /**
  48. * Start a new thread
  49. * @param fn the function to run, must be of the correct signature
  50. * @param parameter pointer to the function parameter, can be NULL
  51. */
  52. void Thread_start(thread_fn fn, void* parameter)
  53. {
  54. #if defined(_WIN32) || defined(_WIN64)
  55. thread_type thread = NULL;
  56. #else
  57. thread_type thread = 0;
  58. pthread_attr_t attr;
  59. #endif
  60. FUNC_ENTRY;
  61. #if defined(_WIN32) || defined(_WIN64)
  62. thread = CreateThread(NULL, 0, fn, parameter, 0, NULL);
  63. CloseHandle(thread);
  64. #else
  65. pthread_attr_init(&attr);
  66. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  67. if (pthread_create(&thread, &attr, fn, parameter) != 0)
  68. thread = 0;
  69. pthread_attr_destroy(&attr);
  70. #endif
  71. FUNC_EXIT;
  72. }
  73. int Thread_set_name(const char* thread_name)
  74. {
  75. int rc = 0;
  76. #if defined(_WIN32) || defined(_WIN64)
  77. #define MAX_THREAD_NAME_LENGTH 30
  78. wchar_t wchars[MAX_THREAD_NAME_LENGTH];
  79. #endif
  80. FUNC_ENTRY;
  81. #if defined(_WIN32) || defined(_WIN64)
  82. /* Using NTDDI_VERSION rather than WINVER for more detailed version targeting */
  83. /* Can't get this conditional compilation to work so remove it for now */
  84. /*#if NTDDI_VERSION >= NTDDI_WIN10_RS1
  85. mbstowcs(wchars, thread_name, MAX_THREAD_NAME_LENGTH);
  86. rc = (int)SetThreadDescription(GetCurrentThread(), wchars);
  87. #endif*/
  88. #elif defined(OSX)
  89. /* pthread_setname_np __API_AVAILABLE(macos(10.6), ios(3.2)) */
  90. #if defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6
  91. rc = pthread_setname_np(thread_name);
  92. #endif
  93. #else
  94. #if defined(__GNUC__) && defined(__linux__)
  95. #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 12
  96. rc = pthread_setname_np(Thread_getid(), thread_name);
  97. #endif
  98. #endif
  99. #endif
  100. FUNC_EXIT_RC(rc);
  101. return rc;
  102. }
  103. /**
  104. * Create a new mutex
  105. * @param rc return code: 0 for success, negative otherwise
  106. * @return the new mutex
  107. */
  108. mutex_type Thread_create_mutex(int* rc)
  109. {
  110. mutex_type mutex = NULL;
  111. FUNC_ENTRY;
  112. *rc = -1;
  113. #if defined(_WIN32) || defined(_WIN64)
  114. mutex = CreateMutex(NULL, 0, NULL);
  115. *rc = (mutex == NULL) ? GetLastError() : 0;
  116. #else
  117. mutex = malloc(sizeof(pthread_mutex_t));
  118. if (mutex)
  119. *rc = pthread_mutex_init(mutex, NULL);
  120. #endif
  121. FUNC_EXIT_RC(*rc);
  122. return mutex;
  123. }
  124. /**
  125. * Lock a mutex which has alrea
  126. * @return completion code, 0 is success
  127. */
  128. int Thread_lock_mutex(mutex_type mutex)
  129. {
  130. int rc = -1;
  131. /* don't add entry/exit trace points as the stack log uses mutexes - recursion beckons */
  132. #if defined(_WIN32) || defined(_WIN64)
  133. /* WaitForSingleObject returns WAIT_OBJECT_0 (0), on success */
  134. rc = WaitForSingleObject(mutex, INFINITE);
  135. #else
  136. rc = pthread_mutex_lock(mutex);
  137. #endif
  138. return rc;
  139. }
  140. /**
  141. * Unlock a mutex which has already been locked
  142. * @param mutex the mutex
  143. * @return completion code, 0 is success
  144. */
  145. int Thread_unlock_mutex(mutex_type mutex)
  146. {
  147. int rc = -1;
  148. /* don't add entry/exit trace points as the stack log uses mutexes - recursion beckons */
  149. #if defined(_WIN32) || defined(_WIN64)
  150. /* if ReleaseMutex fails, the return value is 0 */
  151. if (ReleaseMutex(mutex) == 0)
  152. rc = GetLastError();
  153. else
  154. rc = 0;
  155. #else
  156. rc = pthread_mutex_unlock(mutex);
  157. #endif
  158. return rc;
  159. }
  160. /**
  161. * Destroy a mutex which has already been created
  162. * @param mutex the mutex
  163. */
  164. int Thread_destroy_mutex(mutex_type mutex)
  165. {
  166. int rc = 0;
  167. FUNC_ENTRY;
  168. #if defined(_WIN32) || defined(_WIN64)
  169. rc = CloseHandle(mutex);
  170. #else
  171. rc = pthread_mutex_destroy(mutex);
  172. free(mutex);
  173. #endif
  174. FUNC_EXIT_RC(rc);
  175. return rc;
  176. }
  177. /**
  178. * Get the thread id of the thread from which this function is called
  179. * @return thread id, type varying according to OS
  180. */
  181. thread_id_type Thread_getid(void)
  182. {
  183. #if defined(_WIN32) || defined(_WIN64)
  184. return GetCurrentThreadId();
  185. #else
  186. return pthread_self();
  187. #endif
  188. }
  189. /**
  190. * Create a new semaphore
  191. * @param rc return code: 0 for success, negative otherwise
  192. * @return the new condition variable
  193. */
  194. sem_type Thread_create_sem(int *rc)
  195. {
  196. sem_type sem = NULL;
  197. FUNC_ENTRY;
  198. *rc = -1;
  199. #if defined(_WIN32) || defined(_WIN64)
  200. sem = CreateEvent(
  201. NULL, /* default security attributes */
  202. FALSE, /* manual-reset event? */
  203. FALSE, /* initial state is nonsignaled */
  204. NULL /* object name */
  205. );
  206. *rc = (sem == NULL) ? GetLastError() : 0;
  207. #elif defined(OSX)
  208. sem = dispatch_semaphore_create(0L);
  209. *rc = (sem == NULL) ? -1 : 0;
  210. #else
  211. sem = malloc(sizeof(sem_t));
  212. if (sem)
  213. *rc = sem_init(sem, 0, 0);
  214. #endif
  215. FUNC_EXIT_RC(*rc);
  216. return sem;
  217. }
  218. /**
  219. * Wait for a semaphore to be posted, or timeout.
  220. * @param sem the semaphore
  221. * @param timeout the maximum time to wait, in milliseconds
  222. * @return completion code
  223. */
  224. int Thread_wait_sem(sem_type sem, int timeout)
  225. {
  226. /* sem_timedwait is the obvious call to use, but seemed not to work on the Viper,
  227. * so I've used trywait in a loop instead. Ian Craggs 23/7/2010
  228. */
  229. int rc = -1;
  230. #if !defined(_WIN32) && !defined(_WIN64) && !defined(OSX)
  231. #define USE_TRYWAIT
  232. #if defined(USE_TRYWAIT)
  233. int i = 0;
  234. useconds_t interval = 10000; /* 10000 microseconds: 10 milliseconds */
  235. int count = (1000 * timeout) / interval; /* how many intervals in timeout period */
  236. #else
  237. struct timespec ts;
  238. #endif
  239. #endif
  240. FUNC_ENTRY;
  241. #if defined(_WIN32) || defined(_WIN64)
  242. /* returns 0 (WAIT_OBJECT_0) on success, non-zero (WAIT_TIMEOUT) if timeout occurred */
  243. rc = WaitForSingleObject(sem, timeout < 0 ? 0 : timeout);
  244. if (rc == WAIT_TIMEOUT)
  245. rc = ETIMEDOUT;
  246. #elif defined(OSX)
  247. /* returns 0 on success, non-zero if timeout occurred */
  248. rc = (int)dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, (int64_t)timeout*1000000L));
  249. if (rc != 0)
  250. rc = ETIMEDOUT;
  251. #elif defined(USE_TRYWAIT)
  252. while (++i < count && (rc = sem_trywait(sem)) != 0)
  253. {
  254. if (rc == -1 && ((rc = errno) != EAGAIN))
  255. {
  256. rc = 0;
  257. break;
  258. }
  259. usleep(interval); /* microseconds - .1 of a second */
  260. }
  261. #else
  262. /* We have to use CLOCK_REALTIME rather than MONOTONIC for sem_timedwait interval.
  263. * Does this make it susceptible to system clock changes?
  264. * The intervals are small enough, and repeated, that I think it's not an issue.
  265. */
  266. if (clock_gettime(CLOCK_REALTIME, &ts) != -1)
  267. {
  268. ts.tv_sec += timeout;
  269. rc = sem_timedwait(sem, &ts);
  270. }
  271. #endif
  272. FUNC_EXIT_RC(rc);
  273. return rc;
  274. }
  275. /**
  276. * Check to see if a semaphore has been posted, without waiting
  277. * The semaphore will be unchanged, if the return value is false.
  278. * The semaphore will have been decremented, if the return value is true.
  279. * @param sem the semaphore
  280. * @return 0 (false) or 1 (true)
  281. */
  282. int Thread_check_sem(sem_type sem)
  283. {
  284. #if defined(_WIN32) || defined(_WIN64)
  285. /* if the return value is not 0, the semaphore will not have been decremented */
  286. return WaitForSingleObject(sem, 0) == WAIT_OBJECT_0;
  287. #elif defined(OSX)
  288. /* if the return value is not 0, the semaphore will not have been decremented */
  289. return dispatch_semaphore_wait(sem, DISPATCH_TIME_NOW) == 0;
  290. #else
  291. /* If the call was unsuccessful, the state of the semaphore shall be unchanged,
  292. * and the function shall return a value of -1 */
  293. return sem_trywait(sem) == 0;
  294. #endif
  295. }
  296. /**
  297. * Post a semaphore
  298. * @param sem the semaphore
  299. * @return 0 on success
  300. */
  301. int Thread_post_sem(sem_type sem)
  302. {
  303. int rc = 0;
  304. FUNC_ENTRY;
  305. #if defined(_WIN32) || defined(_WIN64)
  306. if (SetEvent(sem) == 0)
  307. rc = GetLastError();
  308. #elif defined(OSX)
  309. rc = (int)dispatch_semaphore_signal(sem);
  310. #else
  311. int val;
  312. int rc1 = sem_getvalue(sem, &val);
  313. if (rc1 != 0)
  314. rc = errno;
  315. else if (val == 0 && sem_post(sem) == -1)
  316. rc = errno;
  317. #endif
  318. FUNC_EXIT_RC(rc);
  319. return rc;
  320. }
  321. /**
  322. * Destroy a semaphore which has already been created
  323. * @param sem the semaphore
  324. */
  325. int Thread_destroy_sem(sem_type sem)
  326. {
  327. int rc = 0;
  328. FUNC_ENTRY;
  329. #if defined(_WIN32) || defined(_WIN64)
  330. rc = CloseHandle(sem);
  331. #elif defined(OSX)
  332. dispatch_release(sem);
  333. #else
  334. rc = sem_destroy(sem);
  335. free(sem);
  336. #endif
  337. FUNC_EXIT_RC(rc);
  338. return rc;
  339. }
  340. #if !defined(_WIN32) && !defined(_WIN64)
  341. /**
  342. * Create a new condition variable
  343. * @return the condition variable struct
  344. */
  345. cond_type Thread_create_cond(int *rc)
  346. {
  347. cond_type condvar = NULL;
  348. pthread_condattr_t attr;
  349. FUNC_ENTRY;
  350. *rc = -1;
  351. pthread_condattr_init(&attr);
  352. #if 0
  353. /* in theory, a monotonic clock should be able to be used. However on at least
  354. * one system reported, even though setclock() reported success, it didn't work.
  355. */
  356. if ((rc = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) == 0)
  357. use_clock_monotonic = 1;
  358. else
  359. Log(LOG_ERROR, -1, "Error %d calling pthread_condattr_setclock(CLOCK_MONOTONIC)", rc);
  360. #endif
  361. condvar = malloc(sizeof(cond_type_struct));
  362. if (condvar)
  363. {
  364. *rc = pthread_cond_init(&condvar->cond, &attr);
  365. *rc = pthread_mutex_init(&condvar->mutex, NULL);
  366. }
  367. FUNC_EXIT_RC(*rc);
  368. return condvar;
  369. }
  370. /**
  371. * Signal a condition variable
  372. * @return completion code
  373. */
  374. int Thread_signal_cond(cond_type condvar)
  375. {
  376. int rc = 0;
  377. FUNC_ENTRY;
  378. pthread_mutex_lock(&condvar->mutex);
  379. rc = pthread_cond_signal(&condvar->cond);
  380. pthread_mutex_unlock(&condvar->mutex);
  381. FUNC_EXIT_RC(rc);
  382. return rc;
  383. }
  384. /**
  385. * Wait with a timeout (ms) for condition variable
  386. * @return 0 for success, ETIMEDOUT otherwise
  387. */
  388. int Thread_wait_cond(cond_type condvar, int timeout_ms)
  389. {
  390. int rc = 0;
  391. struct timespec cond_timeout;
  392. struct timespec interval;
  393. FUNC_ENTRY;
  394. interval.tv_sec = timeout_ms / 1000;
  395. interval.tv_nsec = (timeout_ms % 1000) * 1000000L;
  396. #if defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 /* for older versions of MacOS */
  397. struct timeval cur_time;
  398. gettimeofday(&cur_time, NULL);
  399. cond_timeout.tv_sec = cur_time.tv_sec;
  400. cond_timeout.tv_nsec = cur_time.tv_usec * 1000;
  401. #else
  402. clock_gettime(CLOCK_REALTIME, &cond_timeout);
  403. #endif
  404. cond_timeout.tv_sec += interval.tv_sec;
  405. cond_timeout.tv_nsec += (timeout_ms % 1000) * 1000000L;
  406. if (cond_timeout.tv_nsec >= 1000000000L)
  407. {
  408. cond_timeout.tv_sec++;
  409. cond_timeout.tv_nsec += (cond_timeout.tv_nsec - 1000000000L);
  410. }
  411. pthread_mutex_lock(&condvar->mutex);
  412. rc = pthread_cond_timedwait(&condvar->cond, &condvar->mutex, &cond_timeout);
  413. pthread_mutex_unlock(&condvar->mutex);
  414. FUNC_EXIT_RC(rc);
  415. return rc;
  416. }
  417. /**
  418. * Destroy a condition variable
  419. * @return completion code
  420. */
  421. int Thread_destroy_cond(cond_type condvar)
  422. {
  423. int rc = 0;
  424. rc = pthread_mutex_destroy(&condvar->mutex);
  425. rc = pthread_cond_destroy(&condvar->cond);
  426. free(condvar);
  427. return rc;
  428. }
  429. #endif
  430. #if defined(THREAD_UNIT_TESTS)
  431. #if defined(_WIN32) || defined(_WINDOWS)
  432. #define mqsleep(A) Sleep(1000*A)
  433. #define START_TIME_TYPE DWORD
  434. static DWORD start_time = 0;
  435. START_TIME_TYPE start_clock(void)
  436. {
  437. return GetTickCount();
  438. }
  439. #elif defined(AIX)
  440. #define mqsleep sleep
  441. #define START_TIME_TYPE struct timespec
  442. START_TIME_TYPE start_clock(void)
  443. {
  444. static struct timespec start;
  445. clock_gettime(CLOCK_REALTIME, &start);
  446. return start;
  447. }
  448. #else
  449. #define mqsleep sleep
  450. #define START_TIME_TYPE struct timeval
  451. /* TODO - unused - remove? static struct timeval start_time; */
  452. START_TIME_TYPE start_clock(void)
  453. {
  454. struct timeval start_time;
  455. gettimeofday(&start_time, NULL);
  456. return start_time;
  457. }
  458. #endif
  459. #if defined(_WIN32)
  460. long elapsed(START_TIME_TYPE start_time)
  461. {
  462. return GetTickCount() - start_time;
  463. }
  464. #elif defined(AIX)
  465. #define assert(a)
  466. long elapsed(struct timespec start)
  467. {
  468. struct timespec now, res;
  469. clock_gettime(CLOCK_REALTIME, &now);
  470. ntimersub(now, start, res);
  471. return (res.tv_sec)*1000L + (res.tv_nsec)/1000000L;
  472. }
  473. #else
  474. long elapsed(START_TIME_TYPE start_time)
  475. {
  476. struct timeval now, res;
  477. gettimeofday(&now, NULL);
  478. timersub(&now, &start_time, &res);
  479. return (res.tv_sec)*1000 + (res.tv_usec)/1000;
  480. }
  481. #endif
  482. int tests = 0, failures = 0;
  483. void myassert(char* filename, int lineno, char* description, int value, char* format, ...)
  484. {
  485. ++tests;
  486. if (!value)
  487. {
  488. va_list args;
  489. ++failures;
  490. printf("Assertion failed, file %s, line %d, description: %s\n", filename, lineno, description);
  491. va_start(args, format);
  492. vprintf(format, args);
  493. va_end(args);
  494. //cur_output += sprintf(cur_output, "<failure type=\"%s\">file %s, line %d </failure>\n",
  495. // description, filename, lineno);
  496. }
  497. else
  498. printf("Assertion succeeded, file %s, line %d, description: %s\n", filename, lineno, description);
  499. }
  500. #define assert(a, b, c, d) myassert(__FILE__, __LINE__, a, b, c, d)
  501. #define assert1(a, b, c, d, e) myassert(__FILE__, __LINE__, a, b, c, d, e)
  502. #include <stdio.h>
  503. thread_return_type cond_secondary(void* n)
  504. {
  505. int rc = 0;
  506. cond_type cond = n;
  507. printf("This should return immediately as it was posted already\n");
  508. rc = Thread_wait_cond(cond, 99999);
  509. assert("rc 1 from wait_cond", rc == 1, "rc was %d", rc);
  510. printf("This should hang around a few seconds\n");
  511. rc = Thread_wait_cond(cond, 99999);
  512. assert("rc 1 from wait_cond", rc == 1, "rc was %d", rc);
  513. printf("Secondary cond thread ending\n");
  514. return 0;
  515. }
  516. int cond_test()
  517. {
  518. int rc = 0;
  519. cond_type cond = Thread_create_cond();
  520. printf("Post secondary so it should return immediately\n");
  521. rc = Thread_signal_cond(cond);
  522. assert("rc 0 from signal cond", rc == 0, "rc was %d", rc);
  523. printf("Starting secondary thread\n");
  524. Thread_start(cond_secondary, (void*)cond);
  525. sleep(3);
  526. printf("post secondary\n");
  527. rc = Thread_signal_cond(cond);
  528. assert("rc 1 from signal cond", rc == 1, "rc was %d", rc);
  529. sleep(3);
  530. printf("Main thread ending\n");
  531. return failures;
  532. }
  533. thread_return_type sem_secondary(void* n)
  534. {
  535. int rc = 0;
  536. sem_type sem = n;
  537. printf("Secondary semaphore pointer %p\n", sem);
  538. rc = Thread_check_sem(sem);
  539. assert("rc 1 from check_sem", rc == 1, "rc was %d", rc);
  540. printf("Secondary thread about to wait\n");
  541. rc = Thread_wait_sem(sem, 99999);
  542. printf("Secondary thread returned from wait %d\n", rc);
  543. printf("Secondary thread about to wait\n");
  544. rc = Thread_wait_sem(sem, 99999);
  545. printf("Secondary thread returned from wait %d\n", rc);
  546. printf("Secondary check sem %d\n", Thread_check_sem(sem));
  547. printf("Secondary thread ending\n");
  548. return 0;
  549. }
  550. int sem_test()
  551. {
  552. int rc = 0;
  553. sem_type sem = Thread_create_sem();
  554. printf("Primary semaphore pointer %p\n", sem);
  555. rc = Thread_check_sem(sem);
  556. assert("rc 0 from check_sem", rc == 0, "rc was %d\n", rc);
  557. printf("post secondary so then check should be 1\n");
  558. rc = Thread_post_sem(sem);
  559. assert("rc 0 from post_sem", rc == 0, "rc was %d\n", rc);
  560. rc = Thread_check_sem(sem);
  561. assert("rc 1 from check_sem", rc == 1, "rc was %d", rc);
  562. printf("Starting secondary thread\n");
  563. Thread_start(sem_secondary, (void*)sem);
  564. sleep(3);
  565. rc = Thread_check_sem(sem);
  566. assert("rc 1 from check_sem", rc == 1, "rc was %d", rc);
  567. printf("post secondary\n");
  568. rc = Thread_post_sem(sem);
  569. assert("rc 1 from post_sem", rc == 1, "rc was %d", rc);
  570. sleep(3);
  571. printf("Main thread ending\n");
  572. return failures;
  573. }
  574. int main(int argc, char *argv[])
  575. {
  576. sem_test();
  577. //cond_test();
  578. }
  579. #endif