(file) Return to Thread.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 mike  1.2 //%/////////////////////////////////////////////////////////////////////////////
  2           //
  3 kumpf 1.17 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
  4            // The Open Group, Tivoli Systems
  5 mike  1.2  //
  6            // Permission is hereby granted, free of charge, to any person obtaining a copy
  7 chip  1.11 // of this software and associated documentation files (the "Software"), to
  8            // deal in the Software without restriction, including without limitation the
  9            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 10 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 11            // furnished to do so, subject to the following conditions:
 12 kumpf 1.17 // 
 13 chip  1.11 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 14 mike  1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 15            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 16 chip  1.11 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 17            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 18            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 19 mike  1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 20            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 21            //
 22            //==============================================================================
 23            //
 24            // Author: Mike Day (mdday@us.ibm.com)
 25            //
 26            // Modified By: Rudy Schuet (rudy.schuet@compaq.com) 11/12/01
 27 chip  1.11 //              added nsk platform support
 28 mike  1.2  //
 29            //%/////////////////////////////////////////////////////////////////////////////
 30            
 31            #include "Thread.h"
 32            #include <Pegasus/Common/IPC.h>
 33 kumpf 1.14 #include <Pegasus/Common/Tracer.h>
 34 mike  1.2  
 35            #if defined(PEGASUS_OS_TYPE_WINDOWS)
 36 chip  1.11 # include "ThreadWindows.cpp"
 37 mike  1.2  #elif defined(PEGASUS_OS_TYPE_UNIX)
 38            # include "ThreadUnix.cpp"
 39            #elif defined(PEGASUS_OS_TYPE_NSK)
 40            # include "ThreadNsk.cpp"
 41            #else
 42            # error "Unsupported platform"
 43            #endif
 44            
 45            PEGASUS_NAMESPACE_BEGIN
 46            
 47 chip  1.11 void thread_data::default_delete(void * data)
 48            {
 49 mike  1.2     if( data != NULL)
 50 chip  1.11       ::operator delete(data);
 51 mike  1.2  }
 52            
 53            Boolean Thread::_signals_blocked = false;
 54            
 55            // for non-native implementations
 56 chip  1.11 #ifndef PEGASUS_THREAD_CLEANUP_NATIVE
 57 mike  1.2  void Thread::cleanup_push( void (*routine)(void *), void *parm) throw(IPCException)
 58            {
 59                cleanup_handler *cu = new cleanup_handler(routine, parm);
 60 chip  1.11     try
 61                {
 62            	_cleanup.insert_first(cu);
 63                }
 64                catch(IPCException&)
 65 mike  1.2      {
 66            	delete cu;
 67 chip  1.11 	throw;
 68 mike  1.2      }
 69                return;
 70            }
 71 chip  1.11 	
 72 mike  1.2  void Thread::cleanup_pop(Boolean execute) throw(IPCException)
 73            {
 74                cleanup_handler *cu ;
 75 chip  1.11     try
 76                {
 77 mike  1.2  	cu = _cleanup.remove_first() ;
 78                }
 79 chip  1.11     catch(IPCException&)
 80 mike  1.2      {
 81 chip  1.11 	PEGASUS_ASSERT(0);
 82 mike  1.2       }
 83                if(execute == true)
 84            	cu->execute();
 85                delete cu;
 86            }
 87 chip  1.11 		
 88 mike  1.2  #endif
 89            
 90            
 91 kumpf 1.8  //thread_data *Thread::put_tsd(const Sint8 *key, void (*delete_func)(void *), Uint32 size, void *value) throw(IPCException)
 92 mike  1.2  
 93            
 94 chip  1.11 #ifndef PEGASUS_THREAD_EXIT_NATIVE
 95            void Thread::exit_self(PEGASUS_THREAD_RETURN exit_code)
 96            {
 97                // execute the cleanup stack and then return
 98 mike  1.2     while( _cleanup.count() )
 99               {
100 chip  1.11        try
101                   {
102            	   cleanup_pop(true);
103                   }
104                   catch(IPCException&)
105                   {
106            	  PEGASUS_ASSERT(0);
107            	  break;
108 mike  1.2         }
109               }
110               _exit_code = exit_code;
111               exit_thread(exit_code);
112 mday  1.4     _handle.thid = 0;
113 mike  1.2  }
114            
115            
116            #endif
117            
118 mday  1.20 DQueue<ThreadPool> ThreadPool::_pools(true);
119            
120            
121            void ThreadPool::kill_idle_threads(void)
122            {
123               static struct timeval now, last = {0, 0};
124               
125               pegasus_gettimeofday(&now);
126               if(now.tv_sec - last.tv_sec > 5)
127               {
128                  _pools.lock();
129                  ThreadPool *p = _pools.next(0);
130                  while(p != 0)
131                  {
132            	 try 
133            	 {
134            	    p->kill_dead_threads();
135            	 }
136            	 catch(...)
137            	 {
138            	 }
139 mday  1.20 	 p = _pools.next(p);
140                  }
141                  _pools.unlock();
142                  pegasus_gettimeofday(&last);
143               }
144            }
145            
146            
147 mike  1.2  ThreadPool::ThreadPool(Sint16 initial_size,
148 kumpf 1.8  		       const Sint8 *key,
149 mike  1.2  		       Sint16 min,
150            		       Sint16 max,
151            		       struct timeval & alloc_wait,
152 chip  1.11 		       struct timeval & dealloc_wait,
153 mike  1.2  		       struct timeval & deadlock_detect)
154               : _max_threads(max), _min_threads(min),
155 mday  1.12      _current_threads(0),
156                 _pool(true), _running(true),
157 mike  1.2       _dead(true), _dying(0)
158            {
159               _allocate_wait.tv_sec = alloc_wait.tv_sec;
160               _allocate_wait.tv_usec = alloc_wait.tv_usec;
161 chip  1.11    _deallocate_wait.tv_sec = dealloc_wait.tv_sec;
162 mike  1.2     _deallocate_wait.tv_usec = dealloc_wait.tv_usec;
163               _deadlock_detect.tv_sec = deadlock_detect.tv_sec;
164               _deadlock_detect.tv_usec = deadlock_detect.tv_usec;
165               memset(_key, 0x00, 17);
166               if(key != 0)
167                  strncpy(_key, key, 16);
168 mday  1.21    if(_max_threads > 0 && _max_threads < initial_size)
169 mike  1.2        _max_threads = initial_size;
170               if(_min_threads > initial_size)
171                  _min_threads = initial_size;
172 chip  1.11 
173 mike  1.2     int i;
174               for(i = 0; i < initial_size; i++)
175               {
176                  _link_pool(_init_thread());
177               }
178 mday  1.20    _pools.insert_last(this);
179               
180 mike  1.2  }
181            
182 chip  1.11 
183 mike  1.2  
184            ThreadPool::~ThreadPool(void)
185            {
186 mday  1.19 
187 mday  1.20    _pools.remove(this);
188 mike  1.2     _dying++;
189 mday  1.12    Thread *th = 0;
190 kumpf 1.16    th = _pool.remove_first();
191 mike  1.2     while(th != 0)
192 chip  1.11    {
193 mike  1.2        Semaphore *sleep_sem = (Semaphore *)th->reference_tsd("sleep sem");
194            
195                  if(sleep_sem == 0)
196                  {
197            	 th->dereference_tsd();
198            	 throw NullPointer();
199                  }
200 chip  1.11 
201 mike  1.2        sleep_sem->signal();
202                  sleep_sem->signal();
203                  th->dereference_tsd();
204                  // signal the thread's sleep semaphore
205                  th->cancel();
206                  th->join();
207                  th->empty_tsd();
208                  delete th;
209                  th = _pool.remove_first();
210               }
211            
212               th = _running.remove_first();
213               while(th != 0)
214               {
215                  // signal the thread's sleep semaphore
216                  th->cancel();
217                  th->join();
218                  th->empty_tsd();
219                  delete th;
220                  th = _running.remove_first();
221               }
222 mike  1.2  
223               th = _dead.remove_first();
224               while(th != 0)
225               {
226                  // signal the thread's sleep semaphore
227                  th->cancel();
228                  th->join();
229                  th->empty_tsd();
230                  delete th;
231                  th = _dead.remove_first();
232               }
233 mday  1.20 
234 mike  1.2  }
235            
236 chip  1.11 // make this static to the class
237 mike  1.2  PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL ThreadPool::_loop(void *parm)
238            {
239 kumpf 1.14    PEG_METHOD_ENTER(TRC_THREAD, "ThreadPool::_loop");
240            
241 mike  1.2     Thread *myself = (Thread *)parm;
242               if(myself == 0)
243 kumpf 1.14    {
244                  PEG_METHOD_EXIT();
245 mike  1.2        throw NullPointer();
246 kumpf 1.14    }
247 mike  1.2     ThreadPool *pool = (ThreadPool *)myself->get_parm();
248 kumpf 1.14    if(pool == 0 ) 
249               {
250                  PEG_METHOD_EXIT();
251 mike  1.2        throw NullPointer();
252 kumpf 1.14    }
253 mike  1.5     Semaphore *sleep_sem = 0;
254 mday  1.13    Semaphore *blocking_sem = 0;
255               
256 mike  1.5     struct timeval *deadlock_timer = 0;
257 chip  1.11 
258               try
259 mike  1.2     {
260                  sleep_sem = (Semaphore *)myself->reference_tsd("sleep sem");
261                  myself->dereference_tsd();
262                  deadlock_timer = (struct timeval *)myself->reference_tsd("deadlock timer");
263 mday  1.22       myself->dereference_tsd(); 
264 mike  1.2     }
265 mike  1.6     catch(IPCException &)
266 mike  1.2     {
267 kumpf 1.14       PEG_METHOD_EXIT();
268 mike  1.2        myself->exit_self(0);
269               }
270 mday  1.30    catch(...)
271               {
272                  PEG_METHOD_EXIT();
273                  myself->exit_self(0);
274               }
275               
276 mike  1.2     if(sleep_sem == 0 || deadlock_timer == 0)
277 kumpf 1.14    {
278                  PEG_METHOD_EXIT();
279 mike  1.2        throw NullPointer();
280 kumpf 1.14    }
281 mike  1.2  
282               while(pool->_dying < 1)
283               {
284                  sleep_sem->wait();
285 mday  1.12         
286 mike  1.2        // when we awaken we reside on the running queue, not the pool queue
287                  if(pool->_dying > 0)
288            	 break;
289 chip  1.11 
290 mike  1.5        PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *_work)(void *) = 0;
291                  void *parm = 0;
292 mike  1.2  
293 chip  1.11       try
294 mike  1.2        {
295            	 _work = (PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *)(void *)) \
296            	    myself->reference_tsd("work func");
297            	 myself->dereference_tsd();
298            	 parm = myself->reference_tsd("work parm");
299            	 myself->dereference_tsd();
300 mday  1.13 	 blocking_sem = (Semaphore *)myself->reference_tsd("blocking sem");
301            	 myself->dereference_tsd();
302            
303 mike  1.2        }
304 mike  1.6        catch(IPCException &)
305 mike  1.2        {
306 kumpf 1.14 	 PEG_METHOD_EXIT();
307 mike  1.2  	 myself->exit_self(0);
308                  }
309 chip  1.11 
310 mike  1.2        if(_work == 0)
311 kumpf 1.14       {
312                     PEG_METHOD_EXIT();
313 mike  1.2  	 throw NullPointer();
314 kumpf 1.14       }
315 kumpf 1.24 
316                  if(_work ==
317                     (PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *)(void *)) &_undertaker)
318                  {
319 mday  1.23 	 _work(parm);
320 kumpf 1.24       }
321            
322 mike  1.2        gettimeofday(deadlock_timer, NULL);
323 mday  1.20       try 
324                  {
325            	 _work(parm);
326                  }
327                  catch(...)
328                  {
329            	 gettimeofday(deadlock_timer, NULL);
330                  }
331                  gettimeofday(deadlock_timer, NULL);
332 mday  1.13       if( blocking_sem != 0 )
333            	 blocking_sem->signal();
334                  
335 chip  1.11       // put myself back onto the available list
336                  try
337 mike  1.2        {
338            	 pool->_running.remove((void *)myself);
339            	 pool->_link_pool(myself);
340                  }
341 mike  1.6        catch(IPCException &)
342 mike  1.2        {
343 kumpf 1.14 	 PEG_METHOD_EXIT();
344 mike  1.2  	 myself->exit_self(0);
345                  }
346               }
347               // wait to be awakend by the thread pool destructor
348               sleep_sem->wait();
349               myself->test_cancel();
350 kumpf 1.14 
351               PEG_METHOD_EXIT();
352 mike  1.2     myself->exit_self(0);
353               return((PEGASUS_THREAD_RETURN)0);
354            }
355            
356            void ThreadPool::allocate_and_awaken(void *parm,
357            				     PEGASUS_THREAD_RETURN \
358 mday  1.13 				     (PEGASUS_THREAD_CDECL *work)(void *), 
359            				     Semaphore *blocking)
360            
361 mike  1.2     throw(IPCException)
362            {
363 kumpf 1.14    PEG_METHOD_ENTER(TRC_THREAD, "ThreadPool::allocate_and_awaken");
364 mike  1.2     struct timeval start;
365               gettimeofday(&start, NULL);
366 chip  1.11 
367 mike  1.2     Thread *th = _pool.remove_first();
368 mday  1.12    
369 mday  1.7     // wait for the right interval and try again
370               while(th == 0 && _dying < 1)
371 mike  1.2     {
372 mday  1.12       _check_deadlock(&start) ;
373                  
374 mday  1.21       if(_max_threads == 0 || _current_threads < _max_threads)
375 mike  1.2        {
376 mday  1.12 	 th = _init_thread();
377            	 continue;
378 mike  1.2        }
379 mday  1.12       pegasus_yield();
380 mday  1.7        th = _pool.remove_first();
381               }
382 chip  1.11 
383            
384 mike  1.2     if(_dying < 1)
385               {
386                  // initialize the thread data with the work function and parameters
387 kumpf 1.14       Tracer::trace(TRC_THREAD, Tracer::LEVEL4,
388                      "Initializing thread with work function and parameters: parm = %p",
389                      parm);
390            
391 kumpf 1.15       th->delete_tsd("work func");
392 chip  1.11       th->put_tsd("work func", NULL,
393 mike  1.2  		  sizeof( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *)(void *)),
394            		  (void *)work);
395 kumpf 1.15       th->delete_tsd("work parm");
396 mike  1.2        th->put_tsd("work parm", NULL, sizeof(void *), parm);
397 kumpf 1.15       th->delete_tsd("blocking sem");
398 mday  1.13       if(blocking != 0 )
399            	 th->put_tsd("blocking sem", NULL, sizeof(Semaphore *), blocking);
400                  
401 chip  1.11       // put the thread on the running list
402 mike  1.2        _running.insert_first(th);
403            
404                  // signal the thread's sleep semaphore to awaken it
405                  Semaphore *sleep_sem = (Semaphore *)th->reference_tsd("sleep sem");
406            
407                  if(sleep_sem == 0)
408                  {
409            	 th->dereference_tsd();
410 kumpf 1.14          PEG_METHOD_EXIT();
411 mike  1.2  	 throw NullPointer();
412                  }
413 kumpf 1.14       Tracer::trace(TRC_THREAD, Tracer::LEVEL4, "Signal thread to awaken");
414 mike  1.2        sleep_sem->signal();
415                  th->dereference_tsd();
416               }
417               else
418                  _pool.insert_first(th);
419 kumpf 1.14 
420               PEG_METHOD_EXIT();
421 mike  1.2  }
422            
423            // caller is responsible for only calling this routine during slack periods
424            // but should call it at least once per _deadlock_detect with the running q
425            // and at least once per _deallocate_wait for the pool q
426            
427 mday  1.12 Uint32 ThreadPool::kill_dead_threads(void)
428 mike  1.2  	 throw(IPCException)
429            {
430               struct timeval now;
431               gettimeofday(&now, NULL);
432 mday  1.12    Uint32 bodies = 0;
433               
434 mike  1.2     // first go thread the dead q and clean it up as much as possible
435               while(_dead.count() > 0)
436               {
437 mday  1.30       PEGASUS_STD(cout) << "ThreadPool:: removing and joining dead thread" << PEGASUS_STD(endl);
438 mike  1.2        Thread *dead = _dead.remove_first();
439                  if(dead == 0)
440            	 throw NullPointer();
441 mday  1.30       dead->join();
442 mike  1.2        delete dead;
443               }
444 chip  1.11 
445               DQueue<Thread> * map[2] =
446 mike  1.2        {
447            	 &_pool, &_running
448                  };
449 chip  1.11 
450            
451 mike  1.2     DQueue<Thread> *q = 0;
452               int i = 0;
453               AtomicInt needed(0);
454 chip  1.11 
455 mday  1.26 
456 mday  1.30    for( ; i < 2; i++)
457 mday  1.21    { 
458                  q = map[i];
459 mike  1.2        if(q->count() > 0 )
460                  {
461 chip  1.11 	 try
462 mike  1.2  	 {
463            	    q->try_lock();
464            	 }
465 mday  1.18 	 catch(...)
466 mike  1.2  	 {
467 mday  1.18 	    return bodies;
468 mike  1.2  	 }
469            
470            	 struct timeval dt = { 0, 0 };
471            	 struct timeval *dtp;
472            	 Thread *th = 0;
473            	 th = q->next(th);
474            	 while (th != 0 )
475            	 {
476 chip  1.11 	    try
477 mike  1.2  	    {
478            	       dtp = (struct timeval *)th->try_reference_tsd("deadlock timer");
479            	    }
480 mday  1.18 	    catch(...)
481 mike  1.2  	    {
482 kumpf 1.25 	       q->unlock();
483 mday  1.18 	       return bodies;
484 mike  1.2  	    }
485 chip  1.11 	
486 mike  1.2  	    if(dtp != 0)
487            	    {
488            	       memcpy(&dt, dtp, sizeof(struct timeval));
489            	    }
490            	    th->dereference_tsd();
491            	    struct timeval deadlock_timeout;
492 mday  1.18 	    Boolean too_long;
493            	    if( i == 0)
494            	    {
495            	       too_long = check_time(&dt, get_deallocate_wait(&deadlock_timeout));
496            	    }
497            	    else 
498            	    {
499 mday  1.22 	       too_long = check_time(&dt, get_deadlock_detect(&deadlock_timeout));
500 mday  1.18 	    }
501            	    
502            	    if( true == too_long)
503 mike  1.2  	    {
504            	       // if we are deallocating from the pool, escape if we are
505 chip  1.11 	       // down to the minimum thread count
506 mday  1.13 	       _current_threads--;
507 mday  1.18 	       if( _current_threads.value() < (Uint32)_min_threads )
508 mike  1.2  	       {
509 mday  1.13 		  if( i == 0)
510 mike  1.2  		  {
511 mday  1.13 		     _current_threads++;
512 mike  1.2  		     th = q->next(th);
513            		     continue;
514            		  }
515 chip  1.11 		  else
516 mike  1.2  		  {
517 chip  1.11 		     // we are killing a hung thread and we will drop below the
518 mike  1.2  		     // minimum. create another thread to make up for the one
519            		     // we are about to kill
520            		     needed++;
521            		  }
522            	       }
523 chip  1.11 	
524 mike  1.2  	       th = q->remove_no_lock((void *)th);
525 chip  1.11 	
526 mike  1.2  	       if(th != 0)
527            	       {
528 mday  1.30 		  if( i == 0 )
529 mike  1.2  		  {
530 mday  1.30 		     th->delete_tsd("work func");
531            		     th->put_tsd("work func", NULL,
532            				 sizeof( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *)(void *)),
533            				 (void *)&_undertaker);
534            		     th->delete_tsd("work parm");
535            		     th->put_tsd("work parm", NULL, sizeof(void *), th);
536            		     
537            		     // signal the thread's sleep semaphore to awaken it
538            		     Semaphore *sleep_sem = (Semaphore *)th->reference_tsd("sleep sem");
539            		     
540            		     if(sleep_sem == 0)
541            		     {
542            			q->unlock();
543            			th->dereference_tsd();
544            			throw NullPointer();
545            		     }
546            		     
547            		     bodies++;
548 mike  1.2  		     th->dereference_tsd();
549 mday  1.30 		     _dead.insert_first(th);
550            		     sleep_sem->signal();
551            		     th = 0;
552            		  }
553            		  else 
554            		  {
555            		     // deadlocked threads
556            		     PEGASUS_STD(cout) << "Killing a deadlocked thread" << PEGASUS_STD(endl);
557            		     th->cancel();
558            		     delete th;
559 mike  1.2  		  }
560            	       }
561            	    }
562            	    th = q->next(th);
563 mday  1.20 	    pegasus_sleep(1);
564 mike  1.2  	 }
565            	 q->unlock();
566            	 while (needed.value() > 0)
567            	 {
568            	    _link_pool(_init_thread());
569            	    needed--;
570 mday  1.20 	    pegasus_sleep(0);
571 mike  1.2  	 }
572                  }
573               }
574 mday  1.18     return bodies; 
575 mike  1.2  }
576            
577 mday  1.12 
578 mike  1.2  Boolean ThreadPool::check_time(struct timeval *start, struct timeval *interval)
579            {
580 mday  1.22    // never time out if the interval is zero
581               if(interval && interval->tv_sec == 0 && interval->tv_usec == 0)
582                  return false;
583               
584 mday  1.13    struct timeval now, finish, remaining;
585               Uint32 usec;
586 mike  1.2     gettimeofday(&now, NULL);
587 mday  1.13 
588               finish.tv_sec = start->tv_sec + interval->tv_sec;
589               usec = start->tv_usec + interval->tv_usec;
590               finish.tv_sec += (usec / 1000000);
591               usec %= 1000000;
592               finish.tv_usec = usec;
593                
594               if ( timeval_subtract(&remaining, &finish, &now) )
595 mike  1.2        return true;
596               else
597                  return false;
598            }
599            
600            PEGASUS_THREAD_RETURN ThreadPool::_undertaker( void *parm )
601            {
602 mday  1.30    exit_thread((PEGASUS_THREAD_RETURN)1);
603               return (PEGASUS_THREAD_RETURN)1;
604 mike  1.2  }
605 mday  1.19 
606            
607             void ThreadPool::_sleep_sem_del(void *p)
608            {
609               if(p != 0)
610               {
611                  delete (Semaphore *)p;
612               }
613            }
614            
615             void ThreadPool::_check_deadlock(struct timeval *start) throw(Deadlock)
616            {
617               if (true == check_time(start, &_deadlock_detect))
618                  throw Deadlock(pegasus_thread_self());
619               return;
620            }
621            
622            
623             Boolean ThreadPool::_check_deadlock_no_throw(struct timeval *start)
624            {
625               return(check_time(start, &_deadlock_detect));
626 mday  1.19 }
627            
628             Boolean ThreadPool::_check_dealloc(struct timeval *start)
629            {
630               return(check_time(start, &_deallocate_wait));
631            }
632            
633             Thread *ThreadPool::_init_thread(void) throw(IPCException)
634            {
635               Thread *th = (Thread *) new Thread(_loop, this, false);
636               // allocate a sleep semaphore and pass it in the thread context
637               // initial count is zero, loop function will sleep until
638               // we signal the semaphore
639               Semaphore *sleep_sem = (Semaphore *) new Semaphore(0);
640               th->put_tsd("sleep sem", &_sleep_sem_del, sizeof(Semaphore), (void *)sleep_sem);
641               
642               struct timeval *dldt = (struct timeval *) ::operator new(sizeof(struct timeval));
643               th->put_tsd("deadlock timer", thread_data::default_delete, sizeof(struct timeval), (void *)dldt);
644               // thread will enter _loop(void *) and sleep on sleep_sem until we signal it
645               th->run();
646               _current_threads++;
647 mday  1.19    pegasus_yield();
648               
649               return th;
650            }
651            
652             void ThreadPool::_link_pool(Thread *th) throw(IPCException)
653            {
654               if(th == 0)
655                  throw NullPointer();
656               _pool.insert_first(th);
657            }
658            
659 mike  1.2  
660            
661            PEGASUS_NAMESPACE_END
662            

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2