• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_thread.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /**************************************************************************
00025   Generic threads interface
00026 
00027 **************************************************************************/
00028 
00029 #ifndef _INK_THREAD_H
00030 #define _INK_THREAD_H
00031 
00032 
00033 #include "ink_hrtime.h"
00034 #include "ink_defs.h"
00035 #include <sched.h>
00036 
00037 
00038 //////////////////////////////////////////////////////////////////////////////
00039 //
00040 //      The POSIX threads interface
00041 //
00042 //////////////////////////////////////////////////////////////////////////////
00043 
00044 #if defined(POSIX_THREAD)
00045 #include <pthread.h>
00046 #include <signal.h>
00047 #include <semaphore.h>
00048 
00049 #if HAVE_PTHREAD_NP_H
00050 #include <pthread_np.h>
00051 #endif
00052 
00053 #define INK_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
00054 
00055 typedef pthread_t ink_thread;
00056 typedef pthread_cond_t ink_cond;
00057 typedef pthread_key_t ink_thread_key;
00058 
00059 // Darwin has a sem_init stub that returns ENOSYS. Rather than bodge around doing runtime
00060 // detection, just emulate on Darwin.
00061 #if defined(darwin)
00062 #define TS_EMULATE_ANON_SEMAPHORES 1
00063 #endif
00064 
00065 struct ink_semaphore {
00066 #if TS_EMULATE_ANON_SEMAPHORES
00067   sem_t * sema;
00068   int64_t semid;
00069 #else
00070   sem_t sema;
00071 #endif
00072 
00073   sem_t * get() {
00074 #if TS_EMULATE_ANON_SEMAPHORES
00075     return sema;
00076 #else
00077     return &sema;
00078 #endif
00079   }
00080 };
00081 
00082 #endif /* #if defined(POSIX_THREAD) */
00083 
00084 /*******************************************************************
00085  *** Condition variables
00086  ******************************************************************/
00087 
00088 #ifdef POSIX_THREAD_10031c
00089 typedef struct timespec ink_timestruc;
00090 #else
00091 typedef timestruc_t ink_timestruc;
00092 #endif
00093 
00094 #include "ink_mutex.h"
00095 #include <errno.h>
00096 #include "ink_assert.h"
00097 
00098 //////////////////////////////////////////////////////////////////////////////
00099 //
00100 //      The POSIX threads interface
00101 //
00102 //////////////////////////////////////////////////////////////////////////////
00103 #if defined(POSIX_THREAD)
00104 
00105 static inline void
00106 ink_thread_key_create(ink_thread_key * key, void (*destructor) (void *value))
00107 {
00108   ink_assert(!pthread_key_create(key, destructor));
00109 }
00110 
00111 static inline void
00112 ink_thread_setspecific(ink_thread_key key, void *value)
00113 {
00114   ink_assert(!pthread_setspecific(key, value));
00115 }
00116 
00117 static inline void *
00118 ink_thread_getspecific(ink_thread_key key)
00119 {
00120   return pthread_getspecific(key);
00121 }
00122 
00123 static inline void
00124 ink_thread_key_delete(ink_thread_key key)
00125 {
00126   ink_assert(!pthread_key_delete(key));
00127 }
00128 
00129 
00130 static inline ink_thread
00131 ink_thread_create(void *(*f) (void *), void *a, int detached = 0, size_t stacksize = 0)
00132 {
00133   ink_thread t;
00134   int ret;
00135   pthread_attr_t attr;
00136 
00137   pthread_attr_init(&attr);
00138   pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
00139 
00140   if (stacksize) {
00141     pthread_attr_setstacksize(&attr, stacksize);
00142   }
00143 
00144   if (detached) {
00145     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00146   }
00147 
00148   ret = pthread_create(&t, &attr, f, a);
00149   ink_assert(ret == 0);
00150   pthread_attr_destroy(&attr);
00151 
00152   /**
00153    * Fix for INKqa10118.
00154    * If the thread has not been created successfully return 0.
00155    */
00156   return ret ? (ink_thread) 0 : t;
00157 }
00158 
00159 static inline void
00160 ink_thread_cancel(ink_thread who)
00161 {
00162 #if defined(freebsd)
00163   (void) who;
00164   ink_assert(!"not supported");
00165 #else
00166   int ret = pthread_cancel(who);
00167   ink_assert(ret == 0);
00168 #endif
00169 }
00170 
00171 static inline void *
00172 ink_thread_join(ink_thread t)
00173 {
00174   void *r;
00175   ink_assert(!pthread_join(t, &r));
00176   return r;
00177 }
00178 
00179 static inline ink_thread
00180 ink_thread_self()
00181 {
00182   return (pthread_self());
00183 }
00184 
00185 static inline int
00186 ink_thread_get_priority(ink_thread t, int *priority)
00187 {
00188 #if defined(freebsd)
00189   (void) t;
00190   (void) priority;
00191   ink_assert(!"not supported");
00192   return -1;
00193 #else
00194   int policy;
00195   struct sched_param param;
00196   int res = pthread_getschedparam(t, &policy, &param);
00197   *priority = param.sched_priority;
00198   return res;
00199 #endif
00200 }
00201 
00202 static inline int
00203 ink_thread_sigsetmask(int how, const sigset_t * set, sigset_t * oset)
00204 {
00205   return (pthread_sigmask(how, set, oset));
00206 }
00207 
00208 /*******************************************************************
00209  * Posix Semaphores
00210  ******************************************************************/
00211 
00212 void ink_sem_init(ink_semaphore * sp, unsigned int count);
00213 void ink_sem_destroy(ink_semaphore * sp);
00214 void ink_sem_wait(ink_semaphore * sp);
00215 bool ink_sem_trywait(ink_semaphore * sp);
00216 void ink_sem_post(ink_semaphore * sp);
00217 
00218 /*******************************************************************
00219  * Posix Condition Variables
00220  ******************************************************************/
00221 
00222 static inline void
00223 ink_cond_init(ink_cond * cp)
00224 {
00225   ink_assert(pthread_cond_init(cp, NULL) == 0);
00226 }
00227 
00228 static inline void
00229 ink_cond_destroy(ink_cond * cp)
00230 {
00231   ink_assert(pthread_cond_destroy(cp) == 0);
00232 }
00233 
00234 static inline void
00235 ink_cond_wait(ink_cond * cp, ink_mutex * mp)
00236 {
00237   ink_assert(pthread_cond_wait(cp, mp) == 0);
00238 }
00239 static inline int
00240 ink_cond_timedwait(ink_cond * cp, ink_mutex * mp, ink_timestruc * t)
00241 {
00242   int err;
00243   while (EINTR == (err = pthread_cond_timedwait(cp, mp, t)));
00244 #if defined(freebsd) || defined(openbsd)
00245   ink_assert((err == 0) || (err == ETIMEDOUT));
00246 #else
00247   ink_assert((err == 0) || (err == ETIME) || (err == ETIMEDOUT));
00248 #endif
00249   return err;
00250 }
00251 
00252 static inline void
00253 ink_cond_signal(ink_cond * cp)
00254 {
00255   ink_assert(pthread_cond_signal(cp) == 0);
00256 }
00257 
00258 static inline void
00259 ink_cond_broadcast(ink_cond * cp)
00260 {
00261   ink_assert(pthread_cond_broadcast(cp) == 0);
00262 }
00263 
00264 static inline void
00265 ink_thr_yield()
00266 {
00267   ink_assert(!sched_yield());
00268 }
00269 
00270 static inline void
00271 ink_thread_exit(void *status)
00272 {
00273   pthread_exit(status);
00274 }
00275 
00276 // This define is from Linux's <sys/prctl.h> and is most likely very
00277 // Linux specific... Feel free to add support for other platforms
00278 // that has a feature to give a thread specific name / tag.
00279 static inline void
00280 ink_set_thread_name(const char* name ATS_UNUSED)
00281 {
00282 #if defined(HAVE_PTHREAD_SETNAME_NP_1)
00283   pthread_setname_np(name);
00284 #elif defined(HAVE_PTHREAD_SETNAME_NP_2)
00285   pthread_setname_np(pthread_self(), name);
00286 #elif defined(HAVE_PTHREAD_SET_NAME_NP_2)
00287   pthread_set_name_np(pthread_self(), name);
00288 #elif defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_NAME)
00289   prctl(PR_SET_NAME, name, 0, 0, 0);
00290 #endif
00291 }
00292 
00293 #endif /* #if defined(POSIX_THREAD) */
00294 
00295 #endif /*_INK_THREAD_H*/

Generated by  doxygen 1.7.1