unsigned int ldap_pvt_thread_sleep( unsigned int interval ) { thread_t mylwp; tl_t *t, *nt; time_t now; if ( lwp_self( &mylwp ) < 0 ) { return -1; } time( &now ); mon_enter( &sglob->tsl_mon ); if ( sglob->tsl_list != NULL ) { for ( t = sglob->tsl_list; t != NULL; t = t->tl_next ) { if ( SAMETHREAD( t->tl_tid, mylwp )) { /* We're already sleeping? */ t->tl_wake = now + interval; mon_exit( &sglob->tsl_mon ); lwp_suspend( mylwp ); return 0; } } } nt = (tl_t *) LDAP_MALLOC( sizeof( tl_t )); if( nt == NULL ) return -1; nt->tl_next = sglob->tsl_list; nt->tl_wake = now + interval; nt->tl_tid = mylwp; sglob->tsl_list = nt; mon_exit( &sglob->tsl_mon ); lwp_suspend( mylwp ); return 0; }
int sys__lwp_suspend(struct lwp *l, const struct sys__lwp_suspend_args *uap, register_t *retval) { /* { syscallarg(lwpid_t) target; } */ struct proc *p = l->l_proc; struct lwp *t; int error; mutex_enter(p->p_lock); if ((t = lwp_find(p, SCARG(uap, target))) == NULL) { mutex_exit(p->p_lock); return ESRCH; } /* * Check for deadlock, which is only possible when we're suspending * ourself. XXX There is a short race here, as p_nrlwps is only * incremented when an LWP suspends itself on the kernel/user * boundary. It's still possible to kill -9 the process so we * don't bother checking further. */ lwp_lock(t); if ((t == l && p->p_nrlwps == 1) || (l->l_flag & (LW_WCORE | LW_WEXIT)) != 0) { lwp_unlock(t); mutex_exit(p->p_lock); return EDEADLK; } /* * Suspend the LWP. XXX If it's on a different CPU, we should wait * for it to be preempted, where it will put itself to sleep. * * Suspension of the current LWP will happen on return to userspace. */ error = lwp_suspend(l, t); if (error) { mutex_exit(p->p_lock); return error; } /* * Wait for: * o process exiting * o target LWP suspended * o target LWP not suspended and L_WSUSPEND clear * o target LWP exited */ for (;;) { error = cv_wait_sig(&p->p_lwpcv, p->p_lock); if (error) { error = ERESTART; break; } if (lwp_find(p, SCARG(uap, target)) == NULL) { error = ESRCH; break; } if ((l->l_flag | t->l_flag) & (LW_WCORE | LW_WEXIT)) { error = ERESTART; break; } if (t->l_stat == LSSUSPENDED || (t->l_flag & LW_WSUSPEND) == 0) break; } mutex_exit(p->p_lock); return error; }
int thr_suspend(int tid) { return( lwp_suspend(thread_table[tid] )); }