12d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===-- sanitizer_pthread_wrappers.h ----------------------------*- C++ -*-===//
22d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
32d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//                     The LLVM Compiler Infrastructure
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
52d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is distributed under the University of Illinois Open Source
62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// License. See LICENSE.TXT for details.
72d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===//
92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// This file is a part of *Sanitizer runtime.
112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// It provides handy wrappers for thread manipulation, that:
122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//  a) assert on any failure rather than returning an error code
132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//  b) defines pthread-like interface on platforms where where <pthread.h>
142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//     is not supplied by default.
152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines//===----------------------------------------------------------------------===//
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#ifndef SANITIZER_PTHREAD_WRAPPERS_H
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#define SANITIZER_PTHREAD_WRAPPERS_H
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_test_utils.h"
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# include <pthread.h>
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// Simply forward the arguments and check that the pthread functions succeed.
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# define PTHREAD_CREATE(a, b, c, d) ASSERT_EQ(0, pthread_create(a, b, c, d))
272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines# define PTHREAD_JOIN(a, b) ASSERT_EQ(0, pthread_join(a, b))
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef HANDLE pthread_t;
302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct PthreadHelperCreateThreadInfo {
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void *(*start_routine)(void *);
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void *arg;
342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesinline DWORD WINAPI PthreadHelperThreadProc(void *arg) {
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  PthreadHelperCreateThreadInfo *start_data =
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      reinterpret_cast<PthreadHelperCreateThreadInfo*>(arg);
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void *ret = (start_data->start_routine)(start_data->arg);
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  delete start_data;
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return (DWORD)ret;
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesinline void PTHREAD_CREATE(pthread_t *thread, void *attr,
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                           void *(*start_routine)(void *), void *arg) {
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(0, attr) << "Thread attributes are not supported yet.";
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  PthreadHelperCreateThreadInfo *data = new PthreadHelperCreateThreadInfo;
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  data->start_routine = start_routine;
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  data->arg = arg;
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *thread = CreateThread(0, 0, PthreadHelperThreadProc, data, 0, 0);
512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_NE(nullptr, *thread) << "Failed to create a thread.";
522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesinline void PTHREAD_JOIN(pthread_t thread, void **value_ptr) {
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(0, value_ptr) << "Nonzero value_ptr is not supported yet.";
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(WAIT_OBJECT_0, WaitForSingleObject(thread, INFINITE));
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_NE(0, CloseHandle(thread));
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesinline void pthread_exit(void *retval) {
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ASSERT_EQ(0, retval) << "Nonzero retval is not supported yet.";
622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ExitThread((DWORD)retval);
632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // _WIN32
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif  // SANITIZER_PTHREAD_WRAPPERS_H
67