2 * Copyright (c) 1996 Regents of the University of Michigan.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of Michigan at Ann Arbor. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
14 * tsleep.c - allow a thread to sleep without putting the whole process
15 * (e.g. pod under lwp) to sleep. Contains platform-specific code to
18 * Under non-preemptive threads packages like SunOS lwp, tsleep() adds
19 * the thread to a list of sleepers. The lwp_scheduler process takes
20 * care of resuming suspended threads.
22 * Under a fully-preemptive threads package, like Solaris threads,
23 * tsleep just calls sleep(), and there is no scheduler thread. Life
24 * is so much simpler...
33 #if defined( THREAD_SUNOS4_LWP )
35 extern stkalign_t *get_stack( int * );
36 extern void free_stack( int );
48 if ( lwp_self( &mylwp ) < 0 ) {
53 mon_enter( &sglob->tsl_mon );
54 if ( sglob->tsl_list != NULL ) {
55 for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
56 if ( SAMETHREAD( t->tl_tid, mylwp )) {
57 /* We're already sleeping? */
58 t->tl_wake = now + (time_t) interval;
59 mon_exit( &sglob->tsl_mon );
65 nt = (tl_t *) malloc( sizeof( tl_t ));
67 nt->tl_next = sglob->tsl_list;
68 nt->tl_wake = now + (time_t) interval;
71 mon_exit( &sglob->tsl_mon );
77 * The lwp_scheduler thread periodically checks to see if any threads
78 * are due to be resumed. If there are, it resumes them. Otherwise,
79 * it computes the lesser of ( 1 second ) or ( the minimum time until
80 * a thread need to be resumed ) and puts itself to sleep for that amount
89 struct timeval interval;
92 while ( !sglob->slurpd_shutdown ) {
93 mon_enter( &sglob->tsl_mon );
96 if ( sglob->tsl_list != NULL ) {
97 for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
98 if (( t->tl_wake > 0L ) && ( t->tl_wake < now )) {
99 lwp_resume( t->tl_tid );
102 if (( t->tl_wake > now ) && ( t->tl_wake < min )) {
107 mon_exit( &sglob->tsl_mon );
108 interval.tv_usec = 0L;
110 interval.tv_sec = 1L;
112 interval.tv_sec = min;
114 lwp_sleep( &interval );
116 mon_enter( &sglob->tsl_mon );
117 for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) {
118 lwp_resume( t->tl_tid );
120 mon_exit( &sglob->tsl_mon );
121 free_stack( stackno );
126 * Create the lwp_scheduler thread.
129 start_lwp_scheduler()
135 if (( stack = get_stack( &stackno )) == NULL ) {
138 lwp_create( &tid, lwp_scheduler, MINPRIO, 0, stack, 1, stackno );
143 #else /* THREAD_SUNOS4_LWP */
146 * Here we assume we have fully preemptive threads, and that sleep()
147 * does the right thing.
156 #endif /* THREAD_SUNOS4_LWP */