(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               if(sleep_sem == 0 || deadlock_timer == 0)
271 kumpf 1.14    {
272                  PEG_METHOD_EXIT();
273 mike  1.2        throw NullPointer();
274 kumpf 1.14    }
275 mike  1.2  
276               while(pool->_dying < 1)
277               {
278                  sleep_sem->wait();
279 mday  1.12         
280 mike  1.2        // when we awaken we reside on the running queue, not the pool queue
281                  if(pool->_dying > 0)
282            	 break;
283 chip  1.11 
284 mike  1.5        PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *_work)(void *) = 0;
285                  void *parm = 0;
286 mike  1.2  
287 chip  1.11       try
288 mike  1.2        {
289            	 _work = (PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *)(void *)) \
290            	    myself->reference_tsd("work func");
291            	 myself->dereference_tsd();
292            	 parm = myself->reference_tsd("work parm");
293            	 myself->dereference_tsd();
294 mday  1.13 	 blocking_sem = (Semaphore *)myself->reference_tsd("blocking sem");
295            	 myself->dereference_tsd();
296            
297 mike  1.2        }
298 mike  1.6        catch(IPCException &)
299 mike  1.2        {
300 kumpf 1.14 	 PEG_METHOD_EXIT();
301 mike  1.2  	 myself->exit_self(0);
302                  }
303 chip  1.11 
304 mike  1.2        if(_work == 0)
305 kumpf 1.14       {
306                     PEG_METHOD_EXIT();
307 mike  1.2  	 throw NullPointer();
308 kumpf 1.14       }
309 mike  1.2        gettimeofday(deadlock_timer, NULL);
310 mday  1.20       try 
311                  {
312            	 _work(parm);
313                  }
314                  catch(...)
315                  {
316            	 gettimeofday(deadlock_timer, NULL);
317                  }
318                  gettimeofday(deadlock_timer, NULL);
319 mday  1.13       if( blocking_sem != 0 )
320            	 blocking_sem->signal();
321                  
322 chip  1.11       // put myself back onto the available list
323                  try
324 mike  1.2        {
325            	 pool->_running.remove((void *)myself);
326            	 pool->_link_pool(myself);
327                  }
328 mike  1.6        catch(IPCException &)
329 mike  1.2        {
330 kumpf 1.14 	 PEG_METHOD_EXIT();
331 mike  1.2  	 myself->exit_self(0);
332                  }
333 mday  1.29.2.1       
334 mike  1.2         }
335                   // wait to be awakend by the thread pool destructor
336                   sleep_sem->wait();
337                   myself->test_cancel();
338 kumpf 1.14     
339                   PEG_METHOD_EXIT();
340 mike  1.2         myself->exit_self(0);
341                   return((PEGASUS_THREAD_RETURN)0);
342                }
343                
344                void ThreadPool::allocate_and_awaken(void *parm,
345                				     PEGASUS_THREAD_RETURN \
346 mday  1.13     				     (PEGASUS_THREAD_CDECL *work)(void *), 
347                				     Semaphore *blocking)
348                
349 mike  1.2         throw(IPCException)
350                {
351 kumpf 1.14        PEG_METHOD_ENTER(TRC_THREAD, "ThreadPool::allocate_and_awaken");
352 mike  1.2         struct timeval start;
353                   gettimeofday(&start, NULL);
354 chip  1.11     
355 mike  1.2         Thread *th = _pool.remove_first();
356 mday  1.12        
357 mday  1.7         // wait for the right interval and try again
358                   while(th == 0 && _dying < 1)
359 mike  1.2         {
360 mday  1.12           _check_deadlock(&start) ;
361                      
362 mday  1.21           if(_max_threads == 0 || _current_threads < _max_threads)
363 mike  1.2            {
364 mday  1.12     	 th = _init_thread();
365                	 continue;
366 mike  1.2            }
367 mday  1.12           pegasus_yield();
368 mday  1.7            th = _pool.remove_first();
369                   }
370 chip  1.11     
371                
372 mike  1.2         if(_dying < 1)
373                   {
374                      // initialize the thread data with the work function and parameters
375 kumpf 1.14           Tracer::trace(TRC_THREAD, Tracer::LEVEL4,
376                          "Initializing thread with work function and parameters: parm = %p",
377                          parm);
378                
379 kumpf 1.15           th->delete_tsd("work func");
380 chip  1.11           th->put_tsd("work func", NULL,
381 mike  1.2      		  sizeof( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *)(void *)),
382                		  (void *)work);
383 kumpf 1.15           th->delete_tsd("work parm");
384 mike  1.2            th->put_tsd("work parm", NULL, sizeof(void *), parm);
385 kumpf 1.15           th->delete_tsd("blocking sem");
386 mday  1.13           if(blocking != 0 )
387                	 th->put_tsd("blocking sem", NULL, sizeof(Semaphore *), blocking);
388                      
389 chip  1.11           // put the thread on the running list
390 mike  1.2            _running.insert_first(th);
391                
392                      // signal the thread's sleep semaphore to awaken it
393                      Semaphore *sleep_sem = (Semaphore *)th->reference_tsd("sleep sem");
394                
395                      if(sleep_sem == 0)
396                      {
397                	 th->dereference_tsd();
398 kumpf 1.14              PEG_METHOD_EXIT();
399 mike  1.2      	 throw NullPointer();
400                      }
401 kumpf 1.14           Tracer::trace(TRC_THREAD, Tracer::LEVEL4, "Signal thread to awaken");
402 mike  1.2            sleep_sem->signal();
403                      th->dereference_tsd();
404                   }
405                   else
406                      _pool.insert_first(th);
407 kumpf 1.14     
408                   PEG_METHOD_EXIT();
409 mike  1.2      }
410                
411                // caller is responsible for only calling this routine during slack periods
412                // but should call it at least once per _deadlock_detect with the running q
413                // and at least once per _deallocate_wait for the pool q
414                
415 mday  1.12     Uint32 ThreadPool::kill_dead_threads(void)
416 mike  1.2      	 throw(IPCException)
417                {
418                   struct timeval now;
419                   gettimeofday(&now, NULL);
420 mday  1.12        Uint32 bodies = 0;
421                   
422 mike  1.2         // first go thread the dead q and clean it up as much as possible
423                   while(_dead.count() > 0)
424                   {
425                      Thread *dead = _dead.remove_first();
426                      if(dead == 0)
427                	 throw NullPointer();
428                      if(dead->_handle.thid != 0)
429                      {
430                	 dead->detach();
431                	 destroy_thread(dead->_handle.thid, 0);
432                	 dead->_handle.thid = 0;
433                	 while(dead->_cleanup.count() )
434                	 {
435 chip  1.11     	    // this may throw a permission exception,
436 mike  1.2      	    // which I will remove from the code prior to stabilizing
437                	    dead->cleanup_pop(true);
438                	 }
439                      }
440                      delete dead;
441 mday  1.20           pegasus_sleep(1);
442 mike  1.2         }
443 chip  1.11     
444                   DQueue<Thread> * map[2] =
445 mike  1.2            {
446                	 &_pool, &_running
447                      };
448 chip  1.11     
449                
450 mike  1.2         DQueue<Thread> *q = 0;
451                   int i = 0;
452                   AtomicInt needed(0);
453 chip  1.11     
454 mday  1.29.2.1    for( ; i < 2; i++)
455 mday  1.21        { 
456                      q = map[i];
457 mike  1.2            if(q->count() > 0 )
458                      {
459 chip  1.11     	 try
460 mike  1.2      	 {
461                	    q->try_lock();
462                	 }
463 mday  1.18     	 catch(...)
464 mike  1.2      	 {
465 mday  1.18     	    return bodies;
466 mike  1.2      	 }
467                
468                	 struct timeval dt = { 0, 0 };
469                	 struct timeval *dtp;
470                	 Thread *th = 0;
471                	 th = q->next(th);
472                	 while (th != 0 )
473                	 {
474 chip  1.11     	    try
475 mike  1.2      	    {
476                	       dtp = (struct timeval *)th->try_reference_tsd("deadlock timer");
477                	    }
478 mday  1.18     	    catch(...)
479 mike  1.2      	    {
480 mday  1.18     	       return bodies;
481 mike  1.2      	    }
482 chip  1.11     	
483 mike  1.2      	    if(dtp != 0)
484                	    {
485                	       memcpy(&dt, dtp, sizeof(struct timeval));
486                	    }
487                	    th->dereference_tsd();
488                	    struct timeval deadlock_timeout;
489 mday  1.18     	    Boolean too_long;
490                	    if( i == 0)
491                	    {
492                	       too_long = check_time(&dt, get_deallocate_wait(&deadlock_timeout));
493                	    }
494                	    else 
495                	    {
496 mday  1.22     	       too_long = check_time(&dt, get_deadlock_detect(&deadlock_timeout));
497 mday  1.18     	    }
498                	    
499                	    if( true == too_long)
500 mike  1.2      	    {
501                	       // if we are deallocating from the pool, escape if we are
502 chip  1.11     	       // down to the minimum thread count
503 mday  1.13     	       _current_threads--;
504 mday  1.18     	       if( _current_threads.value() < (Uint32)_min_threads )
505 mike  1.2      	       {
506 mday  1.13     		  if( i == 0)
507 mike  1.2      		  {
508 mday  1.13     		     _current_threads++;
509 mike  1.2      		     th = q->next(th);
510                		     continue;
511                		  }
512 chip  1.11     		  else
513 mike  1.2      		  {
514 chip  1.11     		     // we are killing a hung thread and we will drop below the
515 mike  1.2      		     // minimum. create another thread to make up for the one
516                		     // we are about to kill
517                		     needed++;
518                		  }
519                	       }
520 chip  1.11     	
521 mike  1.2      	       th = q->remove_no_lock((void *)th);
522 chip  1.11     	
523 mike  1.2      	       if(th != 0)
524                	       {
525 mday  1.18     		  
526 kumpf 1.15     		  th->delete_tsd("work func");
527 chip  1.11     		  th->put_tsd("work func", NULL,
528 mike  1.2      			      sizeof( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *)(void *)),
529                			      (void *)&_undertaker);
530 kumpf 1.15     		  th->delete_tsd("work parm");
531 mike  1.2      		  th->put_tsd("work parm", NULL, sizeof(void *), th);
532 chip  1.11     	
533 mike  1.2      		  // signal the thread's sleep semaphore to awaken it
534                		  Semaphore *sleep_sem = (Semaphore *)th->reference_tsd("sleep sem");
535 chip  1.11     	
536 mike  1.2      		  if(sleep_sem == 0)
537                		  {
538                		     th->dereference_tsd();
539                		     throw NullPointer();
540                		  }
541 mday  1.18     		  
542 chip  1.11     		  // put the thread on the dead  list
543 kumpf 1.28     		  _dead.insert_first(th);
544 mday  1.12     		  bodies++;
545 chip  1.11     		  sleep_sem->signal();
546 mday  1.13     		  
547 mike  1.2      		  th->dereference_tsd();
548                		  th = 0;
549                	       }
550                	    }
551                	    th = q->next(th);
552 mday  1.20     	    pegasus_sleep(1);
553 mike  1.2      	 }
554                	 q->unlock();
555                	 while (needed.value() > 0)
556                	 {
557                	    _link_pool(_init_thread());
558                	    needed--;
559 mday  1.20     	    pegasus_sleep(0);
560 mike  1.2      	 }
561                      }
562                   }
563 mday  1.18         return bodies; 
564 mike  1.2      }
565                
566 mday  1.12     
567 mike  1.2      Boolean ThreadPool::check_time(struct timeval *start, struct timeval *interval)
568                {
569 mday  1.22        // never time out if the interval is zero
570                   if(interval && interval->tv_sec == 0 && interval->tv_usec == 0)
571                      return false;
572                   
573 mday  1.13        struct timeval now, finish, remaining;
574                   Uint32 usec;
575 mike  1.2         gettimeofday(&now, NULL);
576 mday  1.13     
577                   finish.tv_sec = start->tv_sec + interval->tv_sec;
578                   usec = start->tv_usec + interval->tv_usec;
579                   finish.tv_sec += (usec / 1000000);
580                   usec %= 1000000;
581                   finish.tv_usec = usec;
582                    
583                   if ( timeval_subtract(&remaining, &finish, &now) )
584 mike  1.2            return true;
585                   else
586                      return false;
587                }
588                
589                
590                PEGASUS_THREAD_RETURN ThreadPool::_undertaker( void *parm )
591                {
592                   Thread *myself = reinterpret_cast<Thread *>(parm);
593                   if(myself != 0)
594                   {
595                      myself->detach();
596                      myself->_handle.thid = 0;
597                      myself->cancel();
598 kumpf 1.28           myself->test_cancel();
599                      myself->exit_self(0);
600 mike  1.2         }
601                   return((PEGASUS_THREAD_RETURN)0);
602                }
603 mday  1.19     
604                
605                 void ThreadPool::_sleep_sem_del(void *p)
606                {
607                   if(p != 0)
608                   {
609                      delete (Semaphore *)p;
610                   }
611                }
612                
613                 void ThreadPool::_check_deadlock(struct timeval *start) throw(Deadlock)
614                {
615                   if (true == check_time(start, &_deadlock_detect))
616                      throw Deadlock(pegasus_thread_self());
617                   return;
618                }
619                
620                
621                 Boolean ThreadPool::_check_deadlock_no_throw(struct timeval *start)
622                {
623                   return(check_time(start, &_deadlock_detect));
624 mday  1.19     }
625                
626                 Boolean ThreadPool::_check_dealloc(struct timeval *start)
627                {
628                   return(check_time(start, &_deallocate_wait));
629                }
630                
631                 Thread *ThreadPool::_init_thread(void) throw(IPCException)
632                {
633                   Thread *th = (Thread *) new Thread(_loop, this, false);
634                   // allocate a sleep semaphore and pass it in the thread context
635                   // initial count is zero, loop function will sleep until
636                   // we signal the semaphore
637                   Semaphore *sleep_sem = (Semaphore *) new Semaphore(0);
638                   th->put_tsd("sleep sem", &_sleep_sem_del, sizeof(Semaphore), (void *)sleep_sem);
639                   
640                   struct timeval *dldt = (struct timeval *) ::operator new(sizeof(struct timeval));
641                   th->put_tsd("deadlock timer", thread_data::default_delete, sizeof(struct timeval), (void *)dldt);
642                   // thread will enter _loop(void *) and sleep on sleep_sem until we signal it
643                   th->run();
644                   _current_threads++;
645 mday  1.19        pegasus_yield();
646                   
647                   return th;
648                }
649                
650                 void ThreadPool::_link_pool(Thread *th) throw(IPCException)
651                {
652                   if(th == 0)
653                      throw NullPointer();
654                   _pool.insert_first(th);
655                }
656                
657 mike  1.2      
658                
659                PEGASUS_NAMESPACE_END
660                

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2