Home | History | Annotate | Download | only in profiling
      1 // Copyright 2017 The Gemmlowp Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // pthread_everywhere.h: Either includes <pthread.h> or implements a
     16 // subset of pthread functionality on top of C++11 <thread> for portability.
     17 
     18 #ifndef GEMMLOWP_PROFILING_PTHREAD_EVERYWHERE_H_
     19 #define GEMMLOWP_PROFILING_PTHREAD_EVERYWHERE_H_
     20 
     21 #ifndef _WIN32
     22 #define GEMMLOWP_USE_PTHREAD
     23 #endif
     24 
     25 #if defined GEMMLOWP_USE_PTHREAD
     26 #include <pthread.h>
     27 #else
     28 // Implement a small subset of pthread on top of C++11 threads.
     29 // The function signatures differ from true pthread functions in two ways:
     30 //  - True pthread functions return int error codes, ours return void.
     31 //    Rationale: the c++11 <thread> equivalent functions return void
     32 //    and use exceptions to report errors; we don't want to deal with
     33 //    exceptions in this code, so we couldn't meaningfully return errors
     34 //    in the polyfill. Also, the gemmlowp code using these pthread functions
     35 //    never checks their return values anyway.
     36 //  - True pthread *_create/*_init functions take pointers to 'attribute'
     37 //    structs; ours take nullptr_t. That is because gemmlowp always passes
     38 //    nullptr at the moment, so any support we would code for non-null
     39 //    attribs would be unused.
     40 #include <condition_variable>
     41 #include <cstddef>
     42 #include <mutex>
     43 #include <thread>
     44 namespace gemmlowp {
     45 using pthread_t = std::thread *;
     46 using pthread_mutex_t = std::mutex *;
     47 using pthread_cond_t = std::condition_variable *;
     48 inline void pthread_create(pthread_t *thread, std::nullptr_t,
     49                            void *(*start_routine)(void *), void *arg) {
     50   *thread = new std::thread(start_routine, arg);
     51 }
     52 inline void pthread_join(pthread_t thread, std::nullptr_t) { thread->join(); }
     53 inline void pthread_mutex_init(pthread_mutex_t *mutex, std::nullptr_t) {
     54   *mutex = new std::mutex;
     55 }
     56 inline void pthread_mutex_lock(pthread_mutex_t *mutex) { (*mutex)->lock(); }
     57 inline void pthread_mutex_unlock(pthread_mutex_t *mutex) { (*mutex)->unlock(); }
     58 inline void pthread_mutex_destroy(pthread_mutex_t *mutex) { delete *mutex; }
     59 inline void pthread_cond_init(pthread_cond_t *cond, std::nullptr_t) {
     60   *cond = new std::condition_variable;
     61 }
     62 inline void pthread_cond_signal(pthread_cond_t *cond) { (*cond)->notify_one(); }
     63 inline void pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
     64   std::unique_lock<std::mutex> lock(**mutex, std::adopt_lock);
     65   (*cond)->wait(lock);
     66   // detach lock from mutex so when we leave this conext
     67   // the lock is not released
     68   lock.release();
     69 }
     70 inline void pthread_cond_destroy(pthread_cond_t *cond) { delete *cond; }
     71 }  // end namespace gemmlowp
     72 #endif
     73 
     74 #endif  // GEMMLOWP_PROFILING_PTHREAD_EVERYWHERE_H_
     75